2 Unix SMB/Netbios implementation.
4 SMB NT transaction handling
5 Copyright (C) Jeremy Allison 1994-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern int DEBUGLEVEL;
26 extern connection_struct Connections[];
27 extern files_struct Files[];
29 extern int oplock_sock;
30 extern int smb_read_error;
31 extern int global_oplock_break;
33 static char *known_nt_pipes[] = {
46 /****************************************************************************
47 reply to an NT create and X call.
48 ****************************************************************************/
50 THIS IS JUST CRIBBED FROM REPLY.C AT PRESENT AND IS A WORK
53 int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
56 int cnum = SVAL(inbuf,smb_tid);
58 int smb_mode = SVAL(inbuf,smb_vwv3);
59 int smb_attr = SVAL(inbuf,smb_vwv5);
60 /* Breakout the oplock request bits so we can set the
61 reply bits separately. */
62 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
63 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
64 BOOL oplock_request = ex_oplock_request | core_oplock_request;
66 int open_flags = SVAL(inbuf,smb_vwv2);
67 int smb_sattr = SVAL(inbuf,smb_vwv4);
68 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
70 int smb_ofun = SVAL(inbuf,smb_vwv8);
72 int size=0,fmode=0,mtime=0,rmode=0;
75 BOOL bad_path = False;
78 /* If it's an IPC, pass off the pipe handler. */
80 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
82 /* XXXX we need to handle passed times, sattr and flags */
84 pstrcpy(fname,smb_buf(inbuf));
85 unix_convert(fname,cnum,0,&bad_path);
87 fnum = find_free_file();
89 return(ERROR(ERRSRV,ERRnofids));
90 if (!check_name(fname,cnum))
92 if((errno == ENOENT) && bad_path)
94 unix_ERR_class = ERRDOS;
95 unix_ERR_code = ERRbadpath;
97 Files[fnum].reserved = False;
98 return(UNIXERROR(ERRDOS,ERRnoaccess));
101 unixmode = unix_mode(cnum,smb_attr | aARCH);
103 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
104 oplock_request, &rmode,&smb_action);
110 if((errno == ENOENT) && bad_path)
112 unix_ERR_class = ERRDOS;
113 unix_ERR_code = ERRbadpath;
115 Files[fnum].reserved = False;
116 return(UNIXERROR(ERRDOS,ERRnoaccess));
119 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
120 close_file(fnum,False);
121 return(ERROR(ERRDOS,ERRnoaccess));
125 fmode = dos_mode(cnum,fname,&sbuf);
126 mtime = sbuf.st_mtime;
128 close_file(fnum,False);
129 return(ERROR(ERRDOS,ERRnoaccess));
132 /* If the caller set the extended oplock request bit
133 and we granted one (by whatever means) - set the
134 correct bit for extended oplock reply.
137 if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
138 smb_action |= EXTENDED_OPLOCK_GRANTED;
141 if(ex_oplock_request && fsp->granted_oplock) {
142 smb_action |= EXTENDED_OPLOCK_GRANTED;
145 /* If the caller set the core oplock request bit
146 and we granted one (by whatever means) - set the
147 correct bit for core oplock reply.
150 if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
151 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
154 if(core_oplock_request && fsp->granted_oplock) {
155 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
158 set_message(outbuf,15,0,True);
159 SSVAL(outbuf,smb_vwv2,fnum);
160 SSVAL(outbuf,smb_vwv3,fmode);
161 if(lp_dos_filetime_resolution(SNUM(cnum)) )
162 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
164 put_dos_date3(outbuf,smb_vwv4,mtime);
165 SIVAL(outbuf,smb_vwv6,size);
166 SSVAL(outbuf,smb_vwv8,rmode);
167 SSVAL(outbuf,smb_vwv11,smb_action);
171 return chain_reply(inbuf,outbuf,length,bufsize);
174 /****************************************************************************
175 reply to an unsolicited SMBNTtranss - just ignore it!
176 ****************************************************************************/
178 int reply_nttranss(char *inbuf,char *outbuf,int length,int bufsize)
180 DEBUG(4,("Ignoring nttranss of length %d\n",length));
184 /****************************************************************************
185 reply to a SMBNTtrans
186 ****************************************************************************/
188 int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize)
191 int cnum = SVAL(inbuf,smb_tid);
193 uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount);
194 uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount);
195 uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
197 uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount);
198 uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount);
199 uint32 parameter_count = IVAL(inbuf,smb_nt_ParameterCount);
200 uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset);
201 uint32 data_count = IVAL(inbuf,smb_nt_DataCount);
202 uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset);
203 uint16 setup_count = SVAL(inbuf,smb_nt_SetupCount);
204 uint16 function_code = SVAL( inbuf, smb_nt_Function);
205 char *params = NULL, *data = NULL, *setup = NULL;
206 uint32 num_params_sofar, num_data_sofar;
208 if(global_oplock_break && (function_code == NT_TRANSACT_CREATE)) {
210 * Queue this open message as we are the process of an oplock break.
213 DEBUG(2,("%s: reply_nttrans: queueing message NT_TRANSACT_CREATE \
214 due to being in oplock break state.\n", timestring() ));
216 push_smb_message( inbuf, length);
220 outsize = set_message(outbuf,0,0,True);
223 * All nttrans messages we handle have smb_wcnt == 19 + setup_count.
224 * Ensure this is so as a sanity check.
227 if(CVAL(inbuf, smb_wcnt) != 19 + setup_count) {
228 DEBUG(2,("Invalid smb_wcnt in trans2 call\n"));
229 return(ERROR(ERRSRV,ERRerror));
232 /* Allocate the space for the setup, the maximum needed parameters and data */
235 setup = (char *)malloc(setup_count);
236 if (total_parameter_count > 0)
237 params = (char *)malloc(total_parameter_count);
238 if (total_data_count > 0)
239 data = (char *)malloc(total_data_count);
241 if ((total_parameter_count && !params) || (total_data_count && !data) ||
242 (setup_count && !setup)) {
243 DEBUG(0,("reply_nttrans : Out of memory\n"));
244 return(ERROR(ERRDOS,ERRnomem));
247 /* Copy the param and data bytes sent with this request into
249 num_params_sofar = parameter_count;
250 num_data_sofar = data_count;
252 if (parameter_count > total_parameter_count || data_count > total_data_count)
253 exit_server("reply_nttrans: invalid sizes in packet.\n");
256 memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
258 memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
260 memcpy( data, smb_base(inbuf) + data_offset, data_count);
262 if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
263 /* We need to send an interim response then receive the rest
264 of the parameter/data bytes */
265 outsize = set_message(outbuf,0,0,True);
266 send_smb(Client,outbuf);
268 while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
271 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
274 if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
275 outsize = set_message(outbuf,0,0,True);
277 DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
279 DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
280 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
287 return(ERROR(ERRSRV,ERRerror));
290 /* Revise total_params and total_data in case they have changed downwards */
291 total_parameter_count = SIVAL(inbuf, smb_nts_TotalParameterCount);
292 total_data_count = SIVAL(inbuf, smb_nts_TotalDataCount);
293 num_params_sofar += (parameter_count = SIVAL(inbuf,smb_nts_ParameterCount));
294 num_data_sofar += ( data_count = SIVAL(inbuf, smb_nts_DataCount));
295 if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count)
296 exit_server("reply_nttrans2: data overflow in secondary nttrans packet\n");
298 memcpy( ¶ms[ SIVAL(inbuf, smb_nts_ParameterDisplacement)],
299 smb_base(inbuf) + SVAL(inbuf, smb_nts_ParameterOffset), parameter_count);
300 memcpy( &data[SVAL(inbuf, smb_nts_DataDisplacement)],
301 smb_base(inbuf)+ SVAL(inbuf, smb_nts_DataOffset), data_count);
305 if (Protocol >= PROTOCOL_NT1) {
306 uint16 flg2 = SVAL(outbuf,smb_flg2);
307 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
310 /* Now we must call the relevant NT_TRANS function */
311 switch(function_code) {
312 case NT_TRANSACT_CREATE:
313 outsize = call_nt_transact_create(inbuf, outbuf, bufsize, cnum,
314 &setup, ¶ms, &data);
316 case NT_TRANSACT_IOCTL:
317 outsize = call_nt_transact_ioctl(inbuf, outbuf, bufsize, cnum,
318 &setup, ¶ms, &data);
320 case NT_TRANSACT_SET_SECURITY_DESC:
321 outsize = call_nt_transact_set_security_desc(inbuf, outbuf, length, bufsize, cnum,
322 &setup, ¶ms, &data);
324 case NT_TRANSACT_NOTIFY_CHANGE:
325 outsize = call_nt_transact_notify_change(inbuf, outbuf, length, bufsize, cnum,
326 &setup, ¶ms, &data);
328 case NT_TRANSACT_RENAME:
329 outsize = call_nt_transact_rename(inbuf, outbuf, length, bufsize, cnum,
330 &setup, ¶ms, &data);
332 case NT_TRANSACT_QUERY_SECURITY_DESC:
333 outsize = call_nt_transact_query_security_desc(inbuf, outbuf, length, bufsize, cnum,
334 &setup, ¶ms, &data, total_data);
337 /* Error in request */
338 DEBUG(0,("reply_nttrans: %s Unknown request %d in nttrans call\n",timestring(),
346 return (ERROR(ERRSRV,ERRerror));
349 /* As we do not know how many data packets will need to be
350 returned here the various call_nt_transact_xxxx calls
351 must send their own. Thus a call_nt_transact_xxxx routine only
352 returns a value other than -1 when it wants to send
362 return outsize; /* If a correct response was needed the call_nt_transact_xxxx
363 calls have already sent it. If outsize != -1 then it is
364 returning an error packet. */