source: vendor/current/source3/smbd/error.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 6.0 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 error packet handling
4 Copyright (C) Andrew Tridgell 1992-1998
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include "includes.h"
21#include "smbd/smbd.h"
22#include "smbd/globals.h"
23
24bool use_nt_status(void)
25{
26 return lp_nt_status_support() && (global_client_caps & CAP_STATUS32);
27}
28
29/****************************************************************************
30 Create an error packet. Normally called using the ERROR() macro.
31
32 Setting eclass and ecode to zero and status to a valid NT error will
33 reply with an NT error if the client supports CAP_STATUS32, otherwise
34 it maps to and returns a DOS error if the client doesn't support CAP_STATUS32.
35 This is the normal mode of calling this function via reply_nterror(req, status).
36
37 Setting eclass and ecode to non-zero and status to NT_STATUS_OK (0) will map
38 from a DOS error to an NT error and reply with an NT error if the client
39 supports CAP_STATUS32, otherwise it replies with the given DOS error.
40 This mode is currently not used in the server.
41
42 Setting both eclass, ecode and status to non-zero values allows a non-default
43 mapping from NT error codes to DOS error codes, and will return one or the
44 other depending on the client supporting CAP_STATUS32 or not. This is the
45 path taken by calling reply_botherror(req, eclass, ecode, status);
46
47 Setting status to NT_STATUS_DOS(eclass, ecode) forces DOS errors even if the
48 client supports CAP_STATUS32. This is the path taken to force a DOS error
49 reply by calling reply_force_doserror(req, eclass, ecode).
50
51 Setting status only and eclass to -1 forces NT errors even if the client
52 doesn't support CAP_STATUS32. This mode is currently never used in the
53 server.
54****************************************************************************/
55
56void error_packet_set(char *outbuf, uint8_t eclass, uint32_t ecode, NTSTATUS ntstatus, int line, const char *file)
57{
58 bool force_nt_status = False;
59 bool force_dos_status = False;
60
61 if (eclass == (uint8_t)-1) {
62 force_nt_status = True;
63 } else if (NT_STATUS_IS_DOS(ntstatus)) {
64 force_dos_status = True;
65 }
66
67 if (force_nt_status || (!force_dos_status && lp_nt_status_support() && (global_client_caps & CAP_STATUS32))) {
68 /* We're returning an NT error. */
69 if (NT_STATUS_V(ntstatus) == 0 && eclass) {
70 ntstatus = dos_to_ntstatus(eclass, ecode);
71 }
72 SIVAL(outbuf,smb_rcls,NT_STATUS_V(ntstatus));
73 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES);
74 /* This must not start with the word 'error', as this
75 * is reserved in the subunit stream protocol, causing
76 * false errors to show up when debugging is turned
77 * on */
78 DEBUG(3,("NT error packet at %s(%d) cmd=%d (%s) %s\n",
79 file, line,
80 (int)CVAL(outbuf,smb_com),
81 smb_fn_name(CVAL(outbuf,smb_com)),
82 nt_errstr(ntstatus)));
83 } else {
84 /* We're returning a DOS error only,
85 * nt_status_to_dos() pulls DOS error codes out of the
86 * NTSTATUS */
87 if (NT_STATUS_IS_DOS(ntstatus) || (eclass == 0 && NT_STATUS_V(ntstatus))) {
88 ntstatus_to_dos(ntstatus, &eclass, &ecode);
89 }
90
91 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES);
92 SSVAL(outbuf,smb_rcls,eclass);
93 SSVAL(outbuf,smb_err,ecode);
94
95 /* This must not start with the word 'error', as this
96 * is reserved in the subunit stream protocol, causing
97 * false errors to show up when debugging is turned
98 * on */
99 DEBUG(3,("DOS error packet at %s(%d) cmd=%d (%s) eclass=%d ecode=%d\n",
100 file, line,
101 (int)CVAL(outbuf,smb_com),
102 smb_fn_name(CVAL(outbuf,smb_com)),
103 eclass,
104 ecode));
105 }
106}
107
108int error_packet(char *outbuf, uint8_t eclass, uint32_t ecode, NTSTATUS ntstatus, int line, const char *file)
109{
110 int outsize = srv_set_message(outbuf,0,0,True);
111 error_packet_set(outbuf, eclass, ecode, ntstatus, line, file);
112 return outsize;
113}
114
115void reply_nt_error(struct smb_request *req, NTSTATUS ntstatus,
116 int line, const char *file)
117{
118 TALLOC_FREE(req->outbuf);
119 reply_outbuf(req, 0, 0);
120 error_packet_set((char *)req->outbuf, 0, 0, ntstatus, line, file);
121}
122
123/****************************************************************************
124 Forces a DOS error on the wire.
125****************************************************************************/
126
127void reply_force_dos_error(struct smb_request *req, uint8_t eclass, uint32_t ecode,
128 int line, const char *file)
129{
130 TALLOC_FREE(req->outbuf);
131 reply_outbuf(req, 0, 0);
132 error_packet_set((char *)req->outbuf,
133 eclass, ecode,
134 NT_STATUS_DOS(eclass, ecode),
135 line,
136 file);
137}
138
139void reply_both_error(struct smb_request *req, uint8_t eclass, uint32_t ecode,
140 NTSTATUS status, int line, const char *file)
141{
142 TALLOC_FREE(req->outbuf);
143 reply_outbuf(req, 0, 0);
144 error_packet_set((char *)req->outbuf, eclass, ecode, status,
145 line, file);
146}
147
148void reply_openerror(struct smb_request *req, NTSTATUS status)
149{
150 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
151 /*
152 * We hit an existing file, and if we're returning DOS
153 * error codes OBJECT_NAME_COLLISION would map to
154 * ERRDOS/183, we need to return ERRDOS/80, see bug
155 * 4852.
156 */
157 reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION,
158 ERRDOS, ERRfilexists);
159 } else if (NT_STATUS_EQUAL(status, NT_STATUS_TOO_MANY_OPENED_FILES)) {
160 /* EMFILE always seems to be returned as a DOS error.
161 * See bug 6837. NOTE this forces a DOS error on the wire
162 * even though it's calling reply_nterror(). */
163 reply_force_doserror(req, ERRDOS, ERRnofids);
164 } else {
165 reply_nterror(req, status);
166 }
167}
Note: See TracBrowser for help on using the repository browser.