diff options
-rw-r--r-- | source3/include/nt_status.h | 1 | ||||
-rw-r--r-- | source3/include/nterr.h | 3 | ||||
-rw-r--r-- | source3/include/smb.h | 23 | ||||
-rw-r--r-- | source3/include/smb_macros.h | 23 | ||||
-rw-r--r-- | source3/smbd/error.c | 143 | ||||
-rw-r--r-- | source3/smbd/files.c | 6 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 32 | ||||
-rw-r--r-- | source3/smbd/open.c | 101 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 3 | ||||
-rw-r--r-- | source3/smbd/process.c | 3 | ||||
-rw-r--r-- | source3/smbd/reply.c | 78 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 1 |
12 files changed, 186 insertions, 231 deletions
diff --git a/source3/include/nt_status.h b/source3/include/nt_status.h index 9747f73eb1..ab768258df 100644 --- a/source3/include/nt_status.h +++ b/source3/include/nt_status.h @@ -56,6 +56,7 @@ typedef uint32 WERROR; #define NT_STATUS_IS_OK(x) (NT_STATUS_V(x) == 0) #define NT_STATUS_IS_ERR(x) ((NT_STATUS_V(x) & 0xc0000000) == 0xc0000000) +#define NT_STATUS_IS_INVALID(x) (NT_STATUS_V(x) == 0xFFFFFFFF) #define NT_STATUS_EQUAL(x,y) (NT_STATUS_V(x) == NT_STATUS_V(y)) #define W_ERROR_IS_OK(x) (W_ERROR_V(x) == 0) #define W_ERROR_EQUAL(x,y) (W_ERROR_V(x) == W_ERROR_V(y)) diff --git a/source3/include/nterr.h b/source3/include/nterr.h index 6cf5a756d2..417719625e 100644 --- a/source3/include/nterr.h +++ b/source3/include/nterr.h @@ -37,6 +37,9 @@ #define STATUS_NOTIFY_ENUM_DIR NT_STATUS(0x010c) #define ERROR_INVALID_DATATYPE NT_STATUS(0x070c) +/* Special "invalid" NT status code. */ +#define NT_STATUS_INVALID NT_STATUS(0xFFFFFFFF) + /* Win32 Error codes extracted using a loop in smbclient then printing a netmon sniff to a file. */ diff --git a/source3/include/smb.h b/source3/include/smb.h index efa74436ee..d12459c2f9 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -357,14 +357,14 @@ typedef struct time_info } UTIME; /* Structure used when SMBwritebmpx is active */ -typedef struct -{ - size_t wr_total_written; /* So we know when to discard this */ - int32 wr_timeout; - int32 wr_errclass; - int32 wr_error; /* Cached errors */ - BOOL wr_mode; /* write through mode) */ - BOOL wr_discard; /* discard all further data */ +typedef struct { + size_t wr_total_written; /* So we know when to discard this */ + int32 wr_timeout; + int32 wr_errclass; /* Cached errors */ + int32 wr_error; /* Cached errors */ + NTSTATUS wr_status; /* Cached errors */ + BOOL wr_mode; /* write through mode) */ + BOOL wr_discard; /* discard all further data */ } write_bmpx_struct; typedef struct write_cache @@ -1384,13 +1384,6 @@ enum case_handling {CASE_LOWER,CASE_UPPER}; */ #define COPYBUF_SIZE (8*1024) -/* - * Values used to override error codes. - */ -extern int unix_ERR_class; -extern int unix_ERR_code; -extern NTSTATUS unix_ERR_ntstatus; - /* * Used in chaining code. */ diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h index 2b3140783b..e19c51884f 100644 --- a/source3/include/smb_macros.h +++ b/source3/include/smb_macros.h @@ -97,9 +97,6 @@ #define CHECK_WRITE(fsp) if (!(fsp)->can_write) \ return(ERROR_DOS(ERRDOS,ERRbadaccess)) -#define CHECK_ERROR(fsp) if (HAS_CACHED_ERROR(fsp)) \ - return(CACHED_ERROR(fsp)) - #define ERROR_WAS_LOCK_DENIED(status) (NT_STATUS_EQUAL((status), NT_STATUS_LOCK_NOT_GRANTED) || \ NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT) ) @@ -158,25 +155,23 @@ #define SMB_LARGE_LKLEN_OFFSET_HIGH(indx) (12 + (20 * (indx))) #define SMB_LARGE_LKLEN_OFFSET_LOW(indx) (16 + (20 * (indx))) -/* Macro to cache an error in a write_bmpx_struct */ -#define CACHE_ERROR(w,c,e) ((w)->wr_errclass = (c), (w)->wr_error = (e), \ - w->wr_discard = True, -1) /* Macro to test if an error has been cached for this fnum */ #define HAS_CACHED_ERROR(fsp) ((fsp)->wbmpx_ptr && \ (fsp)->wbmpx_ptr->wr_discard) /* Macro to turn the cached error into an error packet */ #define CACHED_ERROR(fsp) cached_error_packet(outbuf,fsp,__LINE__,__FILE__) -/* these are the datagram types */ -#define DGRAM_DIRECT_UNIQUE 0x10 - -#define ERROR_DOS(class,code) error_packet(outbuf,NT_STATUS_OK,class,code,False,__LINE__,__FILE__) -#define ERROR_FORCE_DOS(class,code) error_packet(outbuf,NT_STATUS_OK,class,code,True,__LINE__,__FILE__) -#define ERROR_NT(status) error_packet(outbuf,status,0,0,False,__LINE__,__FILE__) -#define ERROR_BOTH(status,class,code) error_packet(outbuf,status,class,code,False,__LINE__,__FILE__) +#define ERROR_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_OK,__LINE__,__FILE__) +#define ERROR_FORCE_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_INVALID,__LINE__,__FILE__) +#define ERROR_NT(status) error_packet(outbuf,0,0,status,__LINE__,__FILE__) +#define ERROR_FORCE_NT(status) error_packet(outbuf,-1,-1,status,__LINE__,__FILE__) +#define ERROR_BOTH(status,class,code) error_packet(outbuf,class,code,status,__LINE__,__FILE__) /* this is how errors are generated */ -#define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,__LINE__,__FILE__) +#define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,NT_STATUS_OK,__LINE__,__FILE__) + +/* these are the datagram types */ +#define DGRAM_DIRECT_UNIQUE 0x10 #define SMB_ROUNDUP(x,r) ( ((x)%(r)) ? ( (((x)+(r))/(r))*(r) ) : (x)) 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); |