diff options
author | Samba Release Account <samba-bugs@samba.org> | 1997-08-20 20:32:23 +0000 |
---|---|---|
committer | Samba Release Account <samba-bugs@samba.org> | 1997-08-20 20:32:23 +0000 |
commit | 46dbd8c06009ad9e64251ae844fb16f2a30f5ab7 (patch) | |
tree | b3665c4cdda6e60c2e85218f6778213817b4210f /source3 | |
parent | c76dc7c2963d1205cf46849df6b6f0edbf63692d (diff) | |
download | samba-46dbd8c06009ad9e64251ae844fb16f2a30f5ab7.tar.gz samba-46dbd8c06009ad9e64251ae844fb16f2a30f5ab7.tar.bz2 samba-46dbd8c06009ad9e64251ae844fb16f2a30f5ab7.zip |
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" <chris@fast-ag.de>.
Jeremy (jallison@whistle.com)
(This used to be commit 28b3c6db8a81b41b448a4f3cd98e9cd2c4b5fb2e)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/proto.h | 2 | ||||
-rw-r--r-- | source3/include/smb.h | 6 | ||||
-rw-r--r-- | source3/lib/util.c | 7 | ||||
-rw-r--r-- | source3/smbd/pipes.c | 11 | ||||
-rw-r--r-- | source3/smbd/reply.c | 239 | ||||
-rw-r--r-- | source3/smbd/server.c | 25 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 70 |
7 files changed, 297 insertions, 63 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 56bdbfe865..f716c1f9a9 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -691,7 +691,7 @@ void killkids(void); mode_t unix_mode(int cnum,int dosmode); int dos_mode(int cnum,char *path,struct stat *sbuf); int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st); -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); int disk_free(char *path,int *bsize,int *dfree,int *dsize); int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize); BOOL check_name(char *name,int cnum); diff --git a/source3/include/smb.h b/source3/include/smb.h index 0f2dc01865..1dbe04abc8 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -175,14 +175,15 @@ implemented */ #define ERRbadshare 32 /* Share mode on file conflict with open mode */ #define ERRlock 33 /* Lock request conflicts with existing lock */ #define ERRfilexists 80 /* File in operation already exists */ +#define ERRunknownlevel 124 #define ERRbadpipe 230 /* Named pipe invalid */ #define ERRpipebusy 231 /* All instances of pipe are busy */ #define ERRpipeclosing 232 /* named pipe close in progress */ #define ERRnotconnected 233 /* No process on other end of named pipe */ #define ERRmoredata 234 /* More data to be returned */ +#define ERRbaddirectory 267 /* Invalid directory name in a path. */ #define ERROR_EAS_DIDNT_FIT 275 /* Extended attributes didn't fit */ #define ERROR_EAS_NOT_SUPPORTED 282 /* Extended attributes not suppored */ -#define ERRunknownlevel 124 #define ERRunknownipc 2142 @@ -928,4 +929,7 @@ enum case_handling {CASE_LOWER,CASE_UPPER}; /* Size of buffer to use when moving files across filesystems. */ #define COPYBUF_SIZE (8*1024) +/* Integers used to override error codes. */ +extern int unix_ERR_class; +extern int unix_ERR_code; /* _SMB_H */ diff --git a/source3/lib/util.c b/source3/lib/util.c index ca17fbdcb4..a048c8b3a7 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -755,12 +755,17 @@ time_t file_modtime(char *fname) BOOL directory_exist(char *dname,struct stat *st) { struct stat st2; + BOOL ret; + if (!st) st = &st2; if (sys_stat(dname,st) != 0) return(False); - return(S_ISDIR(st->st_mode)); + ret = S_ISDIR(st->st_mode); + if(!ret) + errno = ENOTDIR; + return ret; } /******************************************************************* 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)); } |