diff options
Diffstat (limited to 'source/smbd/error.c')
-rw-r--r-- | source/smbd/error.c | 145 |
1 files changed, 63 insertions, 82 deletions
diff --git a/source/smbd/error.c b/source/smbd/error.c index 090a2f6d813..d611e0ef873 100644 --- a/source/smbd/error.c +++ b/source/smbd/error.c @@ -20,44 +20,23 @@ #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[]; -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 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. + Ensure we don't have any errors cached. ****************************************************************************/ -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) +void clear_cached_errors(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)); + unix_ERR_class = SMB_SUCCESS; + unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; } /**************************************************************************** @@ -67,29 +46,36 @@ BOOL get_saved_error_triple(int *peclass, int *pecode, NTSTATUS *pstatus) 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 */ - SAFE_FREE(fsp->wbmpx_ptr); - return error_packet(outbuf,eclass,err,ntstatus,line,file); + free((char *)wbmpx); + fsp->wbmpx_ptr = NULL; + return error_packet(outbuf,NT_STATUS_OK,eclass,err,False,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(char *outbuf,int def_class,uint32 def_code, + int line, const char *file) { int eclass=def_class; int ecode=def_code; - NTSTATUS ntstatus = def_status; + NTSTATUS ntstatus = NT_STATUS_OK; int i=0; - if (errno != 0) { - DEBUG(3,("unix_error_packet: error string = %s\n",strerror(errno))); - + 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) { eclass = unix_dos_nt_errmap[i].dos_class; @@ -101,43 +87,39 @@ 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(outbuf,ntstatus,eclass,ecode,False,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, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) +int error_packet(char *outbuf,NTSTATUS ntstatus, + uint8 eclass,uint32 ecode,BOOL force_dos, int line, const char *file) { int outsize = set_message(outbuf,0,0,True); - 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; - } + extern uint32 global_client_caps; - 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) { + 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) 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", @@ -145,23 +127,22 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in (int)CVAL(outbuf,smb_com), smb_fn_name(CVAL(outbuf,smb_com)), nt_errstr(ntstatus))); - } 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; + } + + 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; } |