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 int chain_fnum;
27 extern connection_struct Connections[];
28 extern files_struct Files[];
30 extern int oplock_sock;
31 extern int smb_read_error;
32 extern int global_oplock_break;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
37 static char *known_nt_pipes[] = {
50 /****************************************************************************
52 ****************************************************************************/
54 static BOOL saved_case_sensitive;
55 static BOOL saved_case_preserve;
56 static BOOL saved_short_case_preserve;
58 /****************************************************************************
60 ****************************************************************************/
62 static void set_posix_case_semantics(uint32 file_attributes)
64 if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS))
67 saved_case_sensitive = case_sensitive;
68 saved_case_preserve = case_preserve;
69 saved_short_case_preserve = short_case_preserve;
72 case_sensitive = True;
74 short_case_preserve = True;
77 /****************************************************************************
78 Restore case semantics.
79 ****************************************************************************/
81 static void restore_case_semantics(uint32 file_attributes)
83 if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS))
86 case_sensitive = saved_case_sensitive;
87 case_preserve = saved_case_preserve;
88 short_case_preserve = saved_short_case_preserve;
91 /****************************************************************************
92 Utility function to map create disposition.
93 ****************************************************************************/
95 static int map_create_disposition( uint32 create_disposition)
97 switch( create_disposition ) {
99 /* create if not exist, fail if exist */
102 /* create if not exist, trunc if exist */
105 /* fail if not exist, open if exists */
108 /* create if not exist, open if exists */
110 case TRUNCATE_EXISTING:
111 /* fail if not exist, truncate if exists */
114 DEBUG(0,("map_create_disposition: Incorrect value for create_disposition = %d\n",
115 create_disposition ));
120 /****************************************************************************
121 Utility function to map share modes.
122 ****************************************************************************/
124 static int map_share_mode( uint32 desired_access, uint32 share_access)
128 switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA) ) {
132 case FILE_WRITE_DATA:
135 case FILE_READ_DATA|FILE_WRITE_DATA:
139 DEBUG(0,("map_share_mode: Incorrect value for desired_access = %x\n",
144 /* Add in the requested share mode - ignore FILE_SHARE_DELETE for now. */
145 switch( share_access & (FILE_SHARE_READ|FILE_SHARE_WRITE)) {
146 case FILE_SHARE_READ:
147 smb_open_mode |= (DENY_WRITE<<4);
149 case FILE_SHARE_WRITE:
150 smb_open_mode |= (DENY_READ<<4);
152 case (FILE_SHARE_READ|FILE_SHARE_WRITE):
153 smb_open_mode |= (DENY_NONE<<4);
155 case FILE_SHARE_NONE:
156 smb_open_mode |= (DENY_ALL<<4);
161 * Handle a O_SYNC request.
163 if(file_attributes & FILE_FLAG_WRITE_THROUGH)
164 smb_open_mode |= (1<<14);
166 return smb_open_mode;
169 /****************************************************************************
170 Reply to an NT create and X call on a pipe.
171 ****************************************************************************/
173 static int nt_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
176 int cnum = SVAL(inbuf,smb_tid);
178 uint16 vuid = SVAL(inbuf, smb_uid);
179 uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
180 uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess);
181 uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
182 uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
183 uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
184 uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)),
185 ((uint32)sizeof(fname)-1));
188 int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
190 int fmode=0,mtime=0,rmode=0;
194 BOOL bad_path = False;
198 StrnCpy(fname,smb_buf(inbuf),fname_len);
200 DEBUG(4,("nt_open_pipe_and_X: Opening pipe %s.\n", fname));
202 /* See if it is one we want to handle. */
203 for( i = 0; known_nt_pipes[i]; i++ )
204 if( strequal(fname,known_nt_pipes[i]))
207 if ( known_nt_pipes[i] == NULL )
208 return(ERROR(ERRSRV,ERRaccess));
210 /* Strip \\ off the name. */
213 /* Known pipes arrive with DIR attribs. Remove it so a regular file */
214 /* can be opened and add it in after the open. */
215 DEBUG(3,("nt_open_pipe_and_X: Known pipe %s opening.\n",p));
217 if((smb_ofun = map_create_disposition( create_disposition )) == -1)
218 return(ERROR(ERRDOS,ERRbadaccess));
219 smb_ofun |= 0x10; /* Add Create it not exists flag */
221 pnum = open_rpc_pipe_hnd(p, cnum, vuid);
223 return(ERROR(ERRSRV,ERRnofids));
226 /****************************************************************************
227 Reply to an NT create and X call.
228 ****************************************************************************/
230 int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
233 int cnum = SVAL(inbuf,smb_tid);
235 uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
236 uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess);
237 uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
238 uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
239 uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
240 uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)),
241 ((uint32)sizeof(fname)-1));
244 int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
245 /* Breakout the oplock request bits so we can set the
246 reply bits separately. */
247 int oplock_request = flags & (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
249 int fmode=0,mtime=0,rmode=0;
253 BOOL bad_path = False;
257 /* If it's an IPC, pass off the pipe handler. */
259 return nt_open_pipe_and_X(inbuf,outbuf,length,bufsize);
261 /* If it's a request for a directory open, fail it. */
262 if(flags & OPEN_DIRECTORY)
263 return(ERROR(ERRDOS,ERRnoaccess));
266 * We need to construct the open_and_X ofun value from the
267 * NT values, as that's what our code is structured to accept.
270 if((smb_ofun = map_create_disposition( create_disposition )) == -1)
271 return(ERROR(ERRDOS,ERRbadaccess));
274 * Now contruct the smb_open_mode value from the desired access
275 * and the share access.
278 if((smb_open_mode = map_share_mode( desired_access, share_access)) == -1)
279 return(ERROR(ERRDOS,ERRbadaccess));
282 * Check if POSIX semantics are wanted.
285 set_posix_case_semantics(file_attributes);
287 StrnCpy(fname,smb_buf(inbuf),fname_len);
288 unix_convert(fname,cnum,0,&bad_path);
290 fnum = find_free_file();
292 restore_case_semantics(file_attributes);
293 return(ERROR(ERRSRV,ERRnofids));
296 if (!check_name(fname,cnum)) {
297 if((errno == ENOENT) && bad_path) {
298 unix_ERR_class = ERRDOS;
299 unix_ERR_code = ERRbadpath;
301 Files[fnum].reserved = False;
303 restore_case_semantics(file_attributes);
305 return(UNIXERROR(ERRDOS,ERRnoaccess));
308 unixmode = unix_mode(cnum,smb_attr | aARCH);
310 open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode,
311 oplock_request,&rmode,&smb_action);
316 if((errno == ENOENT) && bad_path) {
317 unix_ERR_class = ERRDOS;
318 unix_ERR_code = ERRbadpath;
320 Files[fnum].reserved = False;
322 restore_case_semantics(file_attributes);
324 return(UNIXERROR(ERRDOS,ERRnoaccess));
327 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
328 close_file(fnum,False);
330 restore_case_semantics(file_attributes);
332 return(ERROR(ERRDOS,ERRnoaccess));
335 restore_case_semantics(file_attributes);
338 fmode = dos_mode(cnum,fname,&sbuf);
339 mtime = sbuf.st_mtime;
341 close_file(fnum,False);
342 return(ERROR(ERRDOS,ERRnoaccess));
345 /* If the caller set the extended oplock request bit
346 and we granted one (by whatever means) - set the
347 correct bit for extended oplock reply.
350 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
351 smb_action |= EXTENDED_OPLOCK_GRANTED;
354 if(oplock_request && fsp->granted_oplock) {
355 smb_action |= EXTENDED_OPLOCK_GRANTED;
358 set_message(outbuf,34,0,True);
360 p = outbuf + smb_vwv2;
363 * Currently as we don't support level II oplocks we just report
364 * exclusive & batch here.
367 SCVAL(p,0, (smb_action & EXTENDED_OPLOCK_GRANTED ? 3 : 0));
371 SIVAL(p,0,smb_action);
375 put_long_date(p,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
377 put_long_date(p,sbuf.st_atime); /* access time */
379 put_long_date(p,sbuf.st_mtime); /* write time */
381 put_long_date(p,sbuf.st_mtime); /* change time */
383 SIVAL(p,0,fmode); /* File Attributes. */
385 SIVAL(p,0, size & 0xFFFFFFFF);
386 SIVAL(p,4, (size >> 32));
390 return chain_reply(inbuf,outbuf,length,bufsize);
393 /****************************************************************************
394 Reply to a NT_TRANSACT_CREATE call (needs to process SD's).
395 ****************************************************************************/
397 static int call_nt_transact_create(char *inbuf, char *outbuf, int bufsize, int cnum,
398 char **setup, char **params, char **data)
402 char *params = *pparams;
403 uint32 flags = IVAL(params,0);
404 uint32 desired_access = IVAL(params,8);
405 uint32 file_attributes = IVAL(params,20);
406 uint32 share_access = IVAL(params,24);
407 uint32 create_disposition = IVAL(params,28);
408 uint32 fname_len = MIN(((uint32)IVAL(params,44)),
409 ((uint32)sizeof(fname)-1));
412 int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
414 /* If it's a request for a directory open, fail it. */
415 if(flags & OPEN_DIRECTORY)
416 return(ERROR(ERRDOS,ERRnoaccess));
419 * We need to construct the open_and_X ofun value from the
420 * NT values, as that's what our code is structured to accept.
423 if((smb_ofun = map_create_disposition( create_disposition )) == -1)
424 return(ERROR(ERRDOS,ERRbadaccess));
427 * Now contruct the smb_open_mode value from the desired access
428 * and the share access.
431 if((smb_open_mode = map_share_mode( desired_access, share_access)) == -1)
432 return(ERROR(ERRDOS,ERRbadaccess));
435 * Check if POSIX semantics are wanted.
438 set_posix_case_semantics(file_attributes);
440 StrnCpy(fname,params+53,fname_len);
441 unix_convert(fname,cnum,0,&bad_path);
443 fnum = find_free_file();
445 restore_case_semantics(file_attributes);
446 return(ERROR(ERRSRV,ERRnofids));
449 if (!check_name(fname,cnum)) {
450 if((errno == ENOENT) && bad_path) {
451 unix_ERR_class = ERRDOS;
452 unix_ERR_code = ERRbadpath;
454 Files[fnum].reserved = False;
456 restore_case_semantics(file_attributes);
458 return(UNIXERROR(ERRDOS,ERRnoaccess));
461 unixmode = unix_mode(cnum,smb_attr | aARCH);
463 open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode,
464 oplock_request,&rmode,&smb_action);
469 if((errno == ENOENT) && bad_path) {
470 unix_ERR_class = ERRDOS;
471 unix_ERR_code = ERRbadpath;
473 Files[fnum].reserved = False;
475 restore_case_semantics(file_attributes);
477 return(UNIXERROR(ERRDOS,ERRnoaccess));
480 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
481 close_file(fnum,False);
483 restore_case_semantics(file_attributes);
485 return(ERROR(ERRDOS,ERRnoaccess));
488 restore_case_semantics(file_attributes);
491 fmode = dos_mode(cnum,fname,&sbuf);
492 mtime = sbuf.st_mtime;
494 close_file(fnum,False);
495 return(ERROR(ERRDOS,ERRnoaccess));
498 /* If the caller set the extended oplock request bit
499 and we granted one (by whatever means) - set the
500 correct bit for extended oplock reply.
503 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
504 smb_action |= EXTENDED_OPLOCK_GRANTED;
507 if(oplock_request && fsp->granted_oplock) {
508 smb_action |= EXTENDED_OPLOCK_GRANTED;
513 /****************************************************************************
514 Reply to a NT CANCEL request - just ignore it.
515 ****************************************************************************/
517 int reply_ntcancel(char *inbuf,char *outbuf,int length,int bufsize)
519 DEBUG(4,("Ignoring ntcancel of length %d\n",length));
523 /****************************************************************************
524 Reply to an unsolicited SMBNTtranss - just ignore it!
525 ****************************************************************************/
527 int reply_nttranss(char *inbuf,char *outbuf,int length,int bufsize)
529 DEBUG(4,("Ignoring nttranss of length %d\n",length));
533 /****************************************************************************
534 Reply to an NT transact rename command.
535 ****************************************************************************/
537 static int call_nt_transact_rename(char *inbuf, char *outbuf, int bufsize, int cnum,
538 char **setup, char **params, char **data)
540 char *params = *pparams;
542 int fnum = SVAL(params, 0);
543 uint16 rename_flags = SVAL(params,2);
544 uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount);
545 uint32 fname_len = MIN((((uint32)IVAL(inbuf,smb_nt_TotalParameterCount)-4)),
546 ((uint32)sizeof(fname)-1));
548 StrnCpy(fname,params+4,fname_len);
549 unix_convert(fname,cnum,0,&bad_path);
553 /****************************************************************************
554 Reply to a notify change - we should never get this (for now) as we
555 don't allow a directory to be opened.
556 ****************************************************************************/
558 static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int bufsize, int cnum,
559 char **setup, char **params, char **data)
561 DEBUG(0,("call_nt_transact_notify_change: Should not be called !\n"));
562 return(ERROR(ERRSRV,ERRnosupport));
565 /****************************************************************************
566 Reply to query a security descriptor - currently this is not implemented (it
567 is planned to be though).
568 ****************************************************************************/
570 static int call_nt_transact_query_security_desc(char *inbuf, char *outbuf, int bufsize, int cnum,
571 char **setup, char **params, char **data)
573 DEBUG(0,("call_nt_transact_query_security_desc: Currently not implemented.\n"));
574 return(ERROR(ERRSRV,ERRnosupport));
577 /****************************************************************************
578 Reply to set a security descriptor - currently this is not implemented (it
579 is planned to be though).
580 ****************************************************************************/
582 static int call_nt_transact_set_security_desc(char *inbuf, char *outbuf, int bufsize, int cnum,
583 char **setup, char **params, char **data)
585 DEBUG(0,("call_nt_transact_set_security_desc: Currently not implemented.\n"));
586 return(ERROR(ERRSRV,ERRnosupport));
589 /****************************************************************************
590 Reply to IOCTL - not implemented - no plans.
591 ****************************************************************************/
593 static int call_nt_transact_ioctl(char *inbuf, char *outbuf, int bufsize, int cnum,
594 char **setup, char **params, char **data)
596 DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n"));
597 return(ERROR(ERRSRV,ERRnosupport));
600 /****************************************************************************
601 Reply to a SMBNTtrans.
602 ****************************************************************************/
604 int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize)
607 int cnum = SVAL(inbuf,smb_tid);
608 #if 0 /* Not used. */
609 uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount);
610 uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount);
611 uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
612 #endif /* Not used. */
613 uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount);
614 uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount);
615 uint32 parameter_count = IVAL(inbuf,smb_nt_ParameterCount);
616 uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset);
617 uint32 data_count = IVAL(inbuf,smb_nt_DataCount);
618 uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset);
619 uint16 setup_count = CVAL(inbuf,smb_nt_SetupCount);
620 uint16 function_code = SVAL( inbuf, smb_nt_Function);
621 char *params = NULL, *data = NULL, *setup = NULL;
622 uint32 num_params_sofar, num_data_sofar;
624 if(global_oplock_break && (function_code == NT_TRANSACT_CREATE)) {
626 * Queue this open message as we are the process of an oplock break.
629 DEBUG(2,("%s: reply_nttrans: queueing message NT_TRANSACT_CREATE \
630 due to being in oplock break state.\n", timestring() ));
632 push_smb_message( inbuf, length);
636 outsize = set_message(outbuf,0,0,True);
639 * All nttrans messages we handle have smb_wcnt == 19 + setup_count.
640 * Ensure this is so as a sanity check.
643 if(CVAL(inbuf, smb_wcnt) != 19 + setup_count) {
644 DEBUG(2,("Invalid smb_wcnt in trans2 call\n"));
645 return(ERROR(ERRSRV,ERRerror));
648 /* Allocate the space for the setup, the maximum needed parameters and data */
651 setup = (char *)malloc(setup_count);
652 if (total_parameter_count > 0)
653 params = (char *)malloc(total_parameter_count);
654 if (total_data_count > 0)
655 data = (char *)malloc(total_data_count);
657 if ((total_parameter_count && !params) || (total_data_count && !data) ||
658 (setup_count && !setup)) {
659 DEBUG(0,("reply_nttrans : Out of memory\n"));
660 return(ERROR(ERRDOS,ERRnomem));
663 /* Copy the param and data bytes sent with this request into
665 num_params_sofar = parameter_count;
666 num_data_sofar = data_count;
668 if (parameter_count > total_parameter_count || data_count > total_data_count)
669 exit_server("reply_nttrans: invalid sizes in packet.\n");
672 memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
674 memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
676 memcpy( data, smb_base(inbuf) + data_offset, data_count);
678 if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
679 /* We need to send an interim response then receive the rest
680 of the parameter/data bytes */
681 outsize = set_message(outbuf,0,0,True);
682 send_smb(Client,outbuf);
684 while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
687 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
690 if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
691 outsize = set_message(outbuf,0,0,True);
693 DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
695 DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
696 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
703 return(ERROR(ERRSRV,ERRerror));
706 /* Revise total_params and total_data in case they have changed downwards */
707 total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
708 total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
709 num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount));
710 num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount));
711 if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count)
712 exit_server("reply_nttrans2: data overflow in secondary nttrans packet\n");
714 memcpy( ¶ms[ IVAL(inbuf, smb_nts_ParameterDisplacement)],
715 smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count);
716 memcpy( &data[IVAL(inbuf, smb_nts_DataDisplacement)],
717 smb_base(inbuf)+ IVAL(inbuf, smb_nts_DataOffset), data_count);
721 if (Protocol >= PROTOCOL_NT1) {
722 uint16 flg2 = SVAL(outbuf,smb_flg2);
723 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
726 /* Now we must call the relevant NT_TRANS function */
727 switch(function_code) {
728 case NT_TRANSACT_CREATE:
729 outsize = call_nt_transact_create(inbuf, outbuf, bufsize, cnum,
730 &setup, ¶ms, &data);
732 case NT_TRANSACT_IOCTL:
733 outsize = call_nt_transact_ioctl(inbuf, outbuf, bufsize, cnum,
734 &setup, ¶ms, &data);
736 case NT_TRANSACT_SET_SECURITY_DESC:
737 outsize = call_nt_transact_set_security_desc(inbuf, outbuf, length, bufsize, cnum,
738 &setup, ¶ms, &data);
740 case NT_TRANSACT_NOTIFY_CHANGE:
741 outsize = call_nt_transact_notify_change(inbuf, outbuf, length, bufsize, cnum,
742 &setup, ¶ms, &data);
744 case NT_TRANSACT_RENAME:
745 outsize = call_nt_transact_rename(inbuf, outbuf, length, bufsize, cnum,
746 &setup, ¶ms, &data);
748 case NT_TRANSACT_QUERY_SECURITY_DESC:
749 outsize = call_nt_transact_query_security_desc(inbuf, outbuf, length, bufsize, cnum,
750 &setup, ¶ms, &data, total_data);
753 /* Error in request */
754 DEBUG(0,("reply_nttrans: %s Unknown request %d in nttrans call\n",timestring(),
762 return (ERROR(ERRSRV,ERRerror));
765 /* As we do not know how many data packets will need to be
766 returned here the various call_nt_transact_xxxx calls
767 must send their own. Thus a call_nt_transact_xxxx routine only
768 returns a value other than -1 when it wants to send
778 return outsize; /* If a correct response was needed the call_nt_transact_xxxx
779 calls have already sent it. If outsize != -1 then it is
780 returning an error packet. */