summaryrefslogtreecommitdiffstats
path: root/source/smbd/error.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/smbd/error.c')
-rw-r--r--source/smbd/error.c145
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;
}