2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-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.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
33 extern char magic_char
;
34 extern BOOL case_sensitive
;
35 extern BOOL case_preserve
;
36 extern BOOL short_case_preserve
;
37 extern userdom_struct current_user_info
;
38 extern pstring global_myname
;
39 extern fstring global_myworkgroup
;
40 extern int global_oplock_break
;
41 uint32 global_client_caps
= 0;
42 unsigned int smb_echo_count
= 0;
44 /****************************************************************************
45 Report a possible attack via the password buffer overflow bug.
46 ****************************************************************************/
48 static void overflow_attack(int len
)
51 dbgtext( "ERROR: Invalid password length %d.\n", len
);
52 dbgtext( "Your machine may be under attack by someone " );
53 dbgtext( "attempting to exploit an old bug.\n" );
54 dbgtext( "Attack was from IP = %s.\n", client_addr() );
59 /****************************************************************************
60 Reply to an special message.
61 ****************************************************************************/
63 int reply_special(char *inbuf
,char *outbuf
)
66 int msg_type
= CVAL(inbuf
,0);
67 int msg_flags
= CVAL(inbuf
,1);
69 extern fstring remote_machine
;
70 extern fstring local_machine
;
76 memset(outbuf
,'\0',smb_size
);
81 case 0x81: /* session request */
84 if (name_len(inbuf
+4) > 50 ||
85 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
86 DEBUG(0,("Invalid name length in session request\n"));
89 name_extract(inbuf
,4,name1
);
90 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
91 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
94 fstrcpy(remote_machine
,name2
);
95 remote_machine
[15] = 0;
96 trim_string(remote_machine
," "," ");
97 strlower(remote_machine
);
98 alpha_strcpy(remote_machine
,remote_machine
,SAFE_NETBIOS_CHARS
,sizeof(remote_machine
)-1);
100 fstrcpy(local_machine
,name1
);
101 len
= strlen(local_machine
);
103 name_type
= local_machine
[15];
104 local_machine
[15] = 0;
106 trim_string(local_machine
," "," ");
107 strlower(local_machine
);
108 alpha_strcpy(local_machine
,local_machine
,SAFE_NETBIOS_CHARS
,sizeof(local_machine
)-1);
110 DEBUG(2,("netbios connect: local=%s remote=%s\n",
111 local_machine
, remote_machine
));
113 if (name_type
== 'R') {
114 /* We are being asked for a pathworks session ---
116 SCVAL(outbuf
, 0, 0x83);
120 /* add it as a possible user name if we
121 are in share mode security */
122 if (lp_security() == SEC_SHARE
) {
123 add_session_user(remote_machine
);
126 reload_services(True
);
130 claim_connection(NULL
,"",0,True
);
134 case 0x89: /* session keepalive request
135 (some old clients produce this?) */
136 SCVAL(outbuf
,0,0x85);
140 case 0x82: /* positive session response */
141 case 0x83: /* negative session response */
142 case 0x84: /* retarget session response */
143 DEBUG(0,("Unexpected session response\n"));
146 case 0x85: /* session keepalive */
151 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
152 msg_type
, msg_flags
));
157 /*******************************************************************
158 Work out what error to give to a failed connection.
159 ********************************************************************/
161 static int connection_error(char *outbuf
, int ecode
)
163 if (ecode
== ERRnoipc
|| ecode
== ERRnosuchshare
)
164 return(ERROR_DOS(ERRDOS
,ecode
));
166 return(ERROR_DOS(ERRSRV
,ecode
));
169 /****************************************************************************
170 Parse a share descriptor string.
171 ****************************************************************************/
173 static void parse_connect(char *p
,char *service
,char *user
,
174 char *password
,int *pwlen
,char *dev
)
178 DEBUG(4,("parsing connect string %s\n",p
));
180 p2
= strrchr(p
,'\\');
184 fstrcpy(service
,p2
+1);
189 *pwlen
= strlen(password
);
196 p
= strchr(service
,'%');
204 /****************************************************************************
206 ****************************************************************************/
208 int reply_tcon(connection_struct
*conn
,
209 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
211 BOOL doencrypt
= SMBENCRYPT();
217 uint16 vuid
= SVAL(inbuf
,smb_uid
);
220 START_PROFILE(SMBtcon
);
222 *service
= *user
= *password
= *dev
= 0;
224 parse_connect(smb_buf(inbuf
)+1,service
,user
,password
,&pwlen
,dev
);
227 * If the vuid is valid, we should be using that....
230 if (*user
== '\0' && (lp_security() != SEC_SHARE
) && validated_username(vuid
)) {
231 pstrcpy(user
,validated_username(vuid
));
235 * Ensure the user and password names are in UNIX codepage format.
238 pstrcpy(user
,dos_to_unix_static(user
));
240 pstrcpy(password
,dos_to_unix_static(password
));
243 * Pass the user through the NT -> unix user mapping
247 (void)map_username(user
);
250 * Do any UNIX username case mangling.
252 (void)Get_Pwnam( user
, True
);
254 conn
= make_connection(service
,user
,password
,pwlen
,dev
,vuid
,&ecode
);
257 END_PROFILE(SMBtcon
);
258 return(connection_error(outbuf
,ecode
));
261 outsize
= set_message(outbuf
,2,0,True
);
262 SSVAL(outbuf
,smb_vwv0
,max_recv
);
263 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
264 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
266 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
267 service
, user
, conn
->cnum
));
269 END_PROFILE(SMBtcon
);
273 /****************************************************************************
274 Reply to a tcon and X.
275 ****************************************************************************/
277 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
283 BOOL doencrypt
= SMBENCRYPT();
285 uint16 vuid
= SVAL(inbuf
,smb_uid
);
286 int passlen
= SVAL(inbuf
,smb_vwv3
);
289 START_PROFILE(SMBtconX
);
291 *service
= *user
= *password
= *devicename
= 0;
293 /* we might have to close an old one */
294 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
295 close_cnum(conn
,vuid
);
298 if (passlen
> MAX_PASS_LEN
) {
299 overflow_attack(passlen
);
300 return(ERROR_DOS(ERRDOS
,ERRbuftoosmall
));
303 memcpy(password
,smb_buf(inbuf
),passlen
);
305 path
= smb_buf(inbuf
) + passlen
;
308 if (strequal(password
," "))
310 passlen
= strlen(password
);
314 * the service name can be either: \\server\share
315 * or share directly like on the DELL PowerVault 705
318 p
= strchr(path
+2,'\\');
320 END_PROFILE(SMBtconX
);
321 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
323 fstrcpy(service
,p
+1);
326 fstrcpy(service
,path
);
328 p
= strchr(service
,'%');
333 StrnCpy(devicename
,path
+ strlen(path
) + 1,6);
334 DEBUG(4,("Got device type %s\n",devicename
));
337 * If the vuid is valid, we should be using that....
340 if (*user
== '\0' && (lp_security() != SEC_SHARE
) && validated_username(vuid
)) {
341 pstrcpy(user
,validated_username(vuid
));
345 * Ensure the user and password names are in UNIX codepage format.
348 pstrcpy(user
,dos_to_unix_static(user
));
350 pstrcpy(password
,dos_to_unix_static(password
));
353 * Pass the user through the NT -> unix user mapping
357 (void)map_username(user
);
360 * Do any UNIX username case mangling.
362 (void)Get_Pwnam(user
, True
);
364 conn
= make_connection(service
,user
,password
,passlen
,devicename
,vuid
,&ecode
);
367 END_PROFILE(SMBtconX
);
368 return(connection_error(outbuf
,ecode
));
371 if (Protocol
< PROTOCOL_NT1
) {
372 set_message(outbuf
,2,strlen(devicename
)+1,True
);
373 pstrcpy(smb_buf(outbuf
),devicename
);
375 char *fsname
= lp_fstype(SNUM(conn
));
377 set_message(outbuf
,3,3,True
);
380 pstrcpy(p
,devicename
); p
= skip_string(p
,1); /* device name */
381 pstrcpy(p
,fsname
); p
= skip_string(p
,1); /* filesystem type e.g NTFS */
383 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
385 /* what does setting this bit do? It is set by NT4 and
386 may affect the ability to autorun mounted cdroms */
387 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
388 (lp_csc_policy(SNUM(conn
)) << 2));
390 init_dfsroot(conn
, inbuf
, outbuf
);
394 DEBUG(3,("tconX service=%s user=%s\n",
397 /* set the incoming and outgoing tid to the just created one */
398 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
399 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
401 END_PROFILE(SMBtconX
);
402 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
405 /****************************************************************************
406 Reply to an unknown type.
407 ****************************************************************************/
409 int reply_unknown(char *inbuf
,char *outbuf
)
412 type
= CVAL(inbuf
,smb_com
);
414 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
415 smb_fn_name(type
), type
, type
));
417 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
420 /****************************************************************************
422 ****************************************************************************/
424 int reply_ioctl(connection_struct
*conn
,
425 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
427 uint16 device
= SVAL(inbuf
,smb_vwv1
);
428 uint16 function
= SVAL(inbuf
,smb_vwv2
);
429 uint32 ioctl_code
= (device
<< 16) + function
;
430 int replysize
, outsize
;
432 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
433 START_PROFILE(SMBioctl
);
435 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
439 case IOCTL_QUERY_JOB_INFO
:
443 END_PROFILE(SMBioctl
);
444 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
447 outsize
= set_message(outbuf
,8,replysize
+1,True
);
448 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
449 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
450 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
451 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
455 case IOCTL_QUERY_JOB_INFO
:
456 SSVAL(p
,0,fsp
->print_jobid
); /* Job number */
457 StrnCpy(p
+2, global_myname
, 15); /* Our NetBIOS name */
458 StrnCpy(p
+18, lp_servicename(SNUM(conn
)), 13); /* Service name */
462 END_PROFILE(SMBioctl
);
466 /****************************************************************************
467 Always return an error: it's just a matter of which one...
468 ****************************************************************************/
470 static int session_trust_account(connection_struct
*conn
, char *inbuf
, char *outbuf
, char *user
,
471 char *smb_passwd
, int smb_passlen
,
472 char *smb_nt_passwd
, int smb_nt_passlen
)
474 SAM_ACCOUNT
*sam_trust_acct
= NULL
; /* check if trust account exists */
477 if (lp_security() == SEC_USER
) {
478 pdb_init_sam(&sam_trust_acct
);
479 pdb_getsampwnam(sam_trust_acct
, user
);
481 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user
));
482 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE
,ERRSRV
,ERRbadpw
));
485 if (sam_trust_acct
== NULL
) {
486 /* lkclXXXX: workstation entry doesn't exist */
487 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user
));
488 return(ERROR_BOTH(NT_STATUS_NO_SUCH_USER
,ERRDOS
,1317));
490 if ((smb_passlen
!= 24) || (smb_nt_passlen
!= 24)) {
491 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user
));
492 pdb_free_sam(sam_trust_acct
);
493 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE
,ERRSRV
,ERRbadpw
));
496 if (!smb_password_ok(sam_trust_acct
, NULL
, (unsigned char *)smb_passwd
, (unsigned char *)smb_nt_passwd
)) {
497 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user
));
498 pdb_free_sam(sam_trust_acct
);
499 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE
,ERRSRV
,ERRbadpw
));
502 acct_ctrl
= pdb_get_acct_ctrl(sam_trust_acct
);
503 if (acct_ctrl
& ACB_DOMTRUST
) {
504 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user
));
505 pdb_free_sam(sam_trust_acct
);
506 return(ERROR_BOTH(NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT
,ERRDOS
,1807));
509 if (acct_ctrl
& ACB_SVRTRUST
) {
510 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user
));
511 pdb_free_sam(sam_trust_acct
);
512 return(ERROR_BOTH(NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT
,ERRDOS
,1809));
515 if (acct_ctrl
& ACB_WSTRUST
) {
516 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user
));
517 pdb_free_sam(sam_trust_acct
);
518 return(ERROR_BOTH(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
,ERRDOS
,1808));
522 /* don't know what to do: indicate logon failure */
523 pdb_free_sam(sam_trust_acct
);
524 return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE
,ERRDOS
,1326));
527 /****************************************************************************
528 Create a UNIX user on demand.
529 ****************************************************************************/
531 int smb_create_user(char *unix_user
, char *homedir
)
536 pstrcpy(add_script
, lp_adduser_script());
539 all_string_sub(add_script
, "%u", unix_user
, sizeof(pstring
));
541 all_string_sub(add_script
, "%H", homedir
, sizeof(pstring
));
542 ret
= smbrun(add_script
,NULL
);
543 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script
,ret
));
547 /****************************************************************************
548 Delete a UNIX user on demand.
549 ****************************************************************************/
551 static int smb_delete_user(char *unix_user
)
557 * Sanity check -- do not delete 'root' account
560 if (StrCaseCmp("root", unix_user
) == 0) {
561 DEBUG(0,("smb_delete_user: Will not delete the [%s] user account!\n", unix_user
));
565 pstrcpy(del_script
, lp_deluser_script());
568 all_string_sub(del_script
, "%u", unix_user
, sizeof(pstring
));
569 ret
= smbrun(del_script
,NULL
);
570 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script
,ret
));
574 /****************************************************************************
575 Check user is in correct domain if required
576 ****************************************************************************/
578 static BOOL
check_domain_match(char *user
, char *domain
)
581 * If we aren't serving to trusted domains, we must make sure that
582 * the validation request comes from an account in the same domain
583 * as the Samba server
586 if (!lp_allow_trusted_domains() &&
587 !strequal(lp_workgroup(), domain
) ) {
588 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user
, domain
));
595 /****************************************************************************
596 Check for a valid username and password in security=server mode.
597 ****************************************************************************/
599 static BOOL
check_server_security(char *orig_user
, char *domain
, char *unix_user
,
600 char *smb_apasswd
, int smb_apasslen
,
601 char *smb_ntpasswd
, int smb_ntpasslen
)
605 if(lp_security() != SEC_SERVER
)
608 if (!check_domain_match(orig_user
, domain
))
611 ret
= server_validate(orig_user
, domain
,
612 smb_apasswd
, smb_apasslen
,
613 smb_ntpasswd
, smb_ntpasslen
);
617 * User validated ok against Domain controller.
618 * If the admin wants us to try and create a UNIX
619 * user on the fly, do so.
620 * Note that we can never delete users when in server
621 * level security as we never know if it was a failure
622 * due to a bad password, or the user really doesn't exist.
625 if(lp_adduser_script() && !smb_getpwnam(unix_user
,True
))
626 smb_create_user(unix_user
, NULL
);
632 /****************************************************************************
633 Check for a valid username and password in security=domain mode.
634 ****************************************************************************/
636 static BOOL
check_domain_security(char *orig_user
, char *domain
, char *unix_user
,
637 char *smb_apasswd
, int smb_apasslen
,
638 char *smb_ntpasswd
, int smb_ntpasslen
, NT_USER_TOKEN
**pptoken
)
641 BOOL user_exists
= True
;
642 struct passwd
*pwd
= NULL
;
644 if(lp_security() != SEC_DOMAIN
)
647 if (!check_domain_match(orig_user
, domain
))
650 ret
= domain_client_validate(orig_user
, domain
,
651 smb_apasswd
, smb_apasslen
,
652 smb_ntpasswd
, smb_ntpasslen
,
653 &user_exists
, pptoken
);
657 * User validated ok against Domain controller.
658 * If the admin wants us to try and create a UNIX
659 * user on the fly, do so.
661 if(user_exists
&& lp_adduser_script() && !(pwd
= smb_getpwnam(unix_user
,True
))) {
662 smb_create_user(unix_user
, NULL
);
665 if(lp_adduser_script() && pwd
) {
669 * Also call smb_create_user if the users home directory
670 * doesn't exist. Used with winbindd to allow the script to
671 * create the home directory for a user mapped with winbindd.
674 if (pwd
->pw_dir
&& (sys_stat(pwd
->pw_dir
, &st
) == -1) && (errno
== ENOENT
))
675 smb_create_user(unix_user
, pwd
->pw_dir
);
680 * User failed to validate ok against Domain controller.
681 * If the failure was "user doesn't exist" and admin
682 * wants us to try and delete that UNIX user on the fly,
685 if(!user_exists
&& lp_deluser_script() && smb_getpwnam(unix_user
,True
)) {
686 smb_delete_user(unix_user
);
693 /****************************************************************************
694 Reply to a session setup command.
695 ****************************************************************************/
697 int reply_sesssetup_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
703 int smb_apasslen
= 0;
705 int smb_ntpasslen
= 0;
706 pstring smb_ntpasswd
;
707 BOOL valid_nt_password
= False
;
708 BOOL valid_lm_password
= False
;
712 static BOOL done_sesssetup
= False
;
713 BOOL doencrypt
= SMBENCRYPT();
715 NT_USER_TOKEN
*ptok
= NULL
;
717 START_PROFILE(SMBsesssetupX
);
723 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
725 if (Protocol
< PROTOCOL_NT1
) {
726 smb_apasslen
= SVAL(inbuf
,smb_vwv7
);
727 if (smb_apasslen
> MAX_PASS_LEN
) {
728 overflow_attack(smb_apasslen
);
729 return(ERROR_DOS(ERRDOS
,ERRbuftoosmall
));
732 memcpy(smb_apasswd
,smb_buf(inbuf
),smb_apasslen
);
733 smb_apasswd
[smb_apasslen
] = 0;
734 pstrcpy(user
,smb_buf(inbuf
)+smb_apasslen
);
736 * Incoming user is in DOS codepage format. Convert
739 pstrcpy(user
,dos_to_unix_static(user
));
741 if (!doencrypt
&& (lp_security() != SEC_SERVER
)) {
742 smb_apasslen
= strlen(smb_apasswd
);
745 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
746 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
747 enum remote_arch_types ra_type
= get_remote_arch();
748 char *p
= smb_buf(inbuf
);
750 if(global_client_caps
== 0)
751 global_client_caps
= IVAL(inbuf
,smb_vwv11
);
753 /* client_caps is used as final determination if client is NT or Win95.
754 This is needed to return the correct error codes in some
758 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
|| ra_type
== RA_WIN95
) {
759 if(!(global_client_caps
& (CAP_NT_SMBS
| CAP_STATUS32
))) {
760 set_remote_arch( RA_WIN95
);
764 if (passlen1
!= 24 && passlen2
!= 24)
767 if (passlen1
> MAX_PASS_LEN
) {
768 overflow_attack(passlen1
);
769 return(ERROR_DOS(ERRDOS
,ERRbuftoosmall
));
772 passlen1
= MIN(passlen1
, MAX_PASS_LEN
);
773 passlen2
= MIN(passlen2
, MAX_PASS_LEN
);
776 /* both Win95 and WinNT stuff up the password lengths for
777 non-encrypting systems. Uggh.
779 if passlen1==24 its a win95 system, and its setting the
780 password length incorrectly. Luckily it still works with the
781 default code because Win95 will null terminate the password
784 if passlen1>0 and passlen2>0 then maybe its a NT box and its
785 setting passlen2 to some random value which really stuffs
786 things up. we need to fix that one. */
788 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 && passlen2
!= 1)
792 if (lp_restrict_anonymous()) {
793 /* there seems to be no reason behind the differences in MS clients formatting
794 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
795 * in particular seems to have an extra null byte between the username and the
796 * domain, or the password length calculation is wrong, which throws off the
797 * string extraction routines below. This makes the value of domain be the
798 * empty string, which fails the restrict anonymous check further down.
799 * This compensates for that, and allows browsing to work in mixed NT and
800 * win95 environments even when restrict anonymous is true. AAB
802 dump_data(100, p
, 0x70);
803 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1
, passlen2
));
804 if (ra_type
== RA_WIN95
&& !passlen1
&& !passlen2
&& p
[0] == 0 && p
[1] == 0) {
805 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
806 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
807 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
812 if(doencrypt
|| ((lp_security() == SEC_SERVER
) || (lp_security() == SEC_DOMAIN
))) {
813 /* Save the lanman2 password and the NT md4 password. */
814 smb_apasslen
= passlen1
;
815 memcpy(smb_apasswd
,p
,smb_apasslen
);
816 smb_apasswd
[smb_apasslen
] = 0;
817 smb_ntpasslen
= passlen2
;
818 memcpy(smb_ntpasswd
,p
+passlen1
,smb_ntpasslen
);
819 smb_ntpasswd
[smb_ntpasslen
] = 0;
822 * Ensure the plaintext passwords are in UNIX format.
825 pstrcpy(smb_apasswd
,dos_to_unix_static(smb_apasswd
));
826 pstrcpy(smb_ntpasswd
,dos_to_unix_static(smb_ntpasswd
));
830 /* we use the first password that they gave */
831 smb_apasslen
= passlen1
;
832 StrnCpy(smb_apasswd
,p
,smb_apasslen
);
834 * Ensure the plaintext password is in UNIX format.
836 pstrcpy(smb_apasswd
,dos_to_unix_static(smb_apasswd
));
838 /* trim the password */
839 smb_apasslen
= strlen(smb_apasswd
);
841 /* wfwg sometimes uses a space instead of a null */
842 if (strequal(smb_apasswd
," ")) {
848 p
+= passlen1
+ passlen2
;
850 p
= skip_string(p
,1);
852 * Incoming user and domain are in DOS codepage format. Convert
855 pstrcpy(user
,dos_to_unix_static(user
));
856 fstrcpy(domain
, dos_to_unix_static(p
));
857 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
858 domain
,skip_string(p
,1),skip_string(p
,2)));
861 /* don't allow strange characters in usernames or domains */
862 alpha_strcpy(user
, user
, ". _-$", sizeof(user
));
863 alpha_strcpy(domain
, domain
, ". _-@", sizeof(domain
));
864 if (strstr(user
, "..") || strstr(domain
,"..")) {
865 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE
,ERRSRV
,ERRbadpw
);
868 DEBUG(3,("sesssetupX:name=[%s]\n",user
));
870 /* If name ends in $ then I think it's asking about whether a */
871 /* computer with that name (minus the $) has access. For now */
872 /* say yes to everything ending in $. */
874 if (*user
&& (user
[strlen(user
) - 1] == '$') && (smb_apasslen
== 24) && (smb_ntpasslen
== 24)) {
875 END_PROFILE(SMBsesssetupX
);
876 return session_trust_account(conn
, inbuf
, outbuf
, user
,
877 smb_apasswd
, smb_apasslen
,
878 smb_ntpasswd
, smb_ntpasslen
);
881 if (done_sesssetup
&& lp_restrict_anonymous()) {
882 /* tests show that even if browsing is done over already validated connections
883 * without a username and password the domain is still provided, which it
884 * wouldn't be if it was a purely anonymous connection. So, in order to
885 * restrict anonymous, we only deny connections that have no session
886 * information. If a domain has been provided, then it's not a purely
887 * anonymous connection. AAB
889 if (!*user
&& !*smb_apasswd
&& !*domain
) {
890 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
891 END_PROFILE(SMBsesssetupX
);
892 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
896 /* If no username is sent use the guest account */
898 pstrcpy(user
,lp_guestaccount(-1));
902 pstrcpy(current_user_info
.smb_name
,user
);
904 reload_services(True
);
907 * Save the username before mapping. We will use
908 * the original username sent to us for security=server
909 * and security=domain checking.
912 pstrcpy( orig_user
, user
);
915 * Always try the "DOMAIN\user" lookup first, as this is the most
916 * specific case. If this fails then try the simple "user" lookup.
922 /* Work out who's who */
924 slprintf(dom_user
, sizeof(dom_user
) - 1,"%s%s%s",
925 domain
, lp_winbind_separator(), user
);
927 if (sys_getpwnam(dom_user
) != NULL
) {
928 pstrcpy(user
, dom_user
);
929 DEBUG(3,("Using unix username %s\n", dom_user
));
934 * Pass the user through the NT -> unix user mapping
938 (void)map_username(user
);
941 * Do any UNIX username case mangling.
943 smb_getpwnam(user
, True
);
945 add_session_user(user
);
948 * Check with orig_user for security=server and
952 if (!guest
&& !check_server_security(orig_user
, domain
, user
,
953 smb_apasswd
, smb_apasslen
, smb_ntpasswd
, smb_ntpasslen
) &&
954 !check_domain_security(orig_user
, domain
, user
, smb_apasswd
,
955 smb_apasslen
, smb_ntpasswd
, smb_ntpasslen
, &ptok
) &&
956 !check_hosts_equiv(user
))
960 * If we get here then the user wasn't guest and the remote
961 * authentication methods failed. Check the authentication
962 * methods on this local server.
964 * If an NT password was supplied try and validate with that
965 * first. This is superior as the passwords are mixed case
966 * 128 length unicode.
971 if(!password_ok(user
, smb_ntpasswd
,smb_ntpasslen
,NULL
))
972 DEBUG(2,("NT Password did not match for user '%s'!\n", user
));
974 valid_nt_password
= True
;
978 /* check the LanMan password only if necessary and if allowed
979 by lp_lanman_auth() */
980 if (!valid_nt_password
&& lp_lanman_auth())
982 DEBUG(2,("Defaulting to Lanman password for %s\n", user
));
983 valid_lm_password
= password_ok(user
, smb_apasswd
,smb_apasslen
,NULL
);
987 /* The true branch will be executed if
988 (1) the NT password failed (or was not tried), and
989 (2) LanMan authentication failed (or was disabled)
991 if (!valid_nt_password
&& !valid_lm_password
)
993 if (lp_security() >= SEC_USER
)
995 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST
)
997 delete_nt_token(&ptok
);
998 DEBUG(1,("Rejecting user '%s': authentication failed\n", user
));
999 END_PROFILE(SMBsesssetupX
);
1000 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE
,ERRSRV
,ERRbadpw
);
1003 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER
)
1005 SAM_ACCOUNT
*sampass
= NULL
;
1007 pdb_init_sam(&sampass
);
1010 * This is really bad form. We know that password_ok() failed,
1011 * but the return value can't distinguish between a non-existent user
1012 * and a bad password. So we try to look the user up again here
1013 * to see if he or she exists. We must look up the user in the
1014 * "smb passwd file" and not /etc/passwd so that we don't
1015 * get confused when the two don't have a one-to-one correspondence.
1016 * e.g. a standard UNIX account such as "operator" --jerry
1019 if (pdb_getsampwnam(sampass
, user
))
1021 delete_nt_token(&ptok
);
1022 DEBUG(1,("Rejecting user '%s': bad password\n", user
));
1023 END_PROFILE(SMBsesssetupX
);
1024 pdb_free_sam(sampass
);
1025 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE
,ERRSRV
,ERRbadpw
);
1028 pdb_free_sam(sampass
);
1032 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
1033 * Then always map to guest account - as done below.
1037 if (*smb_apasswd
|| !smb_getpwnam(user
,True
))
1038 pstrcpy(user
,lp_guestaccount(-1));
1039 DEBUG(3,("Registered username %s for guest access\n",user
));
1044 if (!smb_getpwnam(user
,True
)) {
1045 DEBUG(3,("No such user %s [%s] - using guest account\n",user
, domain
));
1046 pstrcpy(user
,lp_guestaccount(-1));
1050 if (!strequal(user
,lp_guestaccount(-1)) &&
1051 lp_servicenumber(user
) < 0)
1053 add_home_service(user
,get_user_service_home_dir(user
));
1057 /* it's ok - setup a reply */
1058 if (Protocol
< PROTOCOL_NT1
) {
1059 set_message(outbuf
,3,0,True
);
1062 set_message(outbuf
,3,3,True
);
1063 p
= smb_buf(outbuf
);
1064 pstrcpy(p
,"Unix"); p
= skip_string(p
,1);
1065 pstrcpy(p
,"Samba "); pstrcat(p
,VERSION
); p
= skip_string(p
,1);
1066 pstrcpy(p
,global_myworkgroup
); unix_to_dos(p
); p
= skip_string(p
,1);
1067 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
1068 /* perhaps grab OS version here?? */
1071 /* Set the correct uid in the outgoing and incoming packets
1072 We will use this on future requests to determine which
1073 user we should become.
1076 const struct passwd
*pw
= smb_getpwnam(user
,False
);
1078 delete_nt_token(&ptok
);
1079 DEBUG(1,("Username %s is invalid on this system\n",user
));
1080 END_PROFILE(SMBsesssetupX
);
1081 return ERROR_BOTH(NT_STATUS_LOGON_FAILURE
,ERRSRV
,ERRbadpw
);
1088 SSVAL(outbuf
,smb_vwv2
,1);
1090 /* register the name and uid as being validated, so further connections
1091 to a uid can get through without a password, on the same VC */
1093 sess_vuid
= register_vuid(uid
,gid
,user
,current_user_info
.smb_name
,domain
,guest
,&ptok
);
1095 delete_nt_token(&ptok
);
1097 if (sess_vuid
== -1) {
1098 END_PROFILE(SMBsesssetupX
);
1099 return(ERROR_DOS(ERRDOS
,ERRnoaccess
));
1102 SSVAL(outbuf
,smb_uid
,sess_vuid
);
1103 SSVAL(inbuf
,smb_uid
,sess_vuid
);
1105 if (!done_sesssetup
)
1106 max_send
= MIN(max_send
,smb_bufsize
);
1108 DEBUG(6,("Client requested max send size of %d\n", max_send
));
1110 done_sesssetup
= True
;
1112 END_PROFILE(SMBsesssetupX
);
1113 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1116 /****************************************************************************
1118 ****************************************************************************/
1120 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1126 BOOL bad_path
= False
;
1127 SMB_STRUCT_STAT sbuf
;
1128 START_PROFILE(SMBchkpth
);
1130 pstrcpy(name
,smb_buf(inbuf
) + 1);
1132 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
1134 unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1136 mode
= SVAL(inbuf
,smb_vwv0
);
1138 if (check_name(name
,conn
)) {
1139 if (VALID_STAT(sbuf
) || vfs_stat(conn
,name
,&sbuf
) == 0)
1140 ok
= S_ISDIR(sbuf
.st_mode
);
1144 /* We special case this - as when a Windows machine
1145 is parsing a path is steps through the components
1146 one at a time - if a component fails it expects
1147 ERRbadpath, not ERRbadfile.
1149 if(errno
== ENOENT
) {
1150 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
1153 return(UNIXERROR(ERRDOS
,ERRbadpath
));
1156 outsize
= set_message(outbuf
,0,0,True
);
1158 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
1160 END_PROFILE(SMBchkpth
);
1164 /****************************************************************************
1166 ****************************************************************************/
1168 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1172 SMB_STRUCT_STAT sbuf
;
1177 BOOL bad_path
= False
;
1178 START_PROFILE(SMBgetatr
);
1180 pstrcpy(fname
,smb_buf(inbuf
) + 1);
1182 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1184 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1185 under WfWg - weird! */
1188 mode
= aHIDDEN
| aDIR
;
1189 if (!CAN_WRITE(conn
)) mode
|= aRONLY
;
1196 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1197 if (check_name(fname
,conn
))
1199 if (VALID_STAT(sbuf
) || vfs_stat(conn
,fname
,&sbuf
) == 0)
1201 mode
= dos_mode(conn
,fname
,&sbuf
);
1202 size
= sbuf
.st_size
;
1203 mtime
= sbuf
.st_mtime
;
1209 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
1215 set_bad_path_error(errno
, bad_path
);
1216 END_PROFILE(SMBgetatr
);
1217 return(UNIXERROR(ERRDOS
,ERRbadfile
));
1220 outsize
= set_message(outbuf
,10,0,True
);
1222 SSVAL(outbuf
,smb_vwv0
,mode
);
1223 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1224 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
1226 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
1227 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
1229 if (Protocol
>= PROTOCOL_NT1
)
1230 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1232 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
1234 END_PROFILE(SMBgetatr
);
1238 /****************************************************************************
1240 ****************************************************************************/
1242 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1249 SMB_STRUCT_STAT sbuf
;
1250 BOOL bad_path
= False
;
1251 START_PROFILE(SMBsetatr
);
1253 pstrcpy(fname
,smb_buf(inbuf
) + 1);
1254 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1256 mode
= SVAL(inbuf
,smb_vwv0
);
1257 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
1259 if (VALID_STAT_OF_DIR(sbuf
))
1264 if (check_name(fname
,conn
))
1265 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
1267 ok
= set_filetime(conn
,fname
,mtime
);
1271 set_bad_path_error(errno
, bad_path
);
1272 END_PROFILE(SMBsetatr
);
1273 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1276 outsize
= set_message(outbuf
,0,0,True
);
1278 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
1280 END_PROFILE(SMBsetatr
);
1284 /****************************************************************************
1286 ****************************************************************************/
1288 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1291 SMB_BIG_UINT dfree
,dsize
,bsize
;
1292 START_PROFILE(SMBdskattr
);
1294 conn
->vfs_ops
.disk_free(conn
,".",True
,&bsize
,&dfree
,&dsize
);
1296 outsize
= set_message(outbuf
,5,0,True
);
1298 if (Protocol
<= PROTOCOL_LANMAN2
) {
1299 double total_space
, free_space
;
1300 /* we need to scale this to a number that DOS6 can handle. We
1301 use floating point so we can handle large drives on systems
1302 that don't have 64 bit integers
1304 we end up displaying a maximum of 2G to DOS systems
1306 total_space
= dsize
* (double)bsize
;
1307 free_space
= dfree
* (double)bsize
;
1309 dsize
= (total_space
+63*512) / (64*512);
1310 dfree
= (free_space
+63*512) / (64*512);
1312 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1313 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1315 SSVAL(outbuf
,smb_vwv0
,dsize
);
1316 SSVAL(outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1317 SSVAL(outbuf
,smb_vwv2
,512); /* and this must be 512 */
1318 SSVAL(outbuf
,smb_vwv3
,dfree
);
1320 SSVAL(outbuf
,smb_vwv0
,dsize
);
1321 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
1322 SSVAL(outbuf
,smb_vwv2
,512);
1323 SSVAL(outbuf
,smb_vwv3
,dfree
);
1326 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1328 END_PROFILE(SMBdskattr
);
1332 /****************************************************************************
1334 Can be called from SMBsearch, SMBffirst or SMBfunique.
1335 ****************************************************************************/
1337 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1348 BOOL finished
= False
;
1357 BOOL check_descend
= False
;
1358 BOOL expect_close
= False
;
1359 BOOL can_open
= True
;
1360 BOOL bad_path
= False
;
1361 START_PROFILE(SMBsearch
);
1363 *mask
= *directory
= *fname
= 0;
1365 /* If we were called as SMBffirst then we must expect close. */
1366 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
1367 expect_close
= True
;
1369 outsize
= set_message(outbuf
,1,3,True
);
1370 maxentries
= SVAL(inbuf
,smb_vwv0
);
1371 dirtype
= SVAL(inbuf
,smb_vwv1
);
1372 path
= smb_buf(inbuf
) + 1;
1373 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
1375 RESOLVE_DFSPATH(path
, conn
, inbuf
, outbuf
);
1376 /* dirtype &= ~aDIR; */
1378 if (status_len
== 0)
1380 SMB_STRUCT_STAT sbuf
;
1383 pstrcpy(directory
,smb_buf(inbuf
)+1);
1384 pstrcpy(dir2
,smb_buf(inbuf
)+1);
1385 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
1388 if (!check_name(directory
,conn
))
1391 p
= strrchr(dir2
,'/');
1403 p
= strrchr(directory
,'/');
1409 if (strlen(directory
) == 0)
1410 pstrcpy(directory
,"./");
1411 memset((char *)status
,'\0',21);
1412 SCVAL(status
,0,(dirtype
& 0x1F));
1417 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1418 status_dirtype
= CVAL(status
,0) & 0x1F;
1419 if (status_dirtype
!= (dirtype
& 0x1F))
1420 dirtype
= status_dirtype
;
1421 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1424 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1425 fstrcpy(mask
, dptr_wcard(dptr_num
));
1430 p
= smb_buf(outbuf
) + 3;
1434 if (status_len
== 0)
1436 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
1441 set_bad_path_error(errno
, bad_path
);
1442 END_PROFILE(SMBsearch
);
1443 return (UNIXERROR(ERRDOS
,ERRnofids
));
1445 END_PROFILE(SMBsearch
);
1446 return ERROR_DOS(ERRDOS
,ERRnofids
);
1448 dptr_set_wcard(dptr_num
, strdup(mask
));
1451 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1455 if ((dirtype
&0x1F) == aVOLID
)
1457 memcpy(p
,status
,21);
1458 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
1459 dptr_fill(p
+12,dptr_num
);
1460 if (dptr_zero(p
+12) && (status_len
==0))
1464 p
+= DIR_STRUCT_SIZE
;
1468 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1469 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1470 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
1471 check_descend
= True
;
1473 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
1476 !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
1479 memcpy(p
,status
,21);
1480 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
1481 dptr_fill(p
+12,dptr_num
);
1484 p
+= DIR_STRUCT_SIZE
;
1493 if ( (numentries
== 0) || !ok
)
1495 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
1496 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1497 dptr_close(&dptr_num
);
1500 /* If we were called as SMBffirst with smb_search_id == NULL
1501 and no entries were found then return error and close dirptr
1504 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
1506 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
1507 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1508 /* Also close the dptr - we know it's gone */
1509 dptr_close(&dptr_num
);
1512 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1513 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
1514 dptr_close(&dptr_num
);
1516 SSVAL(outbuf
,smb_vwv0
,numentries
);
1517 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1518 SCVAL(smb_buf(outbuf
),0,5);
1519 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1521 if (Protocol
>= PROTOCOL_NT1
)
1522 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1524 outsize
+= DIR_STRUCT_SIZE
*numentries
;
1525 smb_setlen(outbuf
,outsize
- 4);
1527 if ((! *directory
) && dptr_path(dptr_num
))
1528 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1530 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1531 smb_fn_name(CVAL(inbuf
,smb_com
)),
1532 mask
, directory
, dirtype
, numentries
, maxentries
) );
1534 END_PROFILE(SMBsearch
);
1538 /****************************************************************************
1539 Reply to a fclose (stop directory search).
1540 ****************************************************************************/
1542 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1549 START_PROFILE(SMBfclose
);
1551 outsize
= set_message(outbuf
,1,0,True
);
1552 path
= smb_buf(inbuf
) + 1;
1553 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
1556 if (status_len
== 0) {
1557 END_PROFILE(SMBfclose
);
1558 return ERROR_DOS(ERRSRV
,ERRsrverror
);
1561 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1563 if(dptr_fetch(status
+12,&dptr_num
)) {
1564 /* Close the dptr - we know it's gone */
1565 dptr_close(&dptr_num
);
1568 SSVAL(outbuf
,smb_vwv0
,0);
1570 DEBUG(3,("search close\n"));
1572 END_PROFILE(SMBfclose
);
1576 /****************************************************************************
1578 ****************************************************************************/
1580 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1590 SMB_STRUCT_STAT sbuf
;
1591 BOOL bad_path
= False
;
1593 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1594 START_PROFILE(SMBopen
);
1596 share_mode
= SVAL(inbuf
,smb_vwv0
);
1598 pstrcpy(fname
,smb_buf(inbuf
)+1);
1600 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1602 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1604 unixmode
= unix_mode(conn
,aARCH
,fname
);
1606 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1607 unixmode
, oplock_request
,&rmode
,NULL
);
1611 set_bad_path_error(errno
, bad_path
);
1612 END_PROFILE(SMBopen
);
1613 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1616 size
= sbuf
.st_size
;
1617 fmode
= dos_mode(conn
,fname
,&sbuf
);
1618 mtime
= sbuf
.st_mtime
;
1621 DEBUG(3,("attempt to open a directory %s\n",fname
));
1622 close_file(fsp
,False
);
1623 END_PROFILE(SMBopen
);
1624 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1627 outsize
= set_message(outbuf
,7,0,True
);
1628 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1629 SSVAL(outbuf
,smb_vwv1
,fmode
);
1630 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1631 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1633 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1634 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1635 SSVAL(outbuf
,smb_vwv6
,rmode
);
1637 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1638 SCVAL(outbuf
,smb_flg
, CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1641 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1642 SCVAL(outbuf
,smb_flg
, CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1643 END_PROFILE(SMBopen
);
1647 /****************************************************************************
1648 Reply to an open and X.
1649 ****************************************************************************/
1651 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1654 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1655 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1656 /* Breakout the oplock request bits so we can set the
1657 reply bits separately. */
1658 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1659 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1660 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1662 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1663 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1664 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1666 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1669 int fmode
=0,mtime
=0,rmode
=0;
1670 SMB_STRUCT_STAT sbuf
;
1672 BOOL bad_path
= False
;
1674 START_PROFILE(SMBopenX
);
1676 /* If it's an IPC, pass off the pipe handler. */
1678 if (lp_nt_pipe_support()) {
1679 END_PROFILE(SMBopenX
);
1680 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1682 END_PROFILE(SMBopenX
);
1683 return ERROR_DOS(ERRSRV
,ERRaccess
);
1687 /* XXXX we need to handle passed times, sattr and flags */
1689 pstrcpy(fname
,smb_buf(inbuf
));
1691 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1693 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1695 unixmode
= unix_mode(conn
,smb_attr
| aARCH
, fname
);
1697 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,unixmode
,
1698 oplock_request
, &rmode
,&smb_action
);
1702 set_bad_path_error(errno
, bad_path
);
1703 END_PROFILE(SMBopenX
);
1704 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1707 size
= sbuf
.st_size
;
1708 fmode
= dos_mode(conn
,fname
,&sbuf
);
1709 mtime
= sbuf
.st_mtime
;
1711 close_file(fsp
,False
);
1712 END_PROFILE(SMBopenX
);
1713 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1716 /* If the caller set the extended oplock request bit
1717 and we granted one (by whatever means) - set the
1718 correct bit for extended oplock reply.
1721 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1722 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1725 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1726 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1729 /* If the caller set the core oplock request bit
1730 and we granted one (by whatever means) - set the
1731 correct bit for core oplock reply.
1734 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1735 SCVAL(outbuf
,smb_flg
, CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1738 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1739 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1742 set_message(outbuf
,15,0,True
);
1743 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1744 SSVAL(outbuf
,smb_vwv3
,fmode
);
1745 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1746 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1748 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1749 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1750 SSVAL(outbuf
,smb_vwv8
,rmode
);
1751 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1753 END_PROFILE(SMBopenX
);
1754 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1757 /****************************************************************************
1758 Reply to a SMBulogoffX.
1759 ****************************************************************************/
1761 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1763 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1764 user_struct
*vuser
= get_valid_user_struct(vuid
);
1765 START_PROFILE(SMBulogoffX
);
1768 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1771 /* in user level security we are supposed to close any files
1772 open by this user */
1773 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1774 file_close_user(vuid
);
1777 invalidate_vuid(vuid
);
1779 set_message(outbuf
,2,0,True
);
1781 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1783 END_PROFILE(SMBulogoffX
);
1784 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1787 /****************************************************************************
1788 Reply to a mknew or a create.
1789 ****************************************************************************/
1791 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1799 BOOL bad_path
= False
;
1801 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1802 SMB_STRUCT_STAT sbuf
;
1803 START_PROFILE(SMBcreate
);
1805 com
= SVAL(inbuf
,smb_com
);
1807 createmode
= SVAL(inbuf
,smb_vwv0
);
1808 pstrcpy(fname
,smb_buf(inbuf
)+1);
1810 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1812 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1814 if (createmode
& aVOLID
) {
1815 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1818 unixmode
= unix_mode(conn
,createmode
,fname
);
1822 /* We should fail if file exists. */
1823 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1827 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1828 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1831 /* Open file in dos compatibility share mode. */
1832 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1833 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1837 set_bad_path_error(errno
, bad_path
);
1838 END_PROFILE(SMBcreate
);
1839 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1842 outsize
= set_message(outbuf
,1,0,True
);
1843 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1845 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1846 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1849 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1850 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1852 DEBUG( 2, ( "new file %s\n", fname
) );
1853 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1854 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1856 END_PROFILE(SMBcreate
);
1860 /****************************************************************************
1861 Reply to a create temporary file.
1862 ****************************************************************************/
1864 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1870 BOOL bad_path
= False
;
1872 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1874 SMB_STRUCT_STAT sbuf
;
1877 START_PROFILE(SMBctemp
);
1879 createmode
= SVAL(inbuf
,smb_vwv0
);
1880 pstrcpy(fname
,smb_buf(inbuf
)+1);
1881 pstrcat(fname
,"\\TMXXXXXX");
1883 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1885 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1887 unixmode
= unix_mode(conn
,createmode
,fname
);
1889 tmpfd
= smb_mkstemp(fname
);
1891 END_PROFILE(SMBctemp
);
1892 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1895 vfs_stat(conn
,fname
,&sbuf
);
1897 /* Open file in dos compatibility share mode. */
1898 /* We should fail if file does not exist. */
1899 fsp
= open_file_shared(conn
,fname
,&sbuf
,
1900 SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1901 FILE_EXISTS_OPEN
|FILE_FAIL_IF_NOT_EXIST
,
1902 unixmode
, oplock_request
, NULL
, NULL
);
1903 /* close fd from smb_mkstemp() */
1907 set_bad_path_error(errno
, bad_path
);
1908 END_PROFILE(SMBctemp
);
1909 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1912 /* the returned filename is relative to the directory */
1913 s
= strrchr(fname
, '/');
1919 outsize
= set_message(outbuf
,1,4+ strlen(fname
),True
);
1920 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1922 p
= smb_buf(outbuf
);
1923 SSVALS(p
, 0, -1); /* what is this? not in spec */
1924 SSVAL(p
, 2, strlen(s
));
1928 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1929 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1932 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1933 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1935 DEBUG( 2, ( "created temp file %s\n", fname
) );
1936 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1937 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1939 END_PROFILE(SMBctemp
);
1943 /*******************************************************************
1944 Check if a user is allowed to rename a file.
1945 ********************************************************************/
1947 static NTSTATUS
can_rename(char *fname
,connection_struct
*conn
, SMB_STRUCT_STAT
*pst
)
1953 if (!CAN_WRITE(conn
))
1954 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1956 if (S_ISDIR(pst
->st_mode
))
1957 return NT_STATUS_OK
;
1959 /* We need a better way to return NT status codes from open... */
1963 fsp
= open_file_shared1(conn
, fname
, pst
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1964 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1967 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1968 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1969 ret
= NT_STATUS_SHARING_VIOLATION
;
1974 close_file(fsp
,False
);
1975 return NT_STATUS_OK
;
1978 /*******************************************************************
1979 Check if a user is allowed to delete a file.
1980 ********************************************************************/
1982 static NTSTATUS
can_delete(char *fname
,connection_struct
*conn
, int dirtype
)
1984 SMB_STRUCT_STAT sbuf
;
1990 if (!CAN_WRITE(conn
))
1991 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1993 if (conn
->vfs_ops
.lstat(conn
,dos_to_unix_static(fname
),&sbuf
) != 0)
1994 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1996 fmode
= dos_mode(conn
,fname
,&sbuf
);
1998 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1999 if (!lp_delete_readonly(SNUM(conn
))) {
2001 return NT_STATUS_CANNOT_DELETE
;
2004 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
2005 return NT_STATUS_CANNOT_DELETE
;
2007 /* We need a better way to return NT status codes from open... */
2011 fsp
= open_file_shared1(conn
, fname
, &sbuf
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
2012 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
2015 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
2016 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
2017 ret
= NT_STATUS_SHARING_VIOLATION
;
2022 close_file(fsp
,False
);
2023 return NT_STATUS_OK
;
2026 /****************************************************************************
2027 The guts of the unlink command, split out so it may be called by the NT SMB
2029 ****************************************************************************/
2031 NTSTATUS
unlink_internals(connection_struct
*conn
, int dirtype
, char *name
)
2037 NTSTATUS error
= NT_STATUS_OK
;
2039 BOOL bad_path
= False
;
2041 SMB_STRUCT_STAT sbuf
;
2043 *directory
= *mask
= 0;
2045 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
2047 p
= strrchr(name
,'/');
2049 pstrcpy(directory
,".");
2053 pstrcpy(directory
,name
);
2058 * We should only check the mangled cache
2059 * here if unix_convert failed. This means
2060 * that the path in 'mask' doesn't exist
2061 * on the file system and so we need to look
2062 * for a possible mangle. This patch from
2063 * Tine Smukavec <valentin.smukavec@hermes.si>.
2066 if (!rc
&& mangle_is_mangled(mask
))
2067 mangle_check_cache( mask
);
2069 has_wild
= ms_has_wild(mask
);
2072 pstrcat(directory
,"/");
2073 pstrcat(directory
,mask
);
2074 error
= can_delete(directory
,conn
,dirtype
);
2075 if (!NT_STATUS_IS_OK(error
))
2078 if (vfs_unlink(conn
,directory
) == 0)
2081 void *dirptr
= NULL
;
2083 if (check_name(directory
,conn
))
2084 dirptr
= OpenDir(conn
, directory
, True
);
2086 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2087 the pattern matches against the long name, otherwise the short name
2088 We don't implement this yet XXXX
2092 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2094 if (strequal(mask
,"????????.???"))
2097 while ((dname
= ReadDirName(dirptr
))) {
2099 pstrcpy(fname
,dname
);
2101 if(!mask_match(fname
, mask
, case_sensitive
))
2104 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
2105 error
= can_delete(fname
,conn
,dirtype
);
2106 if (!NT_STATUS_IS_OK(error
))
2108 if (vfs_unlink(conn
,fname
) == 0)
2110 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
2116 if (count
== 0 && NT_STATUS_IS_OK(error
))
2117 error
= map_nt_error_from_unix(errno
);
2122 /****************************************************************************
2124 ****************************************************************************/
2126 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2133 START_PROFILE(SMBunlink
);
2135 dirtype
= SVAL(inbuf
,smb_vwv0
);
2137 pstrcpy(name
,smb_buf(inbuf
) + 1);
2139 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
2141 DEBUG(3,("reply_unlink : %s\n",name
));
2143 status
= unlink_internals(conn
, dirtype
, name
);
2144 if (!NT_STATUS_IS_OK(status
))
2145 return ERROR_NT(status
);
2148 * Win2k needs a changenotify request response before it will
2149 * update after a rename..
2152 process_pending_change_notify_queue((time_t)0);
2154 outsize
= set_message(outbuf
,0,0,True
);
2156 END_PROFILE(SMBunlink
);
2160 /****************************************************************************
2162 ****************************************************************************/
2164 void fail_readraw(void)
2167 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2169 exit_server(errstr
);
2172 /****************************************************************************
2173 Use sendfile in readbraw.
2174 ****************************************************************************/
2176 void send_file_readbraw(connection_struct
*conn
, files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
,
2177 ssize_t mincount
, char *outbuf
)
2181 #if defined(WITH_SENDFILE)
2183 * We can only use sendfile on a non-chained packet and on a file
2184 * that is exclusively oplocked. reply_readbraw has already checked the length.
2187 if ((nread
> 0) && (lp_write_cache_size(SNUM(conn
)) == 0) &&
2188 EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) && lp_use_sendfile(SNUM(conn
)) ) {
2191 _smb_setlen(outbuf
,nread
);
2192 header
.data
= outbuf
;
2196 if ( conn
->vfs_ops
.sendfile( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, nread
) == -1) {
2198 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2199 * return ENOSYS then pretend we just got a normal read.
2201 if (errno
== ENOSYS
)
2204 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2205 fsp
->fsp_name
, strerror(errno
) ));
2206 exit_server("send_file_readbraw sendfile failed");
2215 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2220 _smb_setlen(outbuf
,ret
);
2221 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
2225 /****************************************************************************
2226 Reply to a readbraw (core+ protocol).
2227 ****************************************************************************/
2229 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
2231 ssize_t maxcount
,mincount
;
2234 char *header
= outbuf
;
2236 START_PROFILE(SMBreadbraw
);
2239 * Special check if an oplock break has been issued
2240 * and the readraw request croses on the wire, we must
2241 * return a zero length response here.
2244 if(global_oplock_break
) {
2245 _smb_setlen(header
,0);
2246 if (write_data(smbd_server_fd(),header
,4) != 4)
2248 DEBUG(5,("readbraw - oplock break finished\n"));
2249 END_PROFILE(SMBreadbraw
);
2253 fsp
= file_fsp(inbuf
,smb_vwv0
);
2255 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
2257 * fsp could be NULL here so use the value from the packet. JRA.
2259 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
2260 _smb_setlen(header
,0);
2261 if (write_data(smbd_server_fd(),header
,4) != 4)
2263 END_PROFILE(SMBreadbraw
);
2267 CHECK_FSP(fsp
,conn
);
2269 flush_write_cache(fsp
, READRAW_FLUSH
);
2271 startpos
= IVAL(inbuf
,smb_vwv1
);
2272 if(CVAL(inbuf
,smb_wct
) == 10) {
2274 * This is a large offset (64 bit) read.
2276 #ifdef LARGE_SMB_OFF_T
2278 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
2280 #else /* !LARGE_SMB_OFF_T */
2283 * Ensure we haven't been sent a >32 bit offset.
2286 if(IVAL(inbuf
,smb_vwv8
) != 0) {
2287 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2288 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
2289 _smb_setlen(header
,0);
2290 if (write_data(smbd_server_fd(),header
,4) != 4)
2292 END_PROFILE(SMBreadbraw
);
2296 #endif /* LARGE_SMB_OFF_T */
2299 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
2300 _smb_setlen(header
,0);
2301 if (write_data(smbd_server_fd(),header
,4) != 4)
2303 END_PROFILE(SMBreadbraw
);
2307 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
2308 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
2310 /* ensure we don't overrun the packet size */
2311 maxcount
= MIN(65535,maxcount
);
2312 maxcount
= MAX(mincount
,maxcount
);
2314 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2315 SMB_OFF_T size
= fsp
->size
;
2316 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
2318 if (size
< sizeneeded
) {
2320 if (vfs_fstat(fsp
,fsp
->fd
,&st
) == 0)
2321 fsp
->size
= size
= st
.st_size
;
2324 if (startpos
>= size
)
2327 nread
= MIN(maxcount
,(size
- startpos
));
2330 if (nread
< mincount
)
2333 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp
->fnum
, (double)startpos
,
2334 (int)maxcount
, (int)mincount
, (int)nread
) );
2336 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
, outbuf
);
2338 DEBUG(5,("readbraw finished\n"));
2339 END_PROFILE(SMBreadbraw
);
2343 /****************************************************************************
2344 Reply to a lockread (core+ protocol).
2345 ****************************************************************************/
2347 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
2355 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2356 START_PROFILE(SMBlockread
);
2358 CHECK_FSP(fsp
,conn
);
2361 release_level_2_oplocks_on_change(fsp
);
2363 numtoread
= SVAL(inbuf
,smb_vwv1
);
2364 startpos
= IVAL(inbuf
,smb_vwv2
);
2366 outsize
= set_message(outbuf
,5,3,True
);
2367 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2368 data
= smb_buf(outbuf
) + 3;
2371 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2372 * protocol request that predates the read/write lock concept.
2373 * Thus instead of asking for a read lock here we need to ask
2374 * for a write lock. JRA.
2377 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
),
2378 (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
);
2380 if (NT_STATUS_V(status
)) {
2381 if (lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
2383 * A blocking lock was requested. Package up
2384 * this smb into a queued request and push it
2385 * onto the blocking lock queue.
2387 if(push_blocking_lock_request(inbuf
, length
, -1, 0)) {
2388 END_PROFILE(SMBlockread
);
2392 END_PROFILE(SMBlockread
);
2393 return ERROR_NT(status
);
2396 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2399 END_PROFILE(SMBlockread
);
2400 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2404 SSVAL(outbuf
,smb_vwv0
,nread
);
2405 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2406 SSVAL(smb_buf(outbuf
),1,nread
);
2408 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2409 fsp
->fnum
, (int)numtoread
, (int)nread
) );
2411 END_PROFILE(SMBlockread
);
2415 /****************************************************************************
2417 ****************************************************************************/
2419 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2426 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2427 START_PROFILE(SMBread
);
2429 CHECK_FSP(fsp
,conn
);
2432 numtoread
= SVAL(inbuf
,smb_vwv1
);
2433 startpos
= IVAL(inbuf
,smb_vwv2
);
2435 outsize
= set_message(outbuf
,5,3,True
);
2436 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2437 data
= smb_buf(outbuf
) + 3;
2439 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2440 END_PROFILE(SMBread
);
2441 return ERROR_DOS(ERRDOS
,ERRlock
);
2445 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2448 END_PROFILE(SMBread
);
2449 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2453 SSVAL(outbuf
,smb_vwv0
,nread
);
2454 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2455 SCVAL(smb_buf(outbuf
),0,1);
2456 SSVAL(smb_buf(outbuf
),1,nread
);
2458 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2459 fsp
->fnum
, (int)numtoread
, (int)nread
) );
2461 END_PROFILE(SMBread
);
2465 /****************************************************************************
2466 Reply to a read and X - possibly using sendfile.
2467 ****************************************************************************/
2469 int send_file_readX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,
2470 files_struct
*fsp
, SMB_OFF_T startpos
, size_t smb_maxcnt
)
2473 char *data
= smb_buf(outbuf
);
2475 #if defined(WITH_SENDFILE)
2477 * We can only use sendfile on a non-chained packet and on a file
2478 * that is exclusively oplocked.
2481 if ((CVAL(inbuf
,smb_vwv0
) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) &&
2482 lp_use_sendfile(SNUM(conn
)) && (lp_write_cache_size(SNUM(conn
)) == 0) ) {
2483 SMB_STRUCT_STAT sbuf
;
2486 if(vfs_fstat(fsp
,fsp
->fd
, &sbuf
) == -1)
2487 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2489 if (startpos
> sbuf
.st_size
)
2492 if (smb_maxcnt
> (sbuf
.st_size
- startpos
))
2493 smb_maxcnt
= (sbuf
.st_size
- startpos
);
2495 if (smb_maxcnt
== 0)
2499 * Set up the packet header before send. We
2500 * assume here the sendfile will work (get the
2501 * correct amount of data).
2504 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
2505 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2506 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
2507 SCVAL(outbuf
,smb_vwv0
,0xFF);
2508 set_message(outbuf
,12,smb_maxcnt
,False
);
2509 header
.data
= outbuf
;
2510 header
.length
= data
- outbuf
;
2513 if ( conn
->vfs_ops
.sendfile( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, smb_maxcnt
) == -1) {
2515 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2516 * return ENOSYS then pretend we just got a normal read.
2518 if (errno
== ENOSYS
)
2521 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2522 fsp
->fsp_name
, strerror(errno
) ));
2523 exit_server("send_file_readX sendfile failed");
2526 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2527 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2535 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2538 END_PROFILE(SMBreadX
);
2539 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2542 SSVAL(outbuf
,smb_vwv5
,nread
);
2543 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2544 SSVAL(smb_buf(outbuf
),-2,nread
);
2546 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2547 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
2552 /****************************************************************************
2553 Reply to a read and X.
2554 ****************************************************************************/
2556 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2558 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2559 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2560 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2562 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2566 START_PROFILE(SMBreadX
);
2568 /* If it's an IPC, pass off the pipe handler. */
2570 END_PROFILE(SMBreadX
);
2571 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2574 CHECK_FSP(fsp
,conn
);
2577 set_message(outbuf
,12,0,True
);
2578 data
= smb_buf(outbuf
);
2580 if(CVAL(inbuf
,smb_wct
) == 12) {
2581 #ifdef LARGE_SMB_OFF_T
2583 * This is a large offset (64 bit) read.
2585 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2587 #else /* !LARGE_SMB_OFF_T */
2590 * Ensure we haven't been sent a >32 bit offset.
2593 if(IVAL(inbuf
,smb_vwv10
) != 0) {
2594 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2595 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
2596 END_PROFILE(SMBreadX
);
2597 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2600 #endif /* LARGE_SMB_OFF_T */
2604 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2605 END_PROFILE(SMBreadX
);
2606 return ERROR_DOS(ERRDOS
,ERRlock
);
2608 nread
= send_file_readX(conn
, inbuf
, outbuf
, length
, fsp
, startpos
, smb_maxcnt
);
2610 nread
= chain_reply(inbuf
,outbuf
,length
,bufsize
);
2612 END_PROFILE(SMBreadX
);
2616 /****************************************************************************
2617 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2618 ****************************************************************************/
2620 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2623 ssize_t total_written
=0;
2624 size_t numtowrite
=0;
2629 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2631 START_PROFILE(SMBwritebraw
);
2633 CHECK_FSP(fsp
,conn
);
2636 tcount
= IVAL(inbuf
,smb_vwv1
);
2637 startpos
= IVAL(inbuf
,smb_vwv3
);
2638 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2640 /* We have to deal with slightly different formats depending
2641 on whether we are using the core+ or lanman1.0 protocol */
2643 if(Protocol
<= PROTOCOL_COREPLUS
) {
2644 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2645 data
= smb_buf(inbuf
);
2647 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2648 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2651 /* force the error type */
2652 SCVAL(inbuf
,smb_com
,SMBwritec
);
2653 SCVAL(outbuf
,smb_com
,SMBwritec
);
2655 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2656 END_PROFILE(SMBwritebraw
);
2657 return(ERROR_DOS(ERRDOS
,ERRlock
));
2661 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2663 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2664 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2666 if (nwritten
< numtowrite
) {
2667 END_PROFILE(SMBwritebraw
);
2668 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2671 total_written
= nwritten
;
2673 /* Return a message to the redirector to tell it to send more bytes */
2674 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
2675 SSVALS(outbuf
,smb_vwv0
,-1);
2676 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2677 if (!send_smb(smbd_server_fd(),outbuf
))
2678 exit_server("reply_writebraw: send_smb failed.");
2680 /* Now read the raw data into the buffer and write it */
2681 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2682 exit_server("secondary writebraw failed");
2685 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2686 numtowrite
= smb_len(inbuf
);
2688 /* Set up outbuf to return the correct return */
2689 outsize
= set_message(outbuf
,1,0,True
);
2690 SCVAL(outbuf
,smb_com
,SMBwritec
);
2691 SSVAL(outbuf
,smb_vwv0
,total_written
);
2693 if (numtowrite
!= 0) {
2695 if (numtowrite
> BUFFER_SIZE
) {
2696 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2697 (unsigned int)numtowrite
));
2698 exit_server("secondary writebraw failed");
2701 if (tcount
> nwritten
+numtowrite
) {
2702 DEBUG(3,("Client overestimated the write %d %d %d\n",
2703 (int)tcount
,(int)nwritten
,(int)numtowrite
));
2706 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
2707 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2709 exit_server("secondary writebraw failed");
2712 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
2714 if (nwritten
< (ssize_t
)numtowrite
) {
2715 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2716 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2720 total_written
+= nwritten
;
2723 if ((lp_syncalways(SNUM(conn
)) || write_through
) && lp_strict_sync(SNUM(conn
)))
2724 sync_file(conn
,fsp
);
2726 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2727 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
2729 /* we won't return a status if write through is not selected - this follows what WfWg does */
2730 END_PROFILE(SMBwritebraw
);
2731 if (!write_through
&& total_written
==tcount
) {
2733 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2734 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2736 if (!send_keepalive(smbd_server_fd()))
2737 exit_server("reply_writebraw: send of keepalive failed");
2744 /****************************************************************************
2745 Reply to a writeunlock (core+).
2746 ****************************************************************************/
2748 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2750 ssize_t nwritten
= -1;
2755 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2757 START_PROFILE(SMBwriteunlock
);
2759 CHECK_FSP(fsp
,conn
);
2762 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2763 startpos
= IVAL(inbuf
,smb_vwv2
);
2764 data
= smb_buf(inbuf
) + 3;
2766 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
,
2767 WRITE_LOCK
,False
)) {
2768 END_PROFILE(SMBwriteunlock
);
2769 return ERROR_DOS(ERRDOS
,ERRlock
);
2772 /* The special X/Open SMB protocol handling of
2773 zero length writes is *NOT* done for
2778 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2780 if (lp_syncalways(SNUM(conn
)))
2781 sync_file(conn
,fsp
);
2783 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2784 END_PROFILE(SMBwriteunlock
);
2785 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2788 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)numtowrite
,
2789 (SMB_BIG_UINT
)startpos
);
2790 if (NT_STATUS_V(status
)) {
2791 END_PROFILE(SMBwriteunlock
);
2792 return ERROR_NT(status
);
2795 outsize
= set_message(outbuf
,1,0,True
);
2797 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2799 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2800 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
2802 END_PROFILE(SMBwriteunlock
);
2806 /****************************************************************************
2808 ****************************************************************************/
2810 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2813 ssize_t nwritten
= -1;
2816 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2818 START_PROFILE(SMBwrite
);
2820 /* If it's an IPC, pass off the pipe handler. */
2822 END_PROFILE(SMBwrite
);
2823 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2826 CHECK_FSP(fsp
,conn
);
2829 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2830 startpos
= IVAL(inbuf
,smb_vwv2
);
2831 data
= smb_buf(inbuf
) + 3;
2833 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2834 END_PROFILE(SMBwrite
);
2835 return ERROR_DOS(ERRDOS
,ERRlock
);
2839 * X/Open SMB protocol says that if smb_vwv1 is
2840 * zero then the file size should be extended or
2841 * truncated to the size given in smb_vwv[2-3].
2844 if(numtowrite
== 0) {
2846 * This is actually an allocate call, and set EOF. JRA.
2848 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2850 END_PROFILE(SMBwrite
);
2851 return ERROR_NT(NT_STATUS_DISK_FULL
);
2853 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2855 END_PROFILE(SMBwrite
);
2856 return ERROR_NT(NT_STATUS_DISK_FULL
);
2859 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2861 if (lp_syncalways(SNUM(conn
)))
2862 sync_file(conn
,fsp
);
2864 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2865 END_PROFILE(SMBwrite
);
2866 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2869 outsize
= set_message(outbuf
,1,0,True
);
2871 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2873 if (nwritten
< (ssize_t
)numtowrite
) {
2874 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2875 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2878 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2880 END_PROFILE(SMBwrite
);
2884 /****************************************************************************
2885 Reply to a write and X.
2886 ****************************************************************************/
2888 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2890 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2891 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2892 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2893 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2894 ssize_t nwritten
= -1;
2895 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2896 unsigned int smblen
= smb_len(inbuf
);
2898 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2899 START_PROFILE(SMBwriteX
);
2901 /* If it's an IPC, pass off the pipe handler. */
2903 END_PROFILE(SMBwriteX
);
2904 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2907 CHECK_FSP(fsp
,conn
);
2910 /* Deal with possible LARGE_WRITEX */
2912 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2914 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2915 END_PROFILE(SMBwriteX
);
2916 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2919 data
= smb_base(inbuf
) + smb_doff
;
2921 if(CVAL(inbuf
,smb_wct
) == 14) {
2922 #ifdef LARGE_SMB_OFF_T
2924 * This is a large offset (64 bit) write.
2926 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2928 #else /* !LARGE_SMB_OFF_T */
2931 * Ensure we haven't been sent a >32 bit offset.
2934 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2935 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2936 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2937 END_PROFILE(SMBwriteX
);
2938 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2941 #endif /* LARGE_SMB_OFF_T */
2944 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2945 END_PROFILE(SMBwriteX
);
2946 return ERROR_DOS(ERRDOS
,ERRlock
);
2949 /* X/Open SMB protocol says that, unlike SMBwrite
2950 if the length is zero then NO truncation is
2951 done, just a write of zero. To truncate a file,
2956 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2958 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2959 END_PROFILE(SMBwriteX
);
2960 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2963 set_message(outbuf
,6,0,True
);
2965 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2967 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2969 if (nwritten
< (ssize_t
)numtowrite
) {
2970 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2971 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2974 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2975 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2977 if (lp_syncalways(SNUM(conn
)) || write_through
)
2978 sync_file(conn
,fsp
);
2980 END_PROFILE(SMBwriteX
);
2981 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2985 /****************************************************************************
2987 ****************************************************************************/
2989 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2995 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2996 START_PROFILE(SMBlseek
);
2998 CHECK_FSP(fsp
,conn
);
3000 flush_write_cache(fsp
, SEEK_FLUSH
);
3002 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
3003 startpos
= IVALS(inbuf
,smb_vwv2
);
3006 case 0: umode
= SEEK_SET
; break;
3007 case 1: umode
= SEEK_CUR
; break;
3008 case 2: umode
= SEEK_END
; break;
3010 umode
= SEEK_SET
; break;
3013 if((res
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
3015 * Check for the special case where a seek before the start
3016 * of the file sets the offset to zero. Added in the CIFS spec,
3020 if(errno
== EINVAL
) {
3021 SMB_OFF_T current_pos
= startpos
;
3023 if(umode
== SEEK_CUR
) {
3025 if((current_pos
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,0,SEEK_CUR
)) == -1) {
3026 END_PROFILE(SMBlseek
);
3027 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3030 current_pos
+= startpos
;
3032 } else if (umode
== SEEK_END
) {
3034 SMB_STRUCT_STAT sbuf
;
3036 if(vfs_fstat(fsp
,fsp
->fd
, &sbuf
) == -1) {
3037 END_PROFILE(SMBlseek
);
3038 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3041 current_pos
+= sbuf
.st_size
;
3045 res
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,0,SEEK_SET
);
3049 END_PROFILE(SMBlseek
);
3050 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3056 outsize
= set_message(outbuf
,2,0,True
);
3057 SIVAL(outbuf
,smb_vwv0
,res
);
3059 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3060 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
3062 END_PROFILE(SMBlseek
);
3066 /****************************************************************************
3068 ****************************************************************************/
3070 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
3072 int outsize
= set_message(outbuf
,0,0,True
);
3073 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3074 START_PROFILE(SMBflush
);
3076 CHECK_FSP(fsp
,conn
);
3079 file_sync_all(conn
);
3081 sync_file(conn
,fsp
);
3084 DEBUG(3,("flush\n"));
3085 END_PROFILE(SMBflush
);
3089 /****************************************************************************
3091 ****************************************************************************/
3093 int reply_exit(connection_struct
*conn
,
3094 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3097 START_PROFILE(SMBexit
);
3098 outsize
= set_message(outbuf
,0,0,True
);
3100 DEBUG(3,("exit\n"));
3102 END_PROFILE(SMBexit
);
3107 /****************************************************************************
3108 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3109 ****************************************************************************/
3111 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
3116 files_struct
*fsp
= NULL
;
3117 START_PROFILE(SMBclose
);
3119 outsize
= set_message(outbuf
,0,0,True
);
3121 /* If it's an IPC, pass off to the pipe handler. */
3123 END_PROFILE(SMBclose
);
3124 return reply_pipe_close(conn
, inbuf
,outbuf
);
3127 fsp
= file_fsp(inbuf
,smb_vwv0
);
3130 * We can only use CHECK_FSP if we know it's not a directory.
3133 if(!fsp
|| (fsp
->conn
!= conn
)) {
3134 END_PROFILE(SMBclose
);
3135 return ERROR_DOS(ERRDOS
,ERRbadfid
);
3138 if(fsp
->is_directory
) {
3140 * Special case - close NT SMB directory handle.
3142 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
3143 close_file(fsp
,True
);
3146 * Close ordinary file.
3151 /* Save the name for time set in close. */
3152 pstrcpy( file_name
, fsp
->fsp_name
);
3154 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3156 conn
->num_files_open
));
3159 * close_file() returns the unix errno if an error
3160 * was detected on close - normally this is due to
3161 * a disk full error. If not then it was probably an I/O error.
3164 if((close_err
= close_file(fsp
,True
)) != 0) {
3166 END_PROFILE(SMBclose
);
3167 return (UNIXERROR(ERRHRD
,ERRgeneral
));
3171 * Now take care of any time sent in the close.
3174 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
3176 /* try and set the date */
3177 set_filetime(conn
, file_name
, mtime
);
3181 END_PROFILE(SMBclose
);
3185 /****************************************************************************
3186 Reply to a writeclose (Core+ protocol)
3187 ****************************************************************************/
3189 int reply_writeclose(connection_struct
*conn
,
3190 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
3193 ssize_t nwritten
= -1;
3199 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3200 START_PROFILE(SMBwriteclose
);
3202 CHECK_FSP(fsp
,conn
);
3205 numtowrite
= SVAL(inbuf
,smb_vwv1
);
3206 startpos
= IVAL(inbuf
,smb_vwv2
);
3207 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
3208 data
= smb_buf(inbuf
) + 1;
3210 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
3211 END_PROFILE(SMBwriteclose
);
3212 return ERROR_DOS(ERRDOS
,ERRlock
);
3215 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
3217 set_filetime(conn
, fsp
->fsp_name
,mtime
);
3219 close_err
= close_file(fsp
,True
);
3221 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3222 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
3223 conn
->num_files_open
));
3225 if (nwritten
<= 0) {
3226 END_PROFILE(SMBwriteclose
);
3227 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3230 if(close_err
!= 0) {
3232 END_PROFILE(SMBwriteclose
);
3233 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3236 outsize
= set_message(outbuf
,1,0,True
);
3238 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3239 END_PROFILE(SMBwriteclose
);
3243 /****************************************************************************
3245 ****************************************************************************/
3247 int reply_lock(connection_struct
*conn
,
3248 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
3250 int outsize
= set_message(outbuf
,0,0,True
);
3251 SMB_BIG_UINT count
,offset
;
3253 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3254 START_PROFILE(SMBlock
);
3256 CHECK_FSP(fsp
,conn
);
3258 release_level_2_oplocks_on_change(fsp
);
3260 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
3261 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
3263 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3264 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
3266 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
, WRITE_LOCK
);
3267 if (NT_STATUS_V(status
)) {
3268 if (lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
3270 * A blocking lock was requested. Package up
3271 * this smb into a queued request and push it
3272 * onto the blocking lock queue.
3274 if(push_blocking_lock_request(inbuf
, length
, -1, 0)) {
3275 END_PROFILE(SMBlock
);
3279 END_PROFILE(SMBlock
);
3280 return ERROR_NT(status
);
3283 END_PROFILE(SMBlock
);
3287 /****************************************************************************
3289 ****************************************************************************/
3291 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
3293 int outsize
= set_message(outbuf
,0,0,True
);
3294 SMB_BIG_UINT count
,offset
;
3296 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3297 START_PROFILE(SMBunlock
);
3299 CHECK_FSP(fsp
,conn
);
3301 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
3302 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
3304 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
);
3305 if (NT_STATUS_V(status
)) {
3306 END_PROFILE(SMBunlock
);
3307 return ERROR_NT(status
);
3310 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3311 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
3313 END_PROFILE(SMBunlock
);
3317 /****************************************************************************
3319 ****************************************************************************/
3321 int reply_tdis(connection_struct
*conn
,
3322 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3324 int outsize
= set_message(outbuf
,0,0,True
);
3326 START_PROFILE(SMBtdis
);
3328 vuid
= SVAL(inbuf
,smb_uid
);
3331 DEBUG(4,("Invalid connection in tdis\n"));
3332 END_PROFILE(SMBtdis
);
3333 return ERROR_DOS(ERRSRV
,ERRinvnid
);
3338 close_cnum(conn
,vuid
);
3340 END_PROFILE(SMBtdis
);
3344 /****************************************************************************
3346 ****************************************************************************/
3348 int reply_echo(connection_struct
*conn
,
3349 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3351 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
3353 unsigned int data_len
= smb_buflen(inbuf
);
3354 int outsize
= set_message(outbuf
,1,data_len
,True
);
3355 START_PROFILE(SMBecho
);
3357 data_len
= MIN(data_len
, (sizeof(inbuf
)-(smb_buf(inbuf
)-inbuf
)));
3359 /* copy any incoming data back out */
3361 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
3363 if (smb_reverb
> 100) {
3364 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
3368 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
3369 SSVAL(outbuf
,smb_vwv0
,seq_num
);
3371 smb_setlen(outbuf
,outsize
- 4);
3373 if (!send_smb(smbd_server_fd(),outbuf
))
3374 exit_server("reply_echo: send_smb failed.");
3377 DEBUG(3,("echo %d times\n", smb_reverb
));
3381 END_PROFILE(SMBecho
);
3385 /****************************************************************************
3386 Reply to a printopen.
3387 ****************************************************************************/
3389 int reply_printopen(connection_struct
*conn
,
3390 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3394 START_PROFILE(SMBsplopen
);
3396 if (!CAN_PRINT(conn
)) {
3397 END_PROFILE(SMBsplopen
);
3398 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3401 /* Open for exclusive use, write only. */
3402 fsp
= print_fsp_open(conn
, NULL
);
3405 END_PROFILE(SMBsplopen
);
3406 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3409 outsize
= set_message(outbuf
,1,0,True
);
3410 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
3412 DEBUG(3,("openprint fd=%d fnum=%d\n",
3413 fsp
->fd
, fsp
->fnum
));
3415 END_PROFILE(SMBsplopen
);
3419 /****************************************************************************
3420 Reply to a printclose.
3421 ****************************************************************************/
3423 int reply_printclose(connection_struct
*conn
,
3424 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3426 int outsize
= set_message(outbuf
,0,0,True
);
3427 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3429 START_PROFILE(SMBsplclose
);
3431 CHECK_FSP(fsp
,conn
);
3433 if (!CAN_PRINT(conn
)) {
3434 END_PROFILE(SMBsplclose
);
3435 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3438 DEBUG(3,("printclose fd=%d fnum=%d\n",
3439 fsp
->fd
,fsp
->fnum
));
3441 close_err
= close_file(fsp
,True
);
3443 if(close_err
!= 0) {
3445 END_PROFILE(SMBsplclose
);
3446 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3449 END_PROFILE(SMBsplclose
);
3453 /****************************************************************************
3454 Reply to a printqueue.
3455 ****************************************************************************/
3457 int reply_printqueue(connection_struct
*conn
,
3458 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3460 int outsize
= set_message(outbuf
,2,3,True
);
3461 int max_count
= SVAL(inbuf
,smb_vwv0
);
3462 int start_index
= SVAL(inbuf
,smb_vwv1
);
3463 START_PROFILE(SMBsplretq
);
3465 /* we used to allow the client to get the cnum wrong, but that
3466 is really quite gross and only worked when there was only
3467 one printer - I think we should now only accept it if they
3468 get it right (tridge) */
3469 if (!CAN_PRINT(conn
)) {
3470 END_PROFILE(SMBsplretq
);
3471 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3474 SSVAL(outbuf
,smb_vwv0
,0);
3475 SSVAL(outbuf
,smb_vwv1
,0);
3476 SCVAL(smb_buf(outbuf
),0,1);
3477 SSVAL(smb_buf(outbuf
),1,0);
3479 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3480 start_index
, max_count
));
3483 print_queue_struct
*queue
= NULL
;
3484 print_status_struct status
;
3485 char *p
= smb_buf(outbuf
) + 3;
3486 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
3487 int num_to_get
= ABS(max_count
);
3488 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
3494 num_to_get
= MIN(num_to_get
,count
-first
);
3497 for (i
=first
;i
<first
+num_to_get
;i
++) {
3498 put_dos_date2(p
,0,queue
[i
].time
);
3499 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
3500 SSVAL(p
,5, queue
[i
].job
);
3501 SIVAL(p
,7,queue
[i
].size
);
3503 StrnCpy(p
+12,queue
[i
].fs_user
,16);
3508 outsize
= set_message(outbuf
,2,28*count
+3,False
);
3509 SSVAL(outbuf
,smb_vwv0
,count
);
3510 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
3511 SCVAL(smb_buf(outbuf
),0,1);
3512 SSVAL(smb_buf(outbuf
),1,28*count
);
3517 DEBUG(3,("%d entries returned in queue\n",count
));
3520 END_PROFILE(SMBsplretq
);
3524 /****************************************************************************
3525 Reply to a printwrite.
3526 ****************************************************************************/
3528 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3531 int outsize
= set_message(outbuf
,0,0,True
);
3533 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3534 START_PROFILE(SMBsplwr
);
3536 if (!CAN_PRINT(conn
)) {
3537 END_PROFILE(SMBsplwr
);
3538 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3541 CHECK_FSP(fsp
,conn
);
3544 numtowrite
= SVAL(smb_buf(inbuf
),1);
3545 data
= smb_buf(inbuf
) + 3;
3547 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
3548 END_PROFILE(SMBsplwr
);
3549 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3552 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
3554 END_PROFILE(SMBsplwr
);
3558 /****************************************************************************
3559 The guts of the mkdir command, split out so it may be called by the NT SMB
3561 ****************************************************************************/
3563 NTSTATUS
mkdir_internal(connection_struct
*conn
, pstring directory
)
3565 BOOL bad_path
= False
;
3566 SMB_STRUCT_STAT sbuf
;
3569 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3571 if (check_name(directory
, conn
))
3572 ret
= vfs_mkdir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3575 NTSTATUS nterr
= set_bad_path_error(errno
, bad_path
);
3576 if (!NT_STATUS_IS_OK(nterr
))
3578 return map_nt_error_from_unix(errno
);
3581 return NT_STATUS_OK
;
3584 /****************************************************************************
3586 ****************************************************************************/
3588 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3593 START_PROFILE(SMBmkdir
);
3595 pstrcpy(directory
,smb_buf(inbuf
) + 1);
3597 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
);
3599 status
= mkdir_internal(conn
, directory
);
3600 if (!NT_STATUS_IS_OK(status
))
3601 return ERROR_NT(status
);
3603 outsize
= set_message(outbuf
,0,0,True
);
3605 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
3607 END_PROFILE(SMBmkdir
);
3611 /****************************************************************************
3612 Static function used by reply_rmdir to delete an entire directory
3613 tree recursively. Return False on ok, True on fail.
3614 ****************************************************************************/
3616 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
3620 void *dirptr
= OpenDir(conn
, directory
, False
);
3625 while((dname
= ReadDirName(dirptr
))) {
3629 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3632 /* Construct the full name. */
3633 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3639 pstrcpy(fullname
, directory
);
3640 pstrcat(fullname
, "/");
3641 pstrcat(fullname
, dname
);
3643 if(conn
->vfs_ops
.lstat(conn
,dos_to_unix_static(fullname
), &st
) != 0) {
3648 if(st
.st_mode
& S_IFDIR
) {
3649 if(recursive_rmdir(conn
, fullname
)!=0) {
3653 if(vfs_rmdir(conn
,fullname
) != 0) {
3657 } else if(vfs_unlink(conn
,fullname
) != 0) {
3667 /****************************************************************************
3668 The internals of the rmdir code - called elsewhere.
3669 ****************************************************************************/
3671 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
3675 ok
= (vfs_rmdir(conn
,directory
) == 0);
3676 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
3678 * Check to see if the only thing in this directory are
3679 * vetoed files/directories. If so then delete them and
3680 * retry. If we fail to delete any of them (and we *don't*
3681 * do a recursive delete) then fail the rmdir.
3683 BOOL all_veto_files
= True
;
3685 void *dirptr
= OpenDir(conn
, directory
, False
);
3687 if(dirptr
!= NULL
) {
3688 int dirpos
= TellDir(dirptr
);
3689 while ((dname
= ReadDirName(dirptr
))) {
3690 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3692 if(!IS_VETO_PATH(conn
, dname
)) {
3693 all_veto_files
= False
;
3697 if(all_veto_files
) {
3698 SeekDir(dirptr
,dirpos
);
3699 while ((dname
= ReadDirName(dirptr
))) {
3703 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3706 /* Construct the full name. */
3707 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3711 pstrcpy(fullname
, directory
);
3712 pstrcat(fullname
, "/");
3713 pstrcat(fullname
, dname
);
3715 if(conn
->vfs_ops
.lstat(conn
,dos_to_unix_static(fullname
), &st
) != 0)
3717 if(st
.st_mode
& S_IFDIR
) {
3718 if(lp_recursive_veto_delete(SNUM(conn
))) {
3719 if(recursive_rmdir(conn
, fullname
) != 0)
3722 if(vfs_rmdir(conn
,fullname
) != 0)
3724 } else if(vfs_unlink(conn
,fullname
) != 0)
3728 /* Retry the rmdir */
3729 ok
= (vfs_rmdir(conn
,directory
) == 0);
3739 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory
,strerror(errno
)));
3744 /****************************************************************************
3746 ****************************************************************************/
3748 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3753 BOOL bad_path
= False
;
3754 SMB_STRUCT_STAT sbuf
;
3755 START_PROFILE(SMBrmdir
);
3757 pstrcpy(directory
,smb_buf(inbuf
) + 1);
3759 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3761 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3763 if (check_name(directory
,conn
))
3765 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3766 ok
= rmdir_internals(conn
, directory
);
3771 set_bad_path_error(errno
, bad_path
);
3772 END_PROFILE(SMBrmdir
);
3773 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3776 outsize
= set_message(outbuf
,0,0,True
);
3778 DEBUG( 3, ( "rmdir %s\n", directory
) );
3780 END_PROFILE(SMBrmdir
);
3784 /*******************************************************************
3785 Resolve wildcards in a filename rename.
3786 ********************************************************************/
3788 static BOOL
resolve_wildcards(char *name1
,char *name2
)
3790 fstring root1
,root2
;
3794 name1
= strrchr(name1
,'/');
3795 name2
= strrchr(name2
,'/');
3797 if (!name1
|| !name2
) return(False
);
3799 fstrcpy(root1
,name1
);
3800 fstrcpy(root2
,name2
);
3801 p
= strrchr(root1
,'.');
3808 p
= strrchr(root2
,'.');
3840 pstrcpy(name2
,root2
);
3843 pstrcat(name2
,ext2
);
3849 /****************************************************************************
3850 The guts of the rename command, split out so it may be called by the NT SMB
3852 ****************************************************************************/
3854 NTSTATUS
rename_internals(connection_struct
*conn
, char *name
, char *newname
, BOOL replace_if_exists
)
3858 pstring newname_last_component
;
3861 BOOL bad_path1
= False
;
3862 BOOL bad_path2
= False
;
3864 NTSTATUS error
= NT_STATUS_OK
;
3866 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3868 *directory
= *mask
= 0;
3870 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
3871 unix_convert(newname
,conn
,newname_last_component
,&bad_path2
,&sbuf2
);
3874 * Split the old name into directory and last component
3875 * strings. Note that unix_convert may have stripped off a
3876 * leading ./ from both name and newname if the rename is
3877 * at the root of the share. We need to make sure either both
3878 * name and newname contain a / character or neither of them do
3879 * as this is checked in resolve_wildcards().
3882 p
= strrchr(name
,'/');
3884 pstrcpy(directory
,".");
3888 pstrcpy(directory
,name
);
3890 *p
= '/'; /* Replace needed for exceptional test below. */
3894 * We should only check the mangled cache
3895 * here if unix_convert failed. This means
3896 * that the path in 'mask' doesn't exist
3897 * on the file system and so we need to look
3898 * for a possible mangle. This patch from
3899 * Tine Smukavec <valentin.smukavec@hermes.si>.
3902 if (!rc
&& mangle_is_mangled(mask
))
3903 mangle_check_cache( mask
);
3905 has_wild
= ms_has_wild(mask
);
3912 * No wildcards - just process the one file.
3914 BOOL is_short_name
= mangle_is_8_3(name
, True
);
3916 /* Add a terminating '/' to the directory name. */
3917 pstrcat(directory
,"/");
3918 pstrcat(directory
,mask
);
3920 /* Ensure newname contains a '/' also */
3921 if(strrchr(newname
,'/') == 0) {
3924 pstrcpy(tmpstr
, "./");
3925 pstrcat(tmpstr
, newname
);
3926 pstrcpy(newname
, tmpstr
);
3929 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3930 directory = %s, newname = %s, newname_last_component = %s, mangle_is_8_3 = %d\n",
3931 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3932 newname
, newname_last_component
, is_short_name
));
3935 * Check for special case with case preserving and not
3936 * case sensitive, if directory and newname are identical,
3937 * and the old last component differs from the original
3938 * last component only by case, then we should allow
3939 * the rename (user is trying to change the case of the
3942 if((case_sensitive
== False
) &&
3943 (((case_preserve
== True
) &&
3944 (is_short_name
== False
)) ||
3945 ((short_case_preserve
== True
) &&
3946 (is_short_name
== True
))) &&
3947 strcsequal(directory
, newname
)) {
3948 pstring newname_modified_last_component
;
3951 * Get the last component of the modified name.
3952 * Note that we guarantee that newname contains a '/'
3955 p
= strrchr(newname
,'/');
3956 pstrcpy(newname_modified_last_component
,p
+1);
3958 if(strcsequal(newname_modified_last_component
,
3959 newname_last_component
) == False
) {
3961 * Replace the modified last component with
3964 pstrcpy(p
+1, newname_last_component
);
3969 resolve_wildcards(directory
,newname
);
3972 * The source object must exist.
3975 if (!vfs_object_exist(conn
, directory
, &sbuf1
)) {
3976 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3977 directory
,newname
));
3979 if (errno
== ENOTDIR
|| errno
== EISDIR
|| errno
== ENOENT
) {
3981 * Must return different errors depending on whether the parent
3982 * directory existed or not.
3985 p
= strrchr(directory
, '/');
3987 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3989 if (vfs_object_exist(conn
, directory
, NULL
))
3990 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3991 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3993 error
= map_nt_error_from_unix(errno
);
3994 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3995 get_nt_error_msg(error
), directory
,newname
));
4000 error
= can_rename(directory
,conn
,&sbuf1
);
4002 if (!NT_STATUS_IS_OK(error
)) {
4003 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4004 get_nt_error_msg(error
), directory
,newname
));
4008 pstrcpy(zdirectory
, dos_to_unix_static(directory
));
4009 pstrcpy(znewname
, dos_to_unix_static(newname
));
4012 * If the src and dest names are identical - including case,
4013 * don't do the rename, just return success.
4016 if (strcsequal(zdirectory
, znewname
)) {
4017 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory
));
4018 return NT_STATUS_OK
;
4021 if(!replace_if_exists
&& vfs_object_exist(conn
,newname
,NULL
)) {
4022 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4023 directory
,newname
));
4024 return NT_STATUS_OBJECT_NAME_COLLISION
;
4027 if(conn
->vfs_ops
.rename(conn
,zdirectory
, znewname
) == 0) {
4028 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4029 directory
,newname
));
4030 return NT_STATUS_OK
;
4033 if (errno
== ENOTDIR
|| errno
== EISDIR
)
4034 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
4036 error
= map_nt_error_from_unix(errno
);
4038 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4039 get_nt_error_msg(error
), directory
,newname
));
4045 * Wildcards - process each file that matches.
4047 void *dirptr
= NULL
;
4051 if (check_name(directory
,conn
))
4052 dirptr
= OpenDir(conn
, directory
, True
);
4055 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4057 if (strequal(mask
,"????????.???"))
4060 while ((dname
= ReadDirName(dirptr
))) {
4063 pstrcpy(fname
,dname
);
4065 if(!mask_match(fname
, mask
, case_sensitive
))
4068 error
= NT_STATUS_ACCESS_DENIED
;
4069 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
4070 if (!vfs_object_exist(conn
, fname
, &sbuf1
)) {
4071 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4072 DEBUG(6,("rename %s failed. Error %s\n", fname
, get_nt_error_msg(error
)));
4075 error
= can_rename(fname
,conn
,&sbuf1
);
4076 if (!NT_STATUS_IS_OK(error
)) {
4077 DEBUG(6,("rename %s failed. Error %s\n", fname
, get_nt_error_msg(error
)));
4080 pstrcpy(destname
,newname
);
4082 if (!resolve_wildcards(fname
,destname
)) {
4083 DEBUG(6,("resolve_wildcards %s %s failed\n",
4088 if (!replace_if_exists
&&
4089 vfs_object_exist(conn
,destname
, NULL
)) {
4090 DEBUG(6,("file_exist %s\n", destname
));
4091 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
4095 if (!conn
->vfs_ops
.rename(conn
,dos_to_unix_static(fname
),
4096 dos_to_unix_static(destname
)))
4098 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
4104 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
4105 error
= map_nt_error_from_unix(errno
);
4111 /****************************************************************************
4113 ****************************************************************************/
4115 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4121 START_PROFILE(SMBmv
);
4123 pstrcpy(name
,smb_buf(inbuf
) + 1);
4124 pstrcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
4126 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
4127 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
4129 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
4131 status
= rename_internals(conn
, name
, newname
, False
);
4132 if (!NT_STATUS_IS_OK(status
)) {
4133 return ERROR_NT(status
);
4137 * Win2k needs a changenotify request response before it will
4138 * update after a rename..
4140 process_pending_change_notify_queue((time_t)0);
4141 outsize
= set_message(outbuf
,0,0,True
);
4147 /*******************************************************************
4148 Copy a file as part of a reply_copy.
4149 ******************************************************************/
4151 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
4152 int count
,BOOL target_is_directory
, int *err_ret
)
4155 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
4157 files_struct
*fsp1
,*fsp2
;
4162 pstrcpy(dest
,dest1
);
4163 if (target_is_directory
) {
4164 char *p
= strrchr(src
,'/');
4173 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
4176 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
4177 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
4182 if (!target_is_directory
&& count
)
4183 ofun
= FILE_EXISTS_OPEN
;
4185 if (vfs_stat(conn
,dest
,&sbuf2
) == -1)
4186 ZERO_STRUCTP(&sbuf2
);
4188 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
4189 ofun
,src_sbuf
.st_mode
,0,&Access
,&action
);
4192 close_file(fsp1
,False
);
4196 if ((ofun
&3) == 1) {
4197 if(conn
->vfs_ops
.lseek(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
4198 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
4200 * Stop the copy from occurring.
4203 src_sbuf
.st_size
= 0;
4207 if (src_sbuf
.st_size
)
4208 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
4210 close_file(fsp1
,False
);
4212 /* Ensure the modtime is set correctly on the destination file. */
4213 fsp2
->pending_modtime
= src_sbuf
.st_mtime
;
4216 * As we are opening fsp1 read-only we only expect
4217 * an error on close on fsp2 if we are out of space.
4218 * Thus we don't look at the error return from the
4221 *err_ret
= close_file(fsp2
,False
);
4223 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
4226 /****************************************************************************
4227 Reply to a file copy.
4228 ****************************************************************************/
4230 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4235 pstring mask
,newname
;
4238 int error
= ERRnoaccess
;
4242 int tid2
= SVAL(inbuf
,smb_vwv0
);
4243 int ofun
= SVAL(inbuf
,smb_vwv1
);
4244 int flags
= SVAL(inbuf
,smb_vwv2
);
4245 BOOL target_is_directory
=False
;
4246 BOOL bad_path1
= False
;
4247 BOOL bad_path2
= False
;
4249 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4250 START_PROFILE(SMBcopy
);
4252 *directory
= *mask
= 0;
4254 pstrcpy(name
,smb_buf(inbuf
));
4255 pstrcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
4257 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
4259 if (tid2
!= conn
->cnum
) {
4260 /* can't currently handle inter share copies XXXX */
4261 DEBUG(3,("Rejecting inter-share copy\n"));
4262 END_PROFILE(SMBcopy
);
4263 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
4266 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
4267 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
4269 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
4270 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
4272 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
4274 if ((flags
&1) && target_is_directory
) {
4275 END_PROFILE(SMBcopy
);
4276 return ERROR_DOS(ERRDOS
,ERRbadfile
);
4279 if ((flags
&2) && !target_is_directory
) {
4280 END_PROFILE(SMBcopy
);
4281 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4284 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
4285 /* wants a tree copy! XXXX */
4286 DEBUG(3,("Rejecting tree copy\n"));
4287 END_PROFILE(SMBcopy
);
4288 return ERROR_DOS(ERRSRV
,ERRerror
);
4291 p
= strrchr(name
,'/');
4293 pstrcpy(directory
,"./");
4297 pstrcpy(directory
,name
);
4302 * We should only check the mangled cache
4303 * here if unix_convert failed. This means
4304 * that the path in 'mask' doesn't exist
4305 * on the file system and so we need to look
4306 * for a possible mangle. This patch from
4307 * Tine Smukavec <valentin.smukavec@hermes.si>.
4310 if (!rc
&& mangle_is_mangled(mask
))
4311 mangle_check_cache( mask
);
4313 has_wild
= ms_has_wild(mask
);
4316 pstrcat(directory
,"/");
4317 pstrcat(directory
,mask
);
4318 if (resolve_wildcards(directory
,newname
) &&
4319 copy_file(directory
,newname
,conn
,ofun
,
4320 count
,target_is_directory
,&err
)) count
++;
4323 END_PROFILE(SMBcopy
);
4324 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4326 if (!count
) exists
= vfs_file_exist(conn
,directory
,NULL
);
4328 void *dirptr
= NULL
;
4332 if (check_name(directory
,conn
))
4333 dirptr
= OpenDir(conn
, directory
, True
);
4338 if (strequal(mask
,"????????.???"))
4341 while ((dname
= ReadDirName(dirptr
))) {
4343 pstrcpy(fname
,dname
);
4345 if(!mask_match(fname
, mask
, case_sensitive
))
4348 error
= ERRnoaccess
;
4349 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
4350 pstrcpy(destname
,newname
);
4351 if (resolve_wildcards(fname
,destname
) &&
4352 copy_file(fname
,destname
,conn
,ofun
,
4353 count
,target_is_directory
,&err
)) count
++;
4354 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
4362 /* Error on close... */
4364 END_PROFILE(SMBcopy
);
4365 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4369 END_PROFILE(SMBcopy
);
4370 return ERROR_DOS(ERRDOS
,error
);
4373 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
4375 unix_ERR_class
= ERRDOS
;
4376 unix_ERR_code
= ERRbadpath
;
4378 END_PROFILE(SMBcopy
);
4379 return(UNIXERROR(ERRDOS
,error
));
4383 outsize
= set_message(outbuf
,1,0,True
);
4384 SSVAL(outbuf
,smb_vwv0
,count
);
4386 END_PROFILE(SMBcopy
);
4390 /****************************************************************************
4392 ****************************************************************************/
4394 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4400 START_PROFILE(pathworks_setdir
);
4403 if (!CAN_SETDIR(snum
)) {
4404 END_PROFILE(pathworks_setdir
);
4405 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4408 pstrcpy(newdir
,smb_buf(inbuf
) + 1);
4411 if (strlen(newdir
) == 0) {
4414 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
4416 string_set(&conn
->connectpath
,newdir
);
4421 END_PROFILE(pathworks_setdir
);
4422 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4425 outsize
= set_message(outbuf
,0,0,True
);
4426 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
4428 DEBUG(3,("setdir %s\n", newdir
));
4430 END_PROFILE(pathworks_setdir
);
4434 /****************************************************************************
4435 Get a lock pid, dealing with large count requests.
4436 ****************************************************************************/
4438 uint16
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
4440 if(!large_file_format
)
4441 return SVAL(data
,SMB_LPID_OFFSET(data_offset
));
4443 return SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
4446 /****************************************************************************
4447 Get a lock count, dealing with large count requests.
4448 ****************************************************************************/
4450 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
4452 SMB_BIG_UINT count
= 0;
4454 if(!large_file_format
) {
4455 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
4458 #if defined(HAVE_LONGLONG)
4459 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
4460 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
4461 #else /* HAVE_LONGLONG */
4464 * NT4.x seems to be broken in that it sends large file (64 bit)
4465 * lockingX calls even if the CAP_LARGE_FILES was *not*
4466 * negotiated. For boxes without large unsigned ints truncate the
4467 * lock count by dropping the top 32 bits.
4470 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
4471 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4472 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
4473 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
4474 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
4477 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
4478 #endif /* HAVE_LONGLONG */
4484 #if !defined(HAVE_LONGLONG)
4485 /****************************************************************************
4486 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4487 ****************************************************************************/
4489 static uint32
map_lock_offset(uint32 high
, uint32 low
)
4493 uint32 highcopy
= high
;
4496 * Try and find out how many significant bits there are in high.
4499 for(i
= 0; highcopy
; i
++)
4503 * We use 31 bits not 32 here as POSIX
4504 * lock offsets may not be negative.
4507 mask
= (~0) << (31 - i
);
4510 return 0; /* Fail. */
4516 #endif /* !defined(HAVE_LONGLONG) */
4518 /****************************************************************************
4519 Get a lock offset, dealing with large offset requests.
4520 ****************************************************************************/
4522 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
4524 SMB_BIG_UINT offset
= 0;
4528 if(!large_file_format
) {
4529 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
4532 #if defined(HAVE_LONGLONG)
4533 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
4534 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
4535 #else /* HAVE_LONGLONG */
4538 * NT4.x seems to be broken in that it sends large file (64 bit)
4539 * lockingX calls even if the CAP_LARGE_FILES was *not*
4540 * negotiated. For boxes without large unsigned ints mangle the
4541 * lock offset by mapping the top 32 bits onto the lower 32.
4544 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
4545 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4546 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
4549 if((new_low
= map_lock_offset(high
, low
)) == 0) {
4551 return (SMB_BIG_UINT
)-1;
4554 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4555 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
4556 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
4557 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
4560 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4561 #endif /* HAVE_LONGLONG */
4567 /****************************************************************************
4568 Reply to a lockingX request.
4569 ****************************************************************************/
4571 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4573 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
4574 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
4575 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
4576 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
4577 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
4578 SMB_BIG_UINT count
= 0, offset
= 0;
4580 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
4583 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
4587 START_PROFILE(SMBlockingX
);
4589 CHECK_FSP(fsp
,conn
);
4591 data
= smb_buf(inbuf
);
4593 if (locktype
& (LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_CHANGE_LOCKTYPE
)) {
4594 /* we don't support these - and CANCEL_LOCK makes w2k
4595 and XP reboot so I don't really want to be
4596 compatible! (tridge) */
4597 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
4600 /* Check if this is an oplock break on a file
4601 we have granted an oplock on.
4603 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
4604 /* Client can insist on breaking to none. */
4605 BOOL break_to_none
= (oplocklevel
== 0);
4607 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4608 (unsigned int)oplocklevel
, fsp
->fnum
));
4611 * Make sure we have granted an exclusive or batch oplock on this file.
4614 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
4615 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4616 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
4618 /* if this is a pure oplock break request then don't send a reply */
4619 if (num_locks
== 0 && num_ulocks
== 0) {
4620 END_PROFILE(SMBlockingX
);
4623 END_PROFILE(SMBlockingX
);
4624 return ERROR_DOS(ERRDOS
,ERRlock
);
4628 if (remove_oplock(fsp
, break_to_none
) == False
) {
4629 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4633 /* if this is a pure oplock break request then don't send a reply */
4634 if (num_locks
== 0 && num_ulocks
== 0) {
4635 /* Sanity check - ensure a pure oplock break is not a
4637 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
4638 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4639 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
4640 END_PROFILE(SMBlockingX
);
4646 * We do this check *after* we have checked this is not a oplock break
4647 * response message. JRA.
4650 release_level_2_oplocks_on_change(fsp
);
4652 /* Data now points at the beginning of the list
4653 of smb_unlkrng structs */
4654 for(i
= 0; i
< (int)num_ulocks
; i
++) {
4655 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4656 count
= get_lock_count( data
, i
, large_file_format
);
4657 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4660 * There is no error code marked "stupid client bug".... :-).
4663 END_PROFILE(SMBlockingX
);
4664 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4667 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4668 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
4670 status
= do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4671 if (NT_STATUS_V(status
)) {
4672 END_PROFILE(SMBlockingX
);
4673 return ERROR_NT(status
);
4677 /* Setup the timeout in seconds. */
4679 lock_timeout
= ((lock_timeout
== -1) ? -1 : (lock_timeout
+999)/1000);
4681 /* Now do any requested locks */
4682 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
4684 /* Data now points at the beginning of the list
4685 of smb_lkrng structs */
4687 for(i
= 0; i
< (int)num_locks
; i
++) {
4688 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4689 count
= get_lock_count( data
, i
, large_file_format
);
4690 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4693 * There is no error code marked "stupid client bug".... :-).
4696 END_PROFILE(SMBlockingX
);
4697 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4700 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4701 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
,
4702 (int)lock_timeout
));
4704 status
= do_lock_spin(fsp
,conn
,lock_pid
, count
,offset
,
4705 ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
));
4707 if (NT_STATUS_V(status
)) {
4708 if ((lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
4710 * A blocking lock was requested. Package up
4711 * this smb into a queued request and push it
4712 * onto the blocking lock queue.
4714 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
)) {
4715 END_PROFILE(SMBlockingX
);
4723 /* If any of the above locks failed, then we must unlock
4724 all of the previous locks (X/Open spec). */
4725 if(i
!= num_locks
&& num_locks
!= 0) {
4727 * Ensure we don't do a remove on the lock that just failed,
4728 * as under POSIX rules, if we have a lock already there, we
4729 * will delete it (and we shouldn't) .....
4731 for(i
--; i
>= 0; i
--) {
4732 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4733 count
= get_lock_count( data
, i
, large_file_format
);
4734 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4737 * There is no error code marked "stupid client bug".... :-).
4740 END_PROFILE(SMBlockingX
);
4741 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4744 do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4746 END_PROFILE(SMBlockingX
);
4747 return ERROR_NT(status
);
4750 set_message(outbuf
,2,0,True
);
4752 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4753 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4755 END_PROFILE(SMBlockingX
);
4756 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4759 /* Back from the dead for OS/2..... JRA. */
4761 /****************************************************************************
4762 Reply to a SMBreadbmpx (read block multiplex) request
4763 ****************************************************************************/
4765 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4776 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4777 START_PROFILE(SMBreadBmpx
);
4779 /* this function doesn't seem to work - disable by default */
4780 if (!lp_readbmpx()) {
4781 END_PROFILE(SMBreadBmpx
);
4782 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
4785 outsize
= set_message(outbuf
,8,0,True
);
4787 CHECK_FSP(fsp
,conn
);
4791 startpos
= IVAL(inbuf
,smb_vwv1
);
4792 maxcount
= SVAL(inbuf
,smb_vwv3
);
4794 data
= smb_buf(outbuf
);
4795 pad
= ((long)data
)%4;
4800 max_per_packet
= bufsize
-(outsize
+pad
);
4804 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
, False
)) {
4805 END_PROFILE(SMBreadBmpx
);
4806 return ERROR_DOS(ERRDOS
,ERRlock
);
4810 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4812 nread
= read_file(fsp
,data
,startpos
,N
);
4817 if (nread
< (ssize_t
)N
)
4818 tcount
= total_read
+ nread
;
4820 set_message(outbuf
,8,nread
,False
);
4821 SIVAL(outbuf
,smb_vwv0
,startpos
);
4822 SSVAL(outbuf
,smb_vwv2
,tcount
);
4823 SSVAL(outbuf
,smb_vwv6
,nread
);
4824 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4826 if (!send_smb(smbd_server_fd(),outbuf
))
4827 exit_server("reply_readbmpx: send_smb failed.");
4829 total_read
+= nread
;
4831 } while (total_read
< (ssize_t
)tcount
);
4833 END_PROFILE(SMBreadBmpx
);
4837 /****************************************************************************
4838 Reply to a SMBsetattrE.
4839 ****************************************************************************/
4841 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4843 struct utimbuf unix_times
;
4845 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4846 START_PROFILE(SMBsetattrE
);
4848 outsize
= set_message(outbuf
,0,0,True
);
4850 if(!fsp
|| (fsp
->conn
!= conn
)) {
4851 END_PROFILE(SMBgetattrE
);
4852 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4856 * Convert the DOS times into unix times. Ignore create
4857 * time as UNIX can't set this.
4859 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4860 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4863 * Patch from Ray Frush <frush@engr.colostate.edu>
4864 * Sometimes times are sent as zero - ignore them.
4867 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0)) {
4868 /* Ignore request */
4869 if( DEBUGLVL( 3 ) ) {
4870 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4871 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4873 END_PROFILE(SMBsetattrE
);
4875 } else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0)) {
4876 /* set modify time = to access time if modify time was 0 */
4877 unix_times
.modtime
= unix_times
.actime
;
4880 /* Set the date on this file */
4881 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4882 END_PROFILE(SMBsetattrE
);
4883 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4886 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4887 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4889 END_PROFILE(SMBsetattrE
);
4894 /* Back from the dead for OS/2..... JRA. */
4896 /****************************************************************************
4897 Reply to a SMBwritebmpx (write block multiplex primary) request.
4898 ****************************************************************************/
4900 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4903 ssize_t nwritten
= -1;
4910 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4911 START_PROFILE(SMBwriteBmpx
);
4913 CHECK_FSP(fsp
,conn
);
4917 tcount
= SVAL(inbuf
,smb_vwv1
);
4918 startpos
= IVAL(inbuf
,smb_vwv3
);
4919 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
4920 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4921 smb_doff
= SVAL(inbuf
,smb_vwv11
);
4923 data
= smb_base(inbuf
) + smb_doff
;
4925 /* If this fails we need to send an SMBwriteC response,
4926 not an SMBwritebmpx - set this up now so we don't forget */
4927 SCVAL(outbuf
,smb_com
,SMBwritec
);
4929 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
,False
)) {
4930 END_PROFILE(SMBwriteBmpx
);
4931 return(ERROR_DOS(ERRDOS
,ERRlock
));
4934 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4936 if(lp_syncalways(SNUM(conn
)) || write_through
)
4937 sync_file(conn
,fsp
);
4939 if(nwritten
< (ssize_t
)numtowrite
) {
4940 END_PROFILE(SMBwriteBmpx
);
4941 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
4944 /* If the maximum to be written to this file
4945 is greater than what we just wrote then set
4946 up a secondary struct to be attached to this
4947 fd, we will use this to cache error messages etc. */
4949 if((ssize_t
)tcount
> nwritten
) {
4950 write_bmpx_struct
*wbms
;
4951 if(fsp
->wbmpx_ptr
!= NULL
)
4952 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
4954 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
4957 DEBUG(0,("Out of memory in reply_readmpx\n"));
4958 END_PROFILE(SMBwriteBmpx
);
4959 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
4961 wbms
->wr_mode
= write_through
;
4962 wbms
->wr_discard
= False
; /* No errors yet */
4963 wbms
->wr_total_written
= nwritten
;
4964 wbms
->wr_errclass
= 0;
4966 fsp
->wbmpx_ptr
= wbms
;
4969 /* We are returning successfully, set the message type back to
4971 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
4973 outsize
= set_message(outbuf
,1,0,True
);
4975 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
4977 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4978 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
4980 if (write_through
&& tcount
==nwritten
) {
4981 /* We need to send both a primary and a secondary response */
4982 smb_setlen(outbuf
,outsize
- 4);
4983 if (!send_smb(smbd_server_fd(),outbuf
))
4984 exit_server("reply_writebmpx: send_smb failed.");
4986 /* Now the secondary */
4987 outsize
= set_message(outbuf
,1,0,True
);
4988 SCVAL(outbuf
,smb_com
,SMBwritec
);
4989 SSVAL(outbuf
,smb_vwv0
,nwritten
);
4992 END_PROFILE(SMBwriteBmpx
);
4996 /****************************************************************************
4997 Reply to a SMBwritebs (write block multiplex secondary) request.
4998 ****************************************************************************/
5000 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
5003 ssize_t nwritten
= -1;
5010 write_bmpx_struct
*wbms
;
5011 BOOL send_response
= False
;
5012 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
5013 START_PROFILE(SMBwriteBs
);
5015 CHECK_FSP(fsp
,conn
);
5018 tcount
= SVAL(inbuf
,smb_vwv1
);
5019 startpos
= IVAL(inbuf
,smb_vwv2
);
5020 numtowrite
= SVAL(inbuf
,smb_vwv6
);
5021 smb_doff
= SVAL(inbuf
,smb_vwv7
);
5023 data
= smb_base(inbuf
) + smb_doff
;
5025 /* We need to send an SMBwriteC response, not an SMBwritebs */
5026 SCVAL(outbuf
,smb_com
,SMBwritec
);
5028 /* This fd should have an auxiliary struct attached,
5029 check that it does */
5030 wbms
= fsp
->wbmpx_ptr
;
5032 END_PROFILE(SMBwriteBs
);
5036 /* If write through is set we can return errors, else we must cache them */
5037 write_through
= wbms
->wr_mode
;
5039 /* Check for an earlier error */
5040 if(wbms
->wr_discard
) {
5041 END_PROFILE(SMBwriteBs
);
5042 return -1; /* Just discard the packet */
5045 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
5047 if(lp_syncalways(SNUM(conn
)) || write_through
)
5048 sync_file(conn
,fsp
);
5050 if (nwritten
< (ssize_t
)numtowrite
) {
5052 /* We are returning an error - we can delete the aux struct */
5054 fsp
->wbmpx_ptr
= NULL
;
5055 END_PROFILE(SMBwriteBs
);
5056 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
5058 END_PROFILE(SMBwriteBs
);
5059 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
5062 /* Increment the total written, if this matches tcount
5063 we can discard the auxiliary struct (hurrah !) and return a writeC */
5064 wbms
->wr_total_written
+= nwritten
;
5065 if(wbms
->wr_total_written
>= tcount
) {
5066 if (write_through
) {
5067 outsize
= set_message(outbuf
,1,0,True
);
5068 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
5069 send_response
= True
;
5073 fsp
->wbmpx_ptr
= NULL
;
5077 END_PROFILE(SMBwriteBs
);
5081 END_PROFILE(SMBwriteBs
);
5085 /****************************************************************************
5086 Reply to a SMBgetattrE.
5087 ****************************************************************************/
5089 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
5091 SMB_STRUCT_STAT sbuf
;
5094 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
5095 START_PROFILE(SMBgetattrE
);
5097 outsize
= set_message(outbuf
,11,0,True
);
5099 if(!fsp
|| (fsp
->conn
!= conn
)) {
5100 END_PROFILE(SMBgetattrE
);
5101 return ERROR_DOS(ERRDOS
,ERRbadfid
);
5104 /* Do an stat on this file */
5106 if(fsp_stat(fsp
, &sbuf
)) {
5107 END_PROFILE(SMBgetattrE
);
5108 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
5111 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
5113 /* Convert the times into dos times. Set create
5114 * date to be last modify date as UNIX doesn't save
5118 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
5119 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
5120 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
5122 SIVAL(outbuf
,smb_vwv6
,0);
5123 SIVAL(outbuf
,smb_vwv8
,0);
5125 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
5126 SIVAL(outbuf
,smb_vwv8
,SMB_ROUNDUP(sbuf
.st_size
,1024));
5128 SSVAL(outbuf
,smb_vwv10
, mode
);
5130 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
5132 END_PROFILE(SMBgetattrE
);