s3-net: use new rpccli_spoolss_enumforms wrapper.
[ira/wip.git] / source3 / smbd / error.c
index 6988d74f91e276e4df5f65fd7bb952c0fceffa21..ce22f86414b385b7ff6faa0630e04aa21b83f137 100644 (file)
@@ -5,7 +5,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "smbd/globals.h"
 
 /* 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;
-
-/****************************************************************************
- 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 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)
-{
-       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));
-}
-
-/****************************************************************************
- Create an error packet from a cached error.
-****************************************************************************/
-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);
-}
-
-/****************************************************************************
- 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)
+bool use_nt_status(void)
 {
-       int eclass=def_class;
-       int ecode=def_code;
-       NTSTATUS ntstatus = def_status;
-       int i=0;
-
-       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;
-                               ecode = unix_dos_nt_errmap[i].dos_code;
-                               ntstatus = unix_dos_nt_errmap[i].nt_error;
-                               break;
-                       }
-                       i++;
-               }
-       }
-
-       return error_packet(outbuf,eclass,ecode,ntstatus,line,file);
+       return lp_nt_status_support() && (global_client_caps & CAP_STATUS32);
 }
 
-
 /****************************************************************************
  Create an error packet. Normally called using the ERROR() macro.
  Setting eclass and ecode only and status to NT_STATUS_OK forces DOS errors.
@@ -111,25 +35,14 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_s
  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)
+void error_packet_set(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;
-       }
+       bool force_nt_status = False;
+       bool force_dos_status = False;
 
        if (eclass == (uint8)-1) {
                force_nt_status = True;
-       } else if (NT_STATUS_IS_INVALID(ntstatus)) {
+       } else if (NT_STATUS_IS_DOS(ntstatus)) {
                force_dos_status = True;
        }
 
@@ -147,7 +60,10 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in
                         nt_errstr(ntstatus)));
        } else {
                /* We're returning a DOS error only. */
-               if (eclass == 0 && NT_STATUS_V(ntstatus)) {
+               if (NT_STATUS_IS_DOS(ntstatus)) {
+                       eclass = NT_STATUS_DOS_CLASS(ntstatus);
+                       ecode = NT_STATUS_DOS_CODE(ntstatus);
+               } else  if (eclass == 0 && NT_STATUS_V(ntstatus)) {
                        ntstatus_to_dos(ntstatus, &eclass, &ecode);
                }
 
@@ -162,6 +78,91 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in
                          eclass,
                          ecode));
        }
+}
 
+int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
+{
+       int outsize = srv_set_message(outbuf,0,0,True);
+       error_packet_set(outbuf, eclass, ecode, ntstatus, line, file);
        return outsize;
 }
+
+void reply_nt_error(struct smb_request *req, NTSTATUS ntstatus,
+                   int line, const char *file)
+{
+       TALLOC_FREE(req->outbuf);
+       reply_outbuf(req, 0, 0);
+       error_packet_set((char *)req->outbuf, 0, 0, ntstatus, line, file);
+}
+
+void reply_force_nt_error(struct smb_request *req, NTSTATUS ntstatus,
+                         int line, const char *file)
+{
+       TALLOC_FREE(req->outbuf);
+       reply_outbuf(req, 0, 0);
+       error_packet_set((char *)req->outbuf, -1, -1, ntstatus, line, file);
+}
+
+void reply_dos_error(struct smb_request *req, uint8 eclass, uint32 ecode,
+                   int line, const char *file)
+{
+       TALLOC_FREE(req->outbuf);
+       reply_outbuf(req, 0, 0);
+       error_packet_set((char *)req->outbuf, eclass, ecode, NT_STATUS_OK, line,
+                        file);
+}
+
+void reply_both_error(struct smb_request *req, uint8 eclass, uint32 ecode,
+                     NTSTATUS status, int line, const char *file)
+{
+       TALLOC_FREE(req->outbuf);
+       reply_outbuf(req, 0, 0);
+       error_packet_set((char *)req->outbuf, eclass, ecode, status,
+                        line, file);
+}
+
+void reply_openerror(struct smb_request *req, NTSTATUS status)
+{
+       if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+               /*
+                * We hit an existing file, and if we're returning DOS
+                * error codes OBJECT_NAME_COLLISION would map to
+                * ERRDOS/183, we need to return ERRDOS/80, see bug
+                * 4852.
+                */
+               reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION,
+                       ERRDOS, ERRfilexists);
+       } else {
+               reply_nterror(req, status);
+       }
+}
+
+void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode,
+                       NTSTATUS defstatus, int line, const char *file)
+{
+       int eclass=defclass;
+       int ecode=defcode;
+       NTSTATUS ntstatus = defstatus;
+       int i=0;
+
+       TALLOC_FREE(req->outbuf);
+       reply_outbuf(req, 0, 0);
+
+       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;
+                               ecode = unix_dos_nt_errmap[i].dos_code;
+                               ntstatus = unix_dos_nt_errmap[i].nt_error;
+                               break;
+                       }
+                       i++;
+               }
+       }
+
+       error_packet_set((char *)req->outbuf, eclass, ecode, ntstatus,
+               line, file);
+}