diff options
-rw-r--r-- | source3/include/proto.h | 16 | ||||
-rw-r--r-- | source3/include/smb.h | 3 | ||||
-rw-r--r-- | source3/lib/util.c | 138 | ||||
-rw-r--r-- | source3/param/loadparm.c | 11 | ||||
-rw-r--r-- | source3/smbd/chgpasswd.c | 2 | ||||
-rw-r--r-- | source3/smbd/dir.c | 28 | ||||
-rw-r--r-- | source3/smbd/reply.c | 14 | ||||
-rw-r--r-- | source3/smbd/server.c | 21 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 2 |
9 files changed, 130 insertions, 105 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 8aecf7907a..aae5b3a63b 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -73,13 +73,13 @@ void dptr_closecnum(int cnum); void dptr_idlecnum(int cnum); void dptr_closepath(char *path,int pid); int dptr_create(int cnum,char *path, BOOL expect_close,int pid); -BOOL dptr_fill(char *buf1,unsigned int key); +BOOL dptr_fill(int snum, char *buf1,unsigned int key); BOOL dptr_zero(char *buf); -void *dptr_fetch(char *buf,int *num); -void *dptr_fetch_lanman2(char *params,int dptr_num); +void *dptr_fetch(int snum, char *buf,int *num); +void *dptr_fetch_lanman2(int snum, char *params,int dptr_num); BOOL dir_check_ftype(int cnum,int mode,struct stat *st,int dirtype); BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend); -void *OpenDir(char *name, BOOL use_veto); +void *OpenDir(int snum, char *name, BOOL use_veto); void CloseDir(void *p); char *ReadDirName(void *p); BOOL SeekDir(void *p,int pos); @@ -141,7 +141,6 @@ char *lp_username_map(void); char *lp_character_set(void); char *lp_logon_script(void); char *lp_logon_path(void); -char *lp_veto_files(void); char *lp_remote_announce(void); char *lp_wins_server(void); char *lp_interfaces(void); @@ -219,6 +218,8 @@ char *lp_readlist(int ); char *lp_writelist(int ); char *lp_volume(int ); char *lp_mangled_map(int ); +char *lp_veto_files(int ); +char *lp_hide_files(int ); BOOL lp_alternate_permissions(int ); BOOL lp_revalidate(int ); BOOL lp_casesensitive(int ); @@ -948,8 +949,9 @@ char *gidtoname(int gid); void BlockSignals(BOOL block,int signum); void ajt_panic(void); char *readdirname(void *p); -BOOL is_vetoed_name(char *name); -BOOL is_vetoed_path(char *name); +BOOL is_hidden_path(int snum, char *name); +BOOL is_vetoed_name(int snum, char *name); +BOOL is_in_path(char *name, char *namelist); BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type); int file_lock(char *name,int timeout); void file_unlock(int fd); diff --git a/source3/include/smb.h b/source3/include/smb.h index ddbd05792d..d4ad9105fe 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -915,4 +915,7 @@ enum case_handling {CASE_LOWER,CASE_UPPER}; /* Size of buffer to use when moving files across filesystems. */ #define COPYBUF_SIZE (8*1024) +/* service-based parameter - files are not visible, but are accessible */ +#define DEFAULT_FILES_TO_HIDE "*/.*" + /* _SMB_H */ diff --git a/source3/lib/util.c b/source3/lib/util.c index 31cb4d6629..0ee6947d09 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -3433,99 +3433,95 @@ char *readdirname(void *p) } -BOOL is_vetoed_name(char *name) +BOOL is_hidden_path(int snum, char *name) { - char *namelist = lp_veto_files(); - char *nameptr = namelist; - char *name_end; - - /* if we have no list it's obviously not vetoed */ - if((nameptr == NULL ) || (*nameptr == '\0')) - return 0; - - /* if the name doesn't exist in the list, it's obviously ok too */ - if(strstr(namelist,name) == NULL ) - return 0; + return is_in_path(name, lp_hide_files(snum)); +} - /* now, we need to find the names one by one and check them - they can contain spaces and all sorts of stuff so we - separate them with of all things '/' which can never be in a filename - I could use "" but then I have to break them all out - maybe such a routine exists somewhere? - */ - while(*nameptr) - { - if ( *nameptr == '/' ) - { - nameptr++; - continue; - } - if((name_end = strchr(nameptr,'/'))!=NULL) - { - *name_end = 0; - } - /* a match! it's veto'd */ - if(strcmp(name,nameptr) == 0) - return 1; - if(name_end == NULL) - return 0; - /* next segment please */ - nameptr = name_end + 1; - } - return 0; +BOOL is_vetoed_name(int snum, char *name) +{ + return is_in_path(name, lp_veto_files(snum)); } -BOOL is_vetoed_path(char *name) +BOOL is_in_path(char *name, char *namelist) { - char *namelist = lp_veto_files(); + char *nameptr = namelist; - char *sub; char *name_end; - int len; - /* if we have no list it's obviously not vetoed */ - if((nameptr == NULL ) || (*nameptr == '\0')) - return 0; + DEBUG(5, ("is_in_path: %s list: %s\n", name, namelist)); + /* if we have no list it's obviously not in the path */ + if((nameptr == NULL ) || (*nameptr == '\0')) + { + DEBUG(5,("is_in_path: no name list. return False\n")); + return False; + } /* now, we need to find the names one by one and check them they can contain spaces and all sorts of stuff so we - separate them with of all things '/' which can never be in a filename + separate them with of all things '\' which can never be in a filename I could use "" but then I have to break them all out maybe such a routine exists somewhere? */ - while(*nameptr) + + /* lkcl 03jul97 - the separator character used to be a '/'. + i changed it to a '\', after examining the code, and seeing + that unix_convert is called before check_path and dos_mode. + unix_convert changes, in the path, all dos '\'s to unix '/'s. + + therefore, users might want to match against '/'s in the path, + and therefore '\' must be used as the separator. + + the alternatives are: + + 1) move all check_path and dos_mode calls to before the + unix_convert calls. + + 2) have a corresponding dos_convert call, which can be used + in here to reverse '/'s into '\'s and vice-versa. users + would specify the lp_veto_files and lp_hide_files parameters + in dos mode path format ('\' for directory separator), with a + list separator of '/', and they would be swapped inside this + function, before making the search. + + */ + + while (*nameptr) { - if ( *nameptr == '/' ) - { + if ( *nameptr == '\\' ) + { + /* cope with multiple (useless) \s) */ nameptr++; continue; - } - if((name_end = strchr(nameptr,'/'))!=NULL) - { + } + /* find the next \ */ + if ((name_end = strchr(nameptr,'\\')) != NULL) + { *name_end = 0; - } - - len = strlen(nameptr); - sub = name; - /* If the name doesn't exist in the path, try the next name.. */ - while( sub && ((sub = strstr(sub,nameptr)) != NULL)) - { - /* Is it a whole component? */ - if(((sub == name) || (sub[-1] == '/')) - && ((sub[len] == '\0') || (sub[len] == '/'))) - { - return 1; - } - /* skip to the next component of the path */ - sub =strchr(sub,'/'); - } - if(name_end == NULL) - return 0; + } + + /* look for a match. */ + if (mask_match(name, nameptr, case_sensitive, False)) + { + DEBUG(5,("is_in_path: mask match succeeded\n")); + return True; + } + + /* oops - the last check for a \ didn't find one. */ + if (name_end == NULL) + { + DEBUG(5,("is_in_path: last name. failed\n")); + return False; + } + /* next segment please */ nameptr = name_end + 1; } - return 0; + + DEBUG(5,("is_in_path: not found\n")); + + return False; } /**************************************************************************** diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 4c6ce30b19..dbe711eac6 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -129,7 +129,6 @@ typedef struct char *szCharacterSet; char *szLogonScript; char *szLogonPath; - char *szVetoFiles; char *szSmbrun; char *szWINSserver; char *szInterfaces; @@ -214,6 +213,8 @@ typedef struct char *szMagicScript; char *szMagicOutput; char *szMangledMap; + char *szVetoFiles; + char *szHideFiles; char *comment; char *force_user; char *force_group; @@ -291,6 +292,8 @@ static service sDefault = NULL, /* szMagicScript */ NULL, /* szMagicOutput */ NULL, /* szMangledMap */ + NULL, /* szVetoFiles */ + DEFAULT_FILES_TO_HIDE, /* szVetoFiles */ NULL, /* comment */ NULL, /* force user */ NULL, /* force group */ @@ -395,7 +398,6 @@ struct parm_struct {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL}, {"netbios name", P_UGSTRING,P_GLOBAL, myname, NULL}, {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL}, - {"veto files", P_STRING, P_GLOBAL, &Globals.szVetoFiles, NULL}, {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL}, {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL}, {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL}, @@ -509,6 +511,8 @@ struct parm_struct {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL}, {"status", P_BOOL, P_LOCAL, &sDefault.status, NULL}, {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL}, + {"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL}, + {"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL}, {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL}, {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL}, {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL}, @@ -810,7 +814,6 @@ FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap) FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet) FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript) FN_GLOBAL_STRING(lp_logon_path,&Globals.szLogonPath) -FN_GLOBAL_STRING(lp_veto_files,&Globals.szVetoFiles) FN_GLOBAL_STRING(lp_remote_announce,&Globals.szRemoteAnnounce) FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver) FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces) @@ -891,6 +894,8 @@ FN_LOCAL_STRING(lp_readlist,readlist) FN_LOCAL_STRING(lp_writelist,writelist) FN_LOCAL_STRING(lp_volume,volume) FN_LOCAL_STRING(lp_mangled_map,szMangledMap) +FN_LOCAL_STRING(lp_veto_files,szVetoFiles) +FN_LOCAL_STRING(lp_hide_files,szHideFiles) FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm) FN_LOCAL_BOOL(lp_revalidate,bRevalidate) 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)); |