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
));
158 /*******************************************************************
159 work out what error to give to a failed connection
160 ********************************************************************/
162 static int connection_error(char *outbuf
, int ecode
)
164 if (ecode
== ERRnoipc
|| ecode
== ERRnosuchshare
)
165 return(ERROR_DOS(ERRDOS
,ecode
));
167 return(ERROR_DOS(ERRSRV
,ecode
));
170 /****************************************************************************
171 parse a share descriptor string
172 ****************************************************************************/
174 static void parse_connect(char *p
,char *service
,char *user
,
175 char *password
,int *pwlen
,char *dev
)
179 DEBUG(4,("parsing connect string %s\n",p
));
181 p2
= strrchr(p
,'\\');
185 fstrcpy(service
,p2
+1);
190 *pwlen
= strlen(password
);
197 p
= strchr(service
,'%');
205 /****************************************************************************
207 ****************************************************************************/
209 int reply_tcon(connection_struct
*conn
,
210 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
212 BOOL doencrypt
= SMBENCRYPT();
218 uint16 vuid
= SVAL(inbuf
,smb_uid
);
221 START_PROFILE(SMBtcon
);
223 *service
= *user
= *password
= *dev
= 0;
225 parse_connect(smb_buf(inbuf
)+1,service
,user
,password
,&pwlen
,dev
);
228 * If the vuid is valid, we should be using that....
231 if (*user
== '\0' && (lp_security() != SEC_SHARE
) && validated_username(vuid
)) {
232 pstrcpy(user
,validated_username(vuid
));
236 * Ensure the user and password names are in UNIX codepage format.
239 pstrcpy(user
,dos_to_unix_static(user
));
241 pstrcpy(password
,dos_to_unix_static(password
));
244 * Pass the user through the NT -> unix user mapping
248 (void)map_username(user
);
251 * Do any UNIX username case mangling.
253 (void)Get_Pwnam( user
, True
);
255 conn
= make_connection(service
,user
,password
,pwlen
,dev
,vuid
,&ecode
);
258 END_PROFILE(SMBtcon
);
259 return(connection_error(outbuf
,ecode
));
262 outsize
= set_message(outbuf
,2,0,True
);
263 SSVAL(outbuf
,smb_vwv0
,max_recv
);
264 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
265 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
267 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
268 service
, user
, conn
->cnum
));
270 END_PROFILE(SMBtcon
);
274 /****************************************************************************
275 Reply to a tcon and X.
276 ****************************************************************************/
278 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
284 BOOL doencrypt
= SMBENCRYPT();
286 uint16 vuid
= SVAL(inbuf
,smb_uid
);
287 int passlen
= SVAL(inbuf
,smb_vwv3
);
290 START_PROFILE(SMBtconX
);
292 *service
= *user
= *password
= *devicename
= 0;
294 /* we might have to close an old one */
295 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
296 close_cnum(conn
,vuid
);
299 if (passlen
> MAX_PASS_LEN
) {
300 overflow_attack(passlen
);
301 return(ERROR_DOS(ERRDOS
,ERRbuftoosmall
));
304 memcpy(password
,smb_buf(inbuf
),passlen
);
306 path
= smb_buf(inbuf
) + passlen
;
309 if (strequal(password
," "))
311 passlen
= strlen(password
);
315 * the service name can be either: \\server\share
316 * or share directly like on the DELL PowerVault 705
319 p
= strchr(path
+2,'\\');
321 END_PROFILE(SMBtconX
);
322 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
324 fstrcpy(service
,p
+1);
327 fstrcpy(service
,path
);
329 p
= strchr(service
,'%');
334 StrnCpy(devicename
,path
+ strlen(path
) + 1,6);
335 DEBUG(4,("Got device type %s\n",devicename
));
338 * If the vuid is valid, we should be using that....
341 if (*user
== '\0' && (lp_security() != SEC_SHARE
) && validated_username(vuid
)) {
342 pstrcpy(user
,validated_username(vuid
));
346 * Ensure the user and password names are in UNIX codepage format.
349 pstrcpy(user
,dos_to_unix_static(user
));
351 pstrcpy(password
,dos_to_unix_static(password
));
354 * Pass the user through the NT -> unix user mapping
358 (void)map_username(user
);
361 * Do any UNIX username case mangling.
363 (void)Get_Pwnam(user
, True
);
365 conn
= make_connection(service
,user
,password
,passlen
,devicename
,vuid
,&ecode
);
368 END_PROFILE(SMBtconX
);
369 return(connection_error(outbuf
,ecode
));
372 if (Protocol
< PROTOCOL_NT1
) {
373 set_message(outbuf
,2,strlen(devicename
)+1,True
);
374 pstrcpy(smb_buf(outbuf
),devicename
);
376 char *fsname
= lp_fstype(SNUM(conn
));
378 set_message(outbuf
,3,3,True
);
381 pstrcpy(p
,devicename
); p
= skip_string(p
,1); /* device name */
382 pstrcpy(p
,fsname
); p
= skip_string(p
,1); /* filesystem type e.g NTFS */
384 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
386 /* what does setting this bit do? It is set by NT4 and
387 may affect the ability to autorun mounted cdroms */
388 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
389 (lp_csc_policy(SNUM(conn
)) << 2));
391 init_dfsroot(conn
, inbuf
, outbuf
);
395 DEBUG(3,("tconX service=%s user=%s\n",
398 /* set the incoming and outgoing tid to the just created one */
399 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
400 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
402 END_PROFILE(SMBtconX
);
403 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
407 /****************************************************************************
408 reply to an unknown type
409 ****************************************************************************/
410 int reply_unknown(char *inbuf
,char *outbuf
)
413 type
= CVAL(inbuf
,smb_com
);
415 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
416 smb_fn_name(type
), type
, type
));
418 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
421 /****************************************************************************
423 ****************************************************************************/
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
);
1117 /****************************************************************************
1119 ****************************************************************************/
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
);
1165 /****************************************************************************
1167 ****************************************************************************/
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
);
1239 /****************************************************************************
1241 ****************************************************************************/
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
);
1285 /****************************************************************************
1287 ****************************************************************************/
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
);
1333 /****************************************************************************
1335 Can be called from SMBsearch, SMBffirst or SMBfunique.
1336 ****************************************************************************/
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
);
1416 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1417 dirtype
= CVAL(status
,0) & 0x1F;
1418 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1421 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1422 fstrcpy(mask
, dptr_wcard(dptr_num
));
1427 p
= smb_buf(outbuf
) + 3;
1431 if (status_len
== 0)
1433 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
1438 set_bad_path_error(errno
, bad_path
);
1439 END_PROFILE(SMBsearch
);
1440 return (UNIXERROR(ERRDOS
,ERRnofids
));
1442 END_PROFILE(SMBsearch
);
1443 return ERROR_DOS(ERRDOS
,ERRnofids
);
1445 dptr_set_wcard(dptr_num
, strdup(mask
));
1448 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1452 if ((dirtype
&0x1F) == aVOLID
)
1454 memcpy(p
,status
,21);
1455 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
1456 dptr_fill(p
+12,dptr_num
);
1457 if (dptr_zero(p
+12) && (status_len
==0))
1461 p
+= DIR_STRUCT_SIZE
;
1465 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1466 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1467 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
1468 check_descend
= True
;
1470 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
1473 !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
1476 memcpy(p
,status
,21);
1477 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
1478 dptr_fill(p
+12,dptr_num
);
1481 p
+= DIR_STRUCT_SIZE
;
1490 if ( (numentries
== 0) || !ok
)
1492 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
1493 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1494 dptr_close(&dptr_num
);
1497 /* If we were called as SMBffirst with smb_search_id == NULL
1498 and no entries were found then return error and close dirptr
1501 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
1503 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
1504 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1505 /* Also close the dptr - we know it's gone */
1506 dptr_close(&dptr_num
);
1509 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1510 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
1511 dptr_close(&dptr_num
);
1513 SSVAL(outbuf
,smb_vwv0
,numentries
);
1514 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1515 SCVAL(smb_buf(outbuf
),0,5);
1516 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1518 if (Protocol
>= PROTOCOL_NT1
)
1519 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1521 outsize
+= DIR_STRUCT_SIZE
*numentries
;
1522 smb_setlen(outbuf
,outsize
- 4);
1524 if ((! *directory
) && dptr_path(dptr_num
))
1525 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1527 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1528 smb_fn_name(CVAL(inbuf
,smb_com
)),
1529 mask
, directory
, dirtype
, numentries
, maxentries
) );
1531 END_PROFILE(SMBsearch
);
1536 /****************************************************************************
1537 reply to a fclose (stop directory search)
1538 ****************************************************************************/
1539 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1546 START_PROFILE(SMBfclose
);
1548 outsize
= set_message(outbuf
,1,0,True
);
1549 path
= smb_buf(inbuf
) + 1;
1550 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
1553 if (status_len
== 0) {
1554 END_PROFILE(SMBfclose
);
1555 return ERROR_DOS(ERRSRV
,ERRsrverror
);
1558 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1560 if(dptr_fetch(status
+12,&dptr_num
)) {
1561 /* Close the dptr - we know it's gone */
1562 dptr_close(&dptr_num
);
1565 SSVAL(outbuf
,smb_vwv0
,0);
1567 DEBUG(3,("search close\n"));
1569 END_PROFILE(SMBfclose
);
1574 /****************************************************************************
1576 ****************************************************************************/
1578 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1588 SMB_STRUCT_STAT sbuf
;
1589 BOOL bad_path
= False
;
1591 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1592 START_PROFILE(SMBopen
);
1594 share_mode
= SVAL(inbuf
,smb_vwv0
);
1596 pstrcpy(fname
,smb_buf(inbuf
)+1);
1598 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1600 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1602 unixmode
= unix_mode(conn
,aARCH
,fname
);
1604 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1605 unixmode
, oplock_request
,&rmode
,NULL
);
1609 set_bad_path_error(errno
, bad_path
);
1610 END_PROFILE(SMBopen
);
1611 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1614 size
= sbuf
.st_size
;
1615 fmode
= dos_mode(conn
,fname
,&sbuf
);
1616 mtime
= sbuf
.st_mtime
;
1619 DEBUG(3,("attempt to open a directory %s\n",fname
));
1620 close_file(fsp
,False
);
1621 END_PROFILE(SMBopen
);
1622 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1625 outsize
= set_message(outbuf
,7,0,True
);
1626 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1627 SSVAL(outbuf
,smb_vwv1
,fmode
);
1628 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1629 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1631 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1632 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1633 SSVAL(outbuf
,smb_vwv6
,rmode
);
1635 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1636 SCVAL(outbuf
,smb_flg
, CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1639 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1640 SCVAL(outbuf
,smb_flg
, CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1641 END_PROFILE(SMBopen
);
1646 /****************************************************************************
1647 reply to an open and X
1648 ****************************************************************************/
1649 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1652 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1653 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1654 /* Breakout the oplock request bits so we can set the
1655 reply bits separately. */
1656 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1657 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1658 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1660 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1661 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1662 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1664 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1667 int fmode
=0,mtime
=0,rmode
=0;
1668 SMB_STRUCT_STAT sbuf
;
1670 BOOL bad_path
= False
;
1672 START_PROFILE(SMBopenX
);
1674 /* If it's an IPC, pass off the pipe handler. */
1676 if (lp_nt_pipe_support()) {
1677 END_PROFILE(SMBopenX
);
1678 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1680 END_PROFILE(SMBopenX
);
1681 return ERROR_DOS(ERRSRV
,ERRaccess
);
1685 /* XXXX we need to handle passed times, sattr and flags */
1687 pstrcpy(fname
,smb_buf(inbuf
));
1689 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1691 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1693 unixmode
= unix_mode(conn
,smb_attr
| aARCH
, fname
);
1695 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,unixmode
,
1696 oplock_request
, &rmode
,&smb_action
);
1700 set_bad_path_error(errno
, bad_path
);
1701 END_PROFILE(SMBopenX
);
1702 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1705 size
= sbuf
.st_size
;
1706 fmode
= dos_mode(conn
,fname
,&sbuf
);
1707 mtime
= sbuf
.st_mtime
;
1709 close_file(fsp
,False
);
1710 END_PROFILE(SMBopenX
);
1711 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1714 /* If the caller set the extended oplock request bit
1715 and we granted one (by whatever means) - set the
1716 correct bit for extended oplock reply.
1719 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1720 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1723 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1724 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1727 /* If the caller set the core oplock request bit
1728 and we granted one (by whatever means) - set the
1729 correct bit for core oplock reply.
1732 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1733 SCVAL(outbuf
,smb_flg
, CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1736 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1737 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1740 set_message(outbuf
,15,0,True
);
1741 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1742 SSVAL(outbuf
,smb_vwv3
,fmode
);
1743 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1744 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1746 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1747 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1748 SSVAL(outbuf
,smb_vwv8
,rmode
);
1749 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1751 END_PROFILE(SMBopenX
);
1752 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1756 /****************************************************************************
1757 reply to a SMBulogoffX
1758 ****************************************************************************/
1759 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1761 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1762 user_struct
*vuser
= get_valid_user_struct(vuid
);
1763 START_PROFILE(SMBulogoffX
);
1766 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1769 /* in user level security we are supposed to close any files
1770 open by this user */
1771 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1772 file_close_user(vuid
);
1775 invalidate_vuid(vuid
);
1777 set_message(outbuf
,2,0,True
);
1779 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1781 END_PROFILE(SMBulogoffX
);
1782 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1786 /****************************************************************************
1787 reply to a mknew or a create
1788 ****************************************************************************/
1789 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1797 BOOL bad_path
= False
;
1799 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1800 SMB_STRUCT_STAT sbuf
;
1801 START_PROFILE(SMBcreate
);
1803 com
= SVAL(inbuf
,smb_com
);
1805 createmode
= SVAL(inbuf
,smb_vwv0
);
1806 pstrcpy(fname
,smb_buf(inbuf
)+1);
1808 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1810 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1812 if (createmode
& aVOLID
) {
1813 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1816 unixmode
= unix_mode(conn
,createmode
,fname
);
1820 /* We should fail if file exists. */
1821 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1825 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1826 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1829 /* Open file in dos compatibility share mode. */
1830 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1831 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1835 set_bad_path_error(errno
, bad_path
);
1836 END_PROFILE(SMBcreate
);
1837 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1840 outsize
= set_message(outbuf
,1,0,True
);
1841 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1843 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1844 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1847 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1848 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1850 DEBUG( 2, ( "new file %s\n", fname
) );
1851 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1852 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1854 END_PROFILE(SMBcreate
);
1859 /****************************************************************************
1860 reply to a create temporary file
1861 ****************************************************************************/
1862 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1868 BOOL bad_path
= False
;
1870 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1872 SMB_STRUCT_STAT sbuf
;
1875 START_PROFILE(SMBctemp
);
1877 createmode
= SVAL(inbuf
,smb_vwv0
);
1878 pstrcpy(fname
,smb_buf(inbuf
)+1);
1879 pstrcat(fname
,"\\TMXXXXXX");
1881 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1883 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1885 unixmode
= unix_mode(conn
,createmode
,fname
);
1887 tmpfd
= smb_mkstemp(fname
);
1889 END_PROFILE(SMBctemp
);
1890 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1893 vfs_stat(conn
,fname
,&sbuf
);
1895 /* Open file in dos compatibility share mode. */
1896 /* We should fail if file does not exist. */
1897 fsp
= open_file_shared(conn
,fname
,&sbuf
,
1898 SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1899 FILE_EXISTS_OPEN
|FILE_FAIL_IF_NOT_EXIST
,
1900 unixmode
, oplock_request
, NULL
, NULL
);
1901 /* close fd from smb_mkstemp() */
1905 set_bad_path_error(errno
, bad_path
);
1906 END_PROFILE(SMBctemp
);
1907 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1910 /* the returned filename is relative to the directory */
1911 s
= strrchr(fname
, '/');
1917 outsize
= set_message(outbuf
,1,4+ strlen(fname
),True
);
1918 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1920 p
= smb_buf(outbuf
);
1921 SSVALS(p
, 0, -1); /* what is this? not in spec */
1922 SSVAL(p
, 2, strlen(s
));
1926 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1927 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1930 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1931 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1933 DEBUG( 2, ( "created temp file %s\n", fname
) );
1934 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1935 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1937 END_PROFILE(SMBctemp
);
1941 /*******************************************************************
1942 Check if a user is allowed to rename a file.
1943 ********************************************************************/
1945 static NTSTATUS
can_rename(char *fname
,connection_struct
*conn
, SMB_STRUCT_STAT
*pst
)
1951 if (!CAN_WRITE(conn
))
1952 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1954 if (S_ISDIR(pst
->st_mode
))
1955 return NT_STATUS_OK
;
1957 /* We need a better way to return NT status codes from open... */
1961 fsp
= open_file_shared1(conn
, fname
, pst
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1962 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1965 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1966 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1967 ret
= NT_STATUS_SHARING_VIOLATION
;
1972 close_file(fsp
,False
);
1973 return NT_STATUS_OK
;
1976 /*******************************************************************
1977 Check if a user is allowed to delete a file.
1978 ********************************************************************/
1980 static NTSTATUS
can_delete(char *fname
,connection_struct
*conn
, int dirtype
)
1982 SMB_STRUCT_STAT sbuf
;
1988 if (!CAN_WRITE(conn
))
1989 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1991 if (conn
->vfs_ops
.lstat(conn
,dos_to_unix_static(fname
),&sbuf
) != 0)
1992 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1994 fmode
= dos_mode(conn
,fname
,&sbuf
);
1996 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1997 if (!lp_delete_readonly(SNUM(conn
))) {
1999 return NT_STATUS_CANNOT_DELETE
;
2002 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
2003 return NT_STATUS_CANNOT_DELETE
;
2005 /* We need a better way to return NT status codes from open... */
2009 fsp
= open_file_shared1(conn
, fname
, &sbuf
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
2010 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
2013 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
2014 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
2015 ret
= NT_STATUS_SHARING_VIOLATION
;
2020 close_file(fsp
,False
);
2021 return NT_STATUS_OK
;
2024 /****************************************************************************
2025 The guts of the unlink command, split out so it may be called by the NT SMB
2027 ****************************************************************************/
2029 NTSTATUS
unlink_internals(connection_struct
*conn
, int dirtype
, char *name
)
2035 NTSTATUS error
= NT_STATUS_OK
;
2037 BOOL bad_path
= False
;
2039 SMB_STRUCT_STAT sbuf
;
2041 *directory
= *mask
= 0;
2043 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
2045 p
= strrchr(name
,'/');
2047 pstrcpy(directory
,".");
2051 pstrcpy(directory
,name
);
2056 * We should only check the mangled cache
2057 * here if unix_convert failed. This means
2058 * that the path in 'mask' doesn't exist
2059 * on the file system and so we need to look
2060 * for a possible mangle. This patch from
2061 * Tine Smukavec <valentin.smukavec@hermes.si>.
2064 if (!rc
&& mangle_is_mangled(mask
))
2065 mangle_check_cache( mask
);
2067 has_wild
= ms_has_wild(mask
);
2070 pstrcat(directory
,"/");
2071 pstrcat(directory
,mask
);
2072 error
= can_delete(directory
,conn
,dirtype
);
2073 if (!NT_STATUS_IS_OK(error
))
2076 if (vfs_unlink(conn
,directory
) == 0)
2079 void *dirptr
= NULL
;
2081 if (check_name(directory
,conn
))
2082 dirptr
= OpenDir(conn
, directory
, True
);
2084 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2085 the pattern matches against the long name, otherwise the short name
2086 We don't implement this yet XXXX
2090 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2092 if (strequal(mask
,"????????.???"))
2095 while ((dname
= ReadDirName(dirptr
))) {
2097 pstrcpy(fname
,dname
);
2099 if(!mask_match(fname
, mask
, case_sensitive
))
2102 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
2103 error
= can_delete(fname
,conn
,dirtype
);
2104 if (!NT_STATUS_IS_OK(error
))
2106 if (vfs_unlink(conn
,fname
) == 0)
2108 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
2114 if (count
== 0 && NT_STATUS_IS_OK(error
))
2115 error
= map_nt_error_from_unix(errno
);
2120 /****************************************************************************
2122 ****************************************************************************/
2124 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2131 START_PROFILE(SMBunlink
);
2133 dirtype
= SVAL(inbuf
,smb_vwv0
);
2135 pstrcpy(name
,smb_buf(inbuf
) + 1);
2137 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
2139 DEBUG(3,("reply_unlink : %s\n",name
));
2141 status
= unlink_internals(conn
, dirtype
, name
);
2142 if (!NT_STATUS_IS_OK(status
))
2143 return ERROR_NT(status
);
2146 * Win2k needs a changenotify request response before it will
2147 * update after a rename..
2150 process_pending_change_notify_queue((time_t)0);
2152 outsize
= set_message(outbuf
,0,0,True
);
2154 END_PROFILE(SMBunlink
);
2158 /****************************************************************************
2160 ****************************************************************************/
2162 void fail_readraw(void)
2165 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2167 exit_server(errstr
);
2170 /****************************************************************************
2171 Reply to a readbraw (core+ protocol).
2172 ****************************************************************************/
2174 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
2176 ssize_t maxcount
,mincount
;
2179 char *header
= outbuf
;
2182 START_PROFILE(SMBreadbraw
);
2185 * Special check if an oplock break has been issued
2186 * and the readraw request croses on the wire, we must
2187 * return a zero length response here.
2190 if(global_oplock_break
) {
2191 _smb_setlen(header
,0);
2192 if (write_data(smbd_server_fd(),header
,4) != 4)
2194 DEBUG(5,("readbraw - oplock break finished\n"));
2195 END_PROFILE(SMBreadbraw
);
2199 fsp
= file_fsp(inbuf
,smb_vwv0
);
2201 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
2203 * fsp could be NULL here so use the value from the packet. JRA.
2205 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
2206 _smb_setlen(header
,0);
2207 if (write_data(smbd_server_fd(),header
,4) != 4)
2209 END_PROFILE(SMBreadbraw
);
2213 CHECK_FSP(fsp
,conn
);
2215 flush_write_cache(fsp
, READRAW_FLUSH
);
2217 startpos
= IVAL(inbuf
,smb_vwv1
);
2218 if(CVAL(inbuf
,smb_wct
) == 10) {
2220 * This is a large offset (64 bit) read.
2222 #ifdef LARGE_SMB_OFF_T
2224 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
2226 #else /* !LARGE_SMB_OFF_T */
2229 * Ensure we haven't been sent a >32 bit offset.
2232 if(IVAL(inbuf
,smb_vwv8
) != 0) {
2233 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2234 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
2235 _smb_setlen(header
,0);
2236 if (write_data(smbd_server_fd(),header
,4) != 4)
2238 END_PROFILE(SMBreadbraw
);
2242 #endif /* LARGE_SMB_OFF_T */
2245 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
2246 _smb_setlen(header
,0);
2247 if (write_data(smbd_server_fd(),header
,4) != 4)
2249 END_PROFILE(SMBreadbraw
);
2253 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
2254 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
2256 /* ensure we don't overrun the packet size */
2257 maxcount
= MIN(65535,maxcount
);
2258 maxcount
= MAX(mincount
,maxcount
);
2260 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2261 SMB_OFF_T size
= fsp
->size
;
2262 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
2264 if (size
< sizeneeded
) {
2266 if (vfs_fstat(fsp
,fsp
->fd
,&st
) == 0)
2267 fsp
->size
= size
= st
.st_size
;
2270 if (startpos
>= size
)
2273 nread
= MIN(maxcount
,(size
- startpos
));
2276 if (nread
< mincount
)
2279 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp
->fnum
, (double)startpos
,
2280 (int)maxcount
, (int)mincount
, (int)nread
) );
2283 ret
= read_file(fsp
,header
+4,startpos
,nread
);
2288 _smb_setlen(header
,ret
);
2289 if (write_data(smbd_server_fd(),header
,4+ret
) != 4+ret
)
2292 DEBUG(5,("readbraw finished\n"));
2293 END_PROFILE(SMBreadbraw
);
2298 /****************************************************************************
2299 reply to a lockread (core+ protocol)
2300 ****************************************************************************/
2301 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
2309 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2310 START_PROFILE(SMBlockread
);
2312 CHECK_FSP(fsp
,conn
);
2315 release_level_2_oplocks_on_change(fsp
);
2317 numtoread
= SVAL(inbuf
,smb_vwv1
);
2318 startpos
= IVAL(inbuf
,smb_vwv2
);
2320 outsize
= set_message(outbuf
,5,3,True
);
2321 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2322 data
= smb_buf(outbuf
) + 3;
2325 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2326 * protocol request that predates the read/write lock concept.
2327 * Thus instead of asking for a read lock here we need to ask
2328 * for a write lock. JRA.
2331 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
),
2332 (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
);
2334 if (NT_STATUS_V(status
)) {
2335 if (lp_blocking_locks(SNUM(conn
))) {
2337 * A blocking lock was requested. Package up
2338 * this smb into a queued request and push it
2339 * onto the blocking lock queue.
2341 if(push_blocking_lock_request(inbuf
, length
, -1, 0))
2342 END_PROFILE(SMBlockread
);
2345 END_PROFILE(SMBlockread
);
2346 return ERROR_NT(status
);
2349 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2352 END_PROFILE(SMBlockread
);
2353 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2357 SSVAL(outbuf
,smb_vwv0
,nread
);
2358 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2359 SSVAL(smb_buf(outbuf
),1,nread
);
2361 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2362 fsp
->fnum
, (int)numtoread
, (int)nread
) );
2364 END_PROFILE(SMBlockread
);
2369 /****************************************************************************
2371 ****************************************************************************/
2373 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2380 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2381 START_PROFILE(SMBread
);
2383 CHECK_FSP(fsp
,conn
);
2386 numtoread
= SVAL(inbuf
,smb_vwv1
);
2387 startpos
= IVAL(inbuf
,smb_vwv2
);
2389 outsize
= set_message(outbuf
,5,3,True
);
2390 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2391 data
= smb_buf(outbuf
) + 3;
2393 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2394 END_PROFILE(SMBread
);
2395 return ERROR_DOS(ERRDOS
,ERRlock
);
2399 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2402 END_PROFILE(SMBread
);
2403 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2407 SSVAL(outbuf
,smb_vwv0
,nread
);
2408 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2409 SCVAL(smb_buf(outbuf
),0,1);
2410 SSVAL(smb_buf(outbuf
),1,nread
);
2412 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2413 fsp
->fnum
, (int)numtoread
, (int)nread
) );
2415 END_PROFILE(SMBread
);
2420 /****************************************************************************
2421 reply to a read and X
2422 ****************************************************************************/
2423 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2425 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2426 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2427 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2428 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2431 START_PROFILE(SMBreadX
);
2433 /* If it's an IPC, pass off the pipe handler. */
2435 END_PROFILE(SMBreadX
);
2436 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2439 CHECK_FSP(fsp
,conn
);
2442 set_message(outbuf
,12,0,True
);
2443 data
= smb_buf(outbuf
);
2445 if(CVAL(inbuf
,smb_wct
) == 12) {
2446 #ifdef LARGE_SMB_OFF_T
2448 * This is a large offset (64 bit) read.
2450 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2452 #else /* !LARGE_SMB_OFF_T */
2455 * Ensure we haven't been sent a >32 bit offset.
2458 if(IVAL(inbuf
,smb_vwv10
) != 0) {
2459 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2460 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
2461 END_PROFILE(SMBreadX
);
2462 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2465 #endif /* LARGE_SMB_OFF_T */
2469 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2470 END_PROFILE(SMBreadX
);
2471 return ERROR_DOS(ERRDOS
,ERRlock
);
2473 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2476 END_PROFILE(SMBreadX
);
2477 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2480 SSVAL(outbuf
,smb_vwv5
,nread
);
2481 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2482 SSVAL(smb_buf(outbuf
),-2,nread
);
2484 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2485 fsp
->fnum
, (int)smb_mincnt
, (int)smb_maxcnt
, (int)nread
) );
2487 END_PROFILE(SMBreadX
);
2488 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2491 /****************************************************************************
2492 reply to a writebraw (core+ or LANMAN1.0 protocol)
2493 ****************************************************************************/
2495 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2498 ssize_t total_written
=0;
2499 size_t numtowrite
=0;
2504 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2506 START_PROFILE(SMBwritebraw
);
2508 CHECK_FSP(fsp
,conn
);
2511 tcount
= IVAL(inbuf
,smb_vwv1
);
2512 startpos
= IVAL(inbuf
,smb_vwv3
);
2513 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2515 /* We have to deal with slightly different formats depending
2516 on whether we are using the core+ or lanman1.0 protocol */
2518 if(Protocol
<= PROTOCOL_COREPLUS
) {
2519 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2520 data
= smb_buf(inbuf
);
2522 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2523 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2526 /* force the error type */
2527 SCVAL(inbuf
,smb_com
,SMBwritec
);
2528 SCVAL(outbuf
,smb_com
,SMBwritec
);
2530 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2531 END_PROFILE(SMBwritebraw
);
2532 return(ERROR_DOS(ERRDOS
,ERRlock
));
2536 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2538 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2539 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2541 if (nwritten
< numtowrite
) {
2542 END_PROFILE(SMBwritebraw
);
2543 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2546 total_written
= nwritten
;
2548 /* Return a message to the redirector to tell it to send more bytes */
2549 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
2550 SSVALS(outbuf
,smb_vwv0
,-1);
2551 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2552 if (!send_smb(smbd_server_fd(),outbuf
))
2553 exit_server("reply_writebraw: send_smb failed.");
2555 /* Now read the raw data into the buffer and write it */
2556 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2557 exit_server("secondary writebraw failed");
2560 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2561 numtowrite
= smb_len(inbuf
);
2563 /* Set up outbuf to return the correct return */
2564 outsize
= set_message(outbuf
,1,0,True
);
2565 SCVAL(outbuf
,smb_com
,SMBwritec
);
2566 SSVAL(outbuf
,smb_vwv0
,total_written
);
2568 if (numtowrite
!= 0) {
2570 if (numtowrite
> BUFFER_SIZE
) {
2571 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2572 (unsigned int)numtowrite
));
2573 exit_server("secondary writebraw failed");
2576 if (tcount
> nwritten
+numtowrite
) {
2577 DEBUG(3,("Client overestimated the write %d %d %d\n",
2578 (int)tcount
,(int)nwritten
,(int)numtowrite
));
2581 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
2582 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2584 exit_server("secondary writebraw failed");
2587 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
2589 if (nwritten
< (ssize_t
)numtowrite
) {
2590 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2591 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2595 total_written
+= nwritten
;
2598 if ((lp_syncalways(SNUM(conn
)) || write_through
) && lp_strict_sync(SNUM(conn
)))
2599 sync_file(conn
,fsp
);
2601 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2602 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
2604 /* we won't return a status if write through is not selected - this follows what WfWg does */
2605 END_PROFILE(SMBwritebraw
);
2606 if (!write_through
&& total_written
==tcount
) {
2608 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2609 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2611 if (!send_keepalive(smbd_server_fd()))
2612 exit_server("reply_writebraw: send of keepalive failed");
2619 /****************************************************************************
2620 reply to a writeunlock (core+)
2621 ****************************************************************************/
2623 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2625 ssize_t nwritten
= -1;
2630 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2632 START_PROFILE(SMBwriteunlock
);
2634 CHECK_FSP(fsp
,conn
);
2637 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2638 startpos
= IVAL(inbuf
,smb_vwv2
);
2639 data
= smb_buf(inbuf
) + 3;
2641 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
,
2642 WRITE_LOCK
,False
)) {
2643 END_PROFILE(SMBwriteunlock
);
2644 return ERROR_DOS(ERRDOS
,ERRlock
);
2647 /* The special X/Open SMB protocol handling of
2648 zero length writes is *NOT* done for
2653 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2655 if (lp_syncalways(SNUM(conn
)))
2656 sync_file(conn
,fsp
);
2658 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2659 END_PROFILE(SMBwriteunlock
);
2660 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2663 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)numtowrite
,
2664 (SMB_BIG_UINT
)startpos
);
2665 if (NT_STATUS_V(status
)) {
2666 END_PROFILE(SMBwriteunlock
);
2667 return ERROR_NT(status
);
2670 outsize
= set_message(outbuf
,1,0,True
);
2672 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2674 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2675 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
2677 END_PROFILE(SMBwriteunlock
);
2682 /****************************************************************************
2684 ****************************************************************************/
2686 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2689 ssize_t nwritten
= -1;
2692 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2694 START_PROFILE(SMBwrite
);
2696 /* If it's an IPC, pass off the pipe handler. */
2698 END_PROFILE(SMBwrite
);
2699 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2702 CHECK_FSP(fsp
,conn
);
2705 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2706 startpos
= IVAL(inbuf
,smb_vwv2
);
2707 data
= smb_buf(inbuf
) + 3;
2709 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2710 END_PROFILE(SMBwrite
);
2711 return ERROR_DOS(ERRDOS
,ERRlock
);
2715 * X/Open SMB protocol says that if smb_vwv1 is
2716 * zero then the file size should be extended or
2717 * truncated to the size given in smb_vwv[2-3].
2720 if(numtowrite
== 0) {
2722 * This is actually an allocate call, and set EOF. JRA.
2724 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2726 END_PROFILE(SMBwrite
);
2727 return ERROR_NT(NT_STATUS_DISK_FULL
);
2729 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2731 END_PROFILE(SMBwrite
);
2732 return ERROR_NT(NT_STATUS_DISK_FULL
);
2735 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2737 if (lp_syncalways(SNUM(conn
)))
2738 sync_file(conn
,fsp
);
2740 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2741 END_PROFILE(SMBwrite
);
2742 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2745 outsize
= set_message(outbuf
,1,0,True
);
2747 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2749 if (nwritten
< (ssize_t
)numtowrite
) {
2750 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2751 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2754 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2756 END_PROFILE(SMBwrite
);
2761 /****************************************************************************
2762 reply to a write and X
2763 ****************************************************************************/
2764 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2766 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2767 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2768 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2769 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2770 ssize_t nwritten
= -1;
2771 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2772 unsigned int smblen
= smb_len(inbuf
);
2774 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2775 START_PROFILE(SMBwriteX
);
2777 /* If it's an IPC, pass off the pipe handler. */
2779 END_PROFILE(SMBwriteX
);
2780 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2783 CHECK_FSP(fsp
,conn
);
2786 /* Deal with possible LARGE_WRITEX */
2788 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2790 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2791 END_PROFILE(SMBwriteX
);
2792 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2795 data
= smb_base(inbuf
) + smb_doff
;
2797 if(CVAL(inbuf
,smb_wct
) == 14) {
2798 #ifdef LARGE_SMB_OFF_T
2800 * This is a large offset (64 bit) write.
2802 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2804 #else /* !LARGE_SMB_OFF_T */
2807 * Ensure we haven't been sent a >32 bit offset.
2810 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2811 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2812 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2813 END_PROFILE(SMBwriteX
);
2814 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2817 #endif /* LARGE_SMB_OFF_T */
2820 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2821 END_PROFILE(SMBwriteX
);
2822 return ERROR_DOS(ERRDOS
,ERRlock
);
2825 /* X/Open SMB protocol says that, unlike SMBwrite
2826 if the length is zero then NO truncation is
2827 done, just a write of zero. To truncate a file,
2832 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2834 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2835 END_PROFILE(SMBwriteX
);
2836 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2839 set_message(outbuf
,6,0,True
);
2841 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2843 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2845 if (nwritten
< (ssize_t
)numtowrite
) {
2846 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2847 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2850 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2851 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2853 if (lp_syncalways(SNUM(conn
)) || write_through
)
2854 sync_file(conn
,fsp
);
2856 END_PROFILE(SMBwriteX
);
2857 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2861 /****************************************************************************
2863 ****************************************************************************/
2865 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2871 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2872 START_PROFILE(SMBlseek
);
2874 CHECK_FSP(fsp
,conn
);
2876 flush_write_cache(fsp
, SEEK_FLUSH
);
2878 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2879 startpos
= IVALS(inbuf
,smb_vwv2
);
2882 case 0: umode
= SEEK_SET
; break;
2883 case 1: umode
= SEEK_CUR
; break;
2884 case 2: umode
= SEEK_END
; break;
2886 umode
= SEEK_SET
; break;
2889 if((res
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
2891 * Check for the special case where a seek before the start
2892 * of the file sets the offset to zero. Added in the CIFS spec,
2896 if(errno
== EINVAL
) {
2897 SMB_OFF_T current_pos
= startpos
;
2899 if(umode
== SEEK_CUR
) {
2901 if((current_pos
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,0,SEEK_CUR
)) == -1) {
2902 END_PROFILE(SMBlseek
);
2903 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2906 current_pos
+= startpos
;
2908 } else if (umode
== SEEK_END
) {
2910 SMB_STRUCT_STAT sbuf
;
2912 if(vfs_fstat(fsp
,fsp
->fd
, &sbuf
) == -1) {
2913 END_PROFILE(SMBlseek
);
2914 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2917 current_pos
+= sbuf
.st_size
;
2921 res
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,0,SEEK_SET
);
2925 END_PROFILE(SMBlseek
);
2926 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2932 outsize
= set_message(outbuf
,2,0,True
);
2933 SIVAL(outbuf
,smb_vwv0
,res
);
2935 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2936 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
2938 END_PROFILE(SMBlseek
);
2942 /****************************************************************************
2944 ****************************************************************************/
2946 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2948 int outsize
= set_message(outbuf
,0,0,True
);
2949 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2950 START_PROFILE(SMBflush
);
2952 CHECK_FSP(fsp
,conn
);
2955 file_sync_all(conn
);
2957 sync_file(conn
,fsp
);
2960 DEBUG(3,("flush\n"));
2961 END_PROFILE(SMBflush
);
2965 /****************************************************************************
2967 ****************************************************************************/
2968 int reply_exit(connection_struct
*conn
,
2969 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2972 START_PROFILE(SMBexit
);
2973 outsize
= set_message(outbuf
,0,0,True
);
2975 DEBUG(3,("exit\n"));
2977 END_PROFILE(SMBexit
);
2982 /****************************************************************************
2983 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2984 ****************************************************************************/
2985 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2990 files_struct
*fsp
= NULL
;
2991 START_PROFILE(SMBclose
);
2993 outsize
= set_message(outbuf
,0,0,True
);
2995 /* If it's an IPC, pass off to the pipe handler. */
2997 END_PROFILE(SMBclose
);
2998 return reply_pipe_close(conn
, inbuf
,outbuf
);
3001 fsp
= file_fsp(inbuf
,smb_vwv0
);
3004 * We can only use CHECK_FSP if we know it's not a directory.
3007 if(!fsp
|| (fsp
->conn
!= conn
)) {
3008 END_PROFILE(SMBclose
);
3009 return ERROR_DOS(ERRDOS
,ERRbadfid
);
3012 if(fsp
->is_directory
) {
3014 * Special case - close NT SMB directory handle.
3016 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
3017 close_file(fsp
,True
);
3020 * Close ordinary file.
3025 /* Save the name for time set in close. */
3026 pstrcpy( file_name
, fsp
->fsp_name
);
3028 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3030 conn
->num_files_open
));
3033 * close_file() returns the unix errno if an error
3034 * was detected on close - normally this is due to
3035 * a disk full error. If not then it was probably an I/O error.
3038 if((close_err
= close_file(fsp
,True
)) != 0) {
3040 END_PROFILE(SMBclose
);
3041 return (UNIXERROR(ERRHRD
,ERRgeneral
));
3045 * Now take care of any time sent in the close.
3048 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
3050 /* try and set the date */
3051 set_filetime(conn
, file_name
, mtime
);
3055 END_PROFILE(SMBclose
);
3060 /****************************************************************************
3061 reply to a writeclose (Core+ protocol)
3062 ****************************************************************************/
3064 int reply_writeclose(connection_struct
*conn
,
3065 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
3068 ssize_t nwritten
= -1;
3074 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3075 START_PROFILE(SMBwriteclose
);
3077 CHECK_FSP(fsp
,conn
);
3080 numtowrite
= SVAL(inbuf
,smb_vwv1
);
3081 startpos
= IVAL(inbuf
,smb_vwv2
);
3082 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
3083 data
= smb_buf(inbuf
) + 1;
3085 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
3086 END_PROFILE(SMBwriteclose
);
3087 return ERROR_DOS(ERRDOS
,ERRlock
);
3090 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
3092 set_filetime(conn
, fsp
->fsp_name
,mtime
);
3094 close_err
= close_file(fsp
,True
);
3096 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3097 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
3098 conn
->num_files_open
));
3100 if (nwritten
<= 0) {
3101 END_PROFILE(SMBwriteclose
);
3102 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3105 if(close_err
!= 0) {
3107 END_PROFILE(SMBwriteclose
);
3108 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3111 outsize
= set_message(outbuf
,1,0,True
);
3113 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3114 END_PROFILE(SMBwriteclose
);
3119 /****************************************************************************
3121 ****************************************************************************/
3122 int reply_lock(connection_struct
*conn
,
3123 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
3125 int outsize
= set_message(outbuf
,0,0,True
);
3126 SMB_BIG_UINT count
,offset
;
3128 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3129 START_PROFILE(SMBlock
);
3131 CHECK_FSP(fsp
,conn
);
3133 release_level_2_oplocks_on_change(fsp
);
3135 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
3136 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
3138 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3139 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
3141 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
, WRITE_LOCK
);
3142 if (NT_STATUS_V(status
)) {
3143 if (lp_blocking_locks(SNUM(conn
))) {
3145 * A blocking lock was requested. Package up
3146 * this smb into a queued request and push it
3147 * onto the blocking lock queue.
3149 if(push_blocking_lock_request(inbuf
, length
, -1, 0)) {
3150 END_PROFILE(SMBlock
);
3154 END_PROFILE(SMBlock
);
3155 return ERROR_NT(status
);
3158 END_PROFILE(SMBlock
);
3163 /****************************************************************************
3165 ****************************************************************************/
3166 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
3168 int outsize
= set_message(outbuf
,0,0,True
);
3169 SMB_BIG_UINT count
,offset
;
3171 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3172 START_PROFILE(SMBunlock
);
3174 CHECK_FSP(fsp
,conn
);
3176 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
3177 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
3179 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
);
3180 if (NT_STATUS_V(status
)) {
3181 END_PROFILE(SMBunlock
);
3182 return ERROR_NT(status
);
3185 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3186 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
3188 END_PROFILE(SMBunlock
);
3193 /****************************************************************************
3195 ****************************************************************************/
3196 int reply_tdis(connection_struct
*conn
,
3197 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3199 int outsize
= set_message(outbuf
,0,0,True
);
3201 START_PROFILE(SMBtdis
);
3203 vuid
= SVAL(inbuf
,smb_uid
);
3206 DEBUG(4,("Invalid connection in tdis\n"));
3207 END_PROFILE(SMBtdis
);
3208 return ERROR_DOS(ERRSRV
,ERRinvnid
);
3213 close_cnum(conn
,vuid
);
3215 END_PROFILE(SMBtdis
);
3221 /****************************************************************************
3223 ****************************************************************************/
3224 int reply_echo(connection_struct
*conn
,
3225 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3227 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
3229 unsigned int data_len
= smb_buflen(inbuf
);
3230 int outsize
= set_message(outbuf
,1,data_len
,True
);
3231 START_PROFILE(SMBecho
);
3233 data_len
= MIN(data_len
, (sizeof(inbuf
)-(smb_buf(inbuf
)-inbuf
)));
3235 /* copy any incoming data back out */
3237 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
3239 if (smb_reverb
> 100) {
3240 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
3244 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
3245 SSVAL(outbuf
,smb_vwv0
,seq_num
);
3247 smb_setlen(outbuf
,outsize
- 4);
3249 if (!send_smb(smbd_server_fd(),outbuf
))
3250 exit_server("reply_echo: send_smb failed.");
3253 DEBUG(3,("echo %d times\n", smb_reverb
));
3257 END_PROFILE(SMBecho
);
3262 /****************************************************************************
3263 reply to a printopen
3264 ****************************************************************************/
3265 int reply_printopen(connection_struct
*conn
,
3266 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3270 START_PROFILE(SMBsplopen
);
3272 if (!CAN_PRINT(conn
)) {
3273 END_PROFILE(SMBsplopen
);
3274 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3277 /* Open for exclusive use, write only. */
3278 fsp
= print_fsp_open(conn
, NULL
);
3281 END_PROFILE(SMBsplopen
);
3282 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3285 outsize
= set_message(outbuf
,1,0,True
);
3286 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
3288 DEBUG(3,("openprint fd=%d fnum=%d\n",
3289 fsp
->fd
, fsp
->fnum
));
3291 END_PROFILE(SMBsplopen
);
3296 /****************************************************************************
3297 reply to a printclose
3298 ****************************************************************************/
3299 int reply_printclose(connection_struct
*conn
,
3300 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3302 int outsize
= set_message(outbuf
,0,0,True
);
3303 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3305 START_PROFILE(SMBsplclose
);
3307 CHECK_FSP(fsp
,conn
);
3309 if (!CAN_PRINT(conn
)) {
3310 END_PROFILE(SMBsplclose
);
3311 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3314 DEBUG(3,("printclose fd=%d fnum=%d\n",
3315 fsp
->fd
,fsp
->fnum
));
3317 close_err
= close_file(fsp
,True
);
3319 if(close_err
!= 0) {
3321 END_PROFILE(SMBsplclose
);
3322 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3325 END_PROFILE(SMBsplclose
);
3330 /****************************************************************************
3331 reply to a printqueue
3332 ****************************************************************************/
3333 int reply_printqueue(connection_struct
*conn
,
3334 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3336 int outsize
= set_message(outbuf
,2,3,True
);
3337 int max_count
= SVAL(inbuf
,smb_vwv0
);
3338 int start_index
= SVAL(inbuf
,smb_vwv1
);
3339 START_PROFILE(SMBsplretq
);
3341 /* we used to allow the client to get the cnum wrong, but that
3342 is really quite gross and only worked when there was only
3343 one printer - I think we should now only accept it if they
3344 get it right (tridge) */
3345 if (!CAN_PRINT(conn
)) {
3346 END_PROFILE(SMBsplretq
);
3347 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3350 SSVAL(outbuf
,smb_vwv0
,0);
3351 SSVAL(outbuf
,smb_vwv1
,0);
3352 SCVAL(smb_buf(outbuf
),0,1);
3353 SSVAL(smb_buf(outbuf
),1,0);
3355 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3356 start_index
, max_count
));
3359 print_queue_struct
*queue
= NULL
;
3360 print_status_struct status
;
3361 char *p
= smb_buf(outbuf
) + 3;
3362 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
3363 int num_to_get
= ABS(max_count
);
3364 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
3370 num_to_get
= MIN(num_to_get
,count
-first
);
3373 for (i
=first
;i
<first
+num_to_get
;i
++) {
3374 put_dos_date2(p
,0,queue
[i
].time
);
3375 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
3376 SSVAL(p
,5, queue
[i
].job
);
3377 SIVAL(p
,7,queue
[i
].size
);
3379 StrnCpy(p
+12,queue
[i
].fs_user
,16);
3384 outsize
= set_message(outbuf
,2,28*count
+3,False
);
3385 SSVAL(outbuf
,smb_vwv0
,count
);
3386 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
3387 SCVAL(smb_buf(outbuf
),0,1);
3388 SSVAL(smb_buf(outbuf
),1,28*count
);
3393 DEBUG(3,("%d entries returned in queue\n",count
));
3396 END_PROFILE(SMBsplretq
);
3401 /****************************************************************************
3402 reply to a printwrite
3403 ****************************************************************************/
3404 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3407 int outsize
= set_message(outbuf
,0,0,True
);
3409 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3410 START_PROFILE(SMBsplwr
);
3412 if (!CAN_PRINT(conn
)) {
3413 END_PROFILE(SMBsplwr
);
3414 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3417 CHECK_FSP(fsp
,conn
);
3420 numtowrite
= SVAL(smb_buf(inbuf
),1);
3421 data
= smb_buf(inbuf
) + 3;
3423 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
3424 END_PROFILE(SMBsplwr
);
3425 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3428 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
3430 END_PROFILE(SMBsplwr
);
3435 /****************************************************************************
3436 The guts of the mkdir command, split out so it may be called by the NT SMB
3438 ****************************************************************************/
3439 NTSTATUS
mkdir_internal(connection_struct
*conn
, pstring directory
)
3441 BOOL bad_path
= False
;
3442 SMB_STRUCT_STAT sbuf
;
3445 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3447 if (check_name(directory
, conn
))
3448 ret
= vfs_mkdir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3451 NTSTATUS nterr
= set_bad_path_error(errno
, bad_path
);
3452 if (!NT_STATUS_IS_OK(nterr
))
3454 return map_nt_error_from_unix(errno
);
3457 return NT_STATUS_OK
;
3460 /****************************************************************************
3462 ****************************************************************************/
3464 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3469 START_PROFILE(SMBmkdir
);
3471 pstrcpy(directory
,smb_buf(inbuf
) + 1);
3473 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
);
3475 status
= mkdir_internal(conn
, directory
);
3476 if (!NT_STATUS_IS_OK(status
))
3477 return ERROR_NT(status
);
3479 outsize
= set_message(outbuf
,0,0,True
);
3481 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
3483 END_PROFILE(SMBmkdir
);
3487 /****************************************************************************
3488 Static function used by reply_rmdir to delete an entire directory
3489 tree recursively. Return False on ok, True on fail.
3490 ****************************************************************************/
3492 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
3496 void *dirptr
= OpenDir(conn
, directory
, False
);
3501 while((dname
= ReadDirName(dirptr
))) {
3505 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3508 /* Construct the full name. */
3509 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3515 pstrcpy(fullname
, directory
);
3516 pstrcat(fullname
, "/");
3517 pstrcat(fullname
, dname
);
3519 if(conn
->vfs_ops
.lstat(conn
,dos_to_unix_static(fullname
), &st
) != 0) {
3524 if(st
.st_mode
& S_IFDIR
) {
3525 if(recursive_rmdir(conn
, fullname
)!=0) {
3529 if(vfs_rmdir(conn
,fullname
) != 0) {
3533 } else if(vfs_unlink(conn
,fullname
) != 0) {
3543 /****************************************************************************
3544 The internals of the rmdir code - called elsewhere.
3545 ****************************************************************************/
3547 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
3551 ok
= (vfs_rmdir(conn
,directory
) == 0);
3552 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
3554 * Check to see if the only thing in this directory are
3555 * vetoed files/directories. If so then delete them and
3556 * retry. If we fail to delete any of them (and we *don't*
3557 * do a recursive delete) then fail the rmdir.
3559 BOOL all_veto_files
= True
;
3561 void *dirptr
= OpenDir(conn
, directory
, False
);
3563 if(dirptr
!= NULL
) {
3564 int dirpos
= TellDir(dirptr
);
3565 while ((dname
= ReadDirName(dirptr
))) {
3566 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3568 if(!IS_VETO_PATH(conn
, dname
)) {
3569 all_veto_files
= False
;
3573 if(all_veto_files
) {
3574 SeekDir(dirptr
,dirpos
);
3575 while ((dname
= ReadDirName(dirptr
))) {
3579 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3582 /* Construct the full name. */
3583 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3587 pstrcpy(fullname
, directory
);
3588 pstrcat(fullname
, "/");
3589 pstrcat(fullname
, dname
);
3591 if(conn
->vfs_ops
.lstat(conn
,dos_to_unix_static(fullname
), &st
) != 0)
3593 if(st
.st_mode
& S_IFDIR
) {
3594 if(lp_recursive_veto_delete(SNUM(conn
))) {
3595 if(recursive_rmdir(conn
, fullname
) != 0)
3598 if(vfs_rmdir(conn
,fullname
) != 0)
3600 } else if(vfs_unlink(conn
,fullname
) != 0)
3604 /* Retry the rmdir */
3605 ok
= (vfs_rmdir(conn
,directory
) == 0);
3615 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory
,strerror(errno
)));
3620 /****************************************************************************
3622 ****************************************************************************/
3624 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3629 BOOL bad_path
= False
;
3630 SMB_STRUCT_STAT sbuf
;
3631 START_PROFILE(SMBrmdir
);
3633 pstrcpy(directory
,smb_buf(inbuf
) + 1);
3635 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3637 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3639 if (check_name(directory
,conn
))
3641 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3642 ok
= rmdir_internals(conn
, directory
);
3647 set_bad_path_error(errno
, bad_path
);
3648 END_PROFILE(SMBrmdir
);
3649 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3652 outsize
= set_message(outbuf
,0,0,True
);
3654 DEBUG( 3, ( "rmdir %s\n", directory
) );
3656 END_PROFILE(SMBrmdir
);
3661 /*******************************************************************
3662 resolve wildcards in a filename rename
3663 ********************************************************************/
3664 static BOOL
resolve_wildcards(char *name1
,char *name2
)
3666 fstring root1
,root2
;
3670 name1
= strrchr(name1
,'/');
3671 name2
= strrchr(name2
,'/');
3673 if (!name1
|| !name2
) return(False
);
3675 fstrcpy(root1
,name1
);
3676 fstrcpy(root2
,name2
);
3677 p
= strrchr(root1
,'.');
3684 p
= strrchr(root2
,'.');
3716 pstrcpy(name2
,root2
);
3719 pstrcat(name2
,ext2
);
3725 /****************************************************************************
3726 The guts of the rename command, split out so it may be called by the NT SMB
3728 ****************************************************************************/
3730 NTSTATUS
rename_internals(connection_struct
*conn
, char *name
, char *newname
, BOOL replace_if_exists
)
3734 pstring newname_last_component
;
3737 BOOL bad_path1
= False
;
3738 BOOL bad_path2
= False
;
3740 NTSTATUS error
= NT_STATUS_OK
;
3742 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3744 *directory
= *mask
= 0;
3746 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
3747 unix_convert(newname
,conn
,newname_last_component
,&bad_path2
,&sbuf2
);
3750 * Split the old name into directory and last component
3751 * strings. Note that unix_convert may have stripped off a
3752 * leading ./ from both name and newname if the rename is
3753 * at the root of the share. We need to make sure either both
3754 * name and newname contain a / character or neither of them do
3755 * as this is checked in resolve_wildcards().
3758 p
= strrchr(name
,'/');
3760 pstrcpy(directory
,".");
3764 pstrcpy(directory
,name
);
3766 *p
= '/'; /* Replace needed for exceptional test below. */
3770 * We should only check the mangled cache
3771 * here if unix_convert failed. This means
3772 * that the path in 'mask' doesn't exist
3773 * on the file system and so we need to look
3774 * for a possible mangle. This patch from
3775 * Tine Smukavec <valentin.smukavec@hermes.si>.
3778 if (!rc
&& mangle_is_mangled(mask
))
3779 mangle_check_cache( mask
);
3781 has_wild
= ms_has_wild(mask
);
3788 * No wildcards - just process the one file.
3790 BOOL is_short_name
= mangle_is_8_3(name
, True
);
3792 /* Add a terminating '/' to the directory name. */
3793 pstrcat(directory
,"/");
3794 pstrcat(directory
,mask
);
3796 /* Ensure newname contains a '/' also */
3797 if(strrchr(newname
,'/') == 0) {
3800 pstrcpy(tmpstr
, "./");
3801 pstrcat(tmpstr
, newname
);
3802 pstrcpy(newname
, tmpstr
);
3805 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3806 directory = %s, newname = %s, newname_last_component = %s, mangle_is_8_3 = %d\n",
3807 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3808 newname
, newname_last_component
, is_short_name
));
3811 * Check for special case with case preserving and not
3812 * case sensitive, if directory and newname are identical,
3813 * and the old last component differs from the original
3814 * last component only by case, then we should allow
3815 * the rename (user is trying to change the case of the
3818 if((case_sensitive
== False
) &&
3819 (((case_preserve
== True
) &&
3820 (is_short_name
== False
)) ||
3821 ((short_case_preserve
== True
) &&
3822 (is_short_name
== True
))) &&
3823 strcsequal(directory
, newname
)) {
3824 pstring newname_modified_last_component
;
3827 * Get the last component of the modified name.
3828 * Note that we guarantee that newname contains a '/'
3831 p
= strrchr(newname
,'/');
3832 pstrcpy(newname_modified_last_component
,p
+1);
3834 if(strcsequal(newname_modified_last_component
,
3835 newname_last_component
) == False
) {
3837 * Replace the modified last component with
3840 pstrcpy(p
+1, newname_last_component
);
3845 resolve_wildcards(directory
,newname
);
3848 * The source object must exist.
3851 if (!vfs_object_exist(conn
, directory
, &sbuf1
)) {
3852 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3853 directory
,newname
));
3855 if (errno
== ENOTDIR
|| errno
== EISDIR
|| errno
== ENOENT
) {
3857 * Must return different errors depending on whether the parent
3858 * directory existed or not.
3861 p
= strrchr(directory
, '/');
3863 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3865 if (vfs_object_exist(conn
, directory
, NULL
))
3866 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3867 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3869 error
= map_nt_error_from_unix(errno
);
3870 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3871 get_nt_error_msg(error
), directory
,newname
));
3876 error
= can_rename(directory
,conn
,&sbuf1
);
3878 if (!NT_STATUS_IS_OK(error
)) {
3879 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3880 get_nt_error_msg(error
), directory
,newname
));
3884 pstrcpy(zdirectory
, dos_to_unix_static(directory
));
3885 pstrcpy(znewname
, dos_to_unix_static(newname
));
3888 * If the src and dest names are identical - including case,
3889 * don't do the rename, just return success.
3892 if (strcsequal(zdirectory
, znewname
)) {
3893 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory
));
3894 return NT_STATUS_OK
;
3897 if(!replace_if_exists
&& vfs_object_exist(conn
,newname
,NULL
)) {
3898 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3899 directory
,newname
));
3900 return NT_STATUS_OBJECT_NAME_COLLISION
;
3903 if(conn
->vfs_ops
.rename(conn
,zdirectory
, znewname
) == 0) {
3904 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3905 directory
,newname
));
3906 return NT_STATUS_OK
;
3909 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3910 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3912 error
= map_nt_error_from_unix(errno
);
3914 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3915 get_nt_error_msg(error
), directory
,newname
));
3921 * Wildcards - process each file that matches.
3923 void *dirptr
= NULL
;
3927 if (check_name(directory
,conn
))
3928 dirptr
= OpenDir(conn
, directory
, True
);
3931 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3933 if (strequal(mask
,"????????.???"))
3936 while ((dname
= ReadDirName(dirptr
))) {
3939 pstrcpy(fname
,dname
);
3941 if(!mask_match(fname
, mask
, case_sensitive
))
3944 error
= NT_STATUS_ACCESS_DENIED
;
3945 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3946 if (!vfs_object_exist(conn
, fname
, &sbuf1
)) {
3947 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3948 DEBUG(6,("rename %s failed. Error %s\n", fname
, get_nt_error_msg(error
)));
3951 error
= can_rename(fname
,conn
,&sbuf1
);
3952 if (!NT_STATUS_IS_OK(error
)) {
3953 DEBUG(6,("rename %s failed. Error %s\n", fname
, get_nt_error_msg(error
)));
3956 pstrcpy(destname
,newname
);
3958 if (!resolve_wildcards(fname
,destname
)) {
3959 DEBUG(6,("resolve_wildcards %s %s failed\n",
3964 if (!replace_if_exists
&&
3965 vfs_object_exist(conn
,destname
, NULL
)) {
3966 DEBUG(6,("file_exist %s\n", destname
));
3967 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3971 if (!conn
->vfs_ops
.rename(conn
,dos_to_unix_static(fname
),
3972 dos_to_unix_static(destname
)))
3974 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3980 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
3981 error
= map_nt_error_from_unix(errno
);
3987 /****************************************************************************
3989 ****************************************************************************/
3991 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3997 START_PROFILE(SMBmv
);
3999 pstrcpy(name
,smb_buf(inbuf
) + 1);
4000 pstrcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
4002 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
4003 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
4005 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
4007 status
= rename_internals(conn
, name
, newname
, False
);
4008 if (!NT_STATUS_IS_OK(status
)) {
4009 return ERROR_NT(status
);
4013 * Win2k needs a changenotify request response before it will
4014 * update after a rename..
4016 process_pending_change_notify_queue((time_t)0);
4017 outsize
= set_message(outbuf
,0,0,True
);
4023 /*******************************************************************
4024 Copy a file as part of a reply_copy.
4025 ******************************************************************/
4027 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
4028 int count
,BOOL target_is_directory
, int *err_ret
)
4031 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
4033 files_struct
*fsp1
,*fsp2
;
4038 pstrcpy(dest
,dest1
);
4039 if (target_is_directory
) {
4040 char *p
= strrchr(src
,'/');
4049 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
4052 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
4053 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
4058 if (!target_is_directory
&& count
)
4059 ofun
= FILE_EXISTS_OPEN
;
4061 if (vfs_stat(conn
,dest
,&sbuf2
) == -1)
4062 ZERO_STRUCTP(&sbuf2
);
4064 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
4065 ofun
,src_sbuf
.st_mode
,0,&Access
,&action
);
4068 close_file(fsp1
,False
);
4072 if ((ofun
&3) == 1) {
4073 if(conn
->vfs_ops
.lseek(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
4074 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
4076 * Stop the copy from occurring.
4079 src_sbuf
.st_size
= 0;
4083 if (src_sbuf
.st_size
)
4084 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
4086 close_file(fsp1
,False
);
4088 /* Ensure the modtime is set correctly on the destination file. */
4089 fsp2
->pending_modtime
= src_sbuf
.st_mtime
;
4092 * As we are opening fsp1 read-only we only expect
4093 * an error on close on fsp2 if we are out of space.
4094 * Thus we don't look at the error return from the
4097 *err_ret
= close_file(fsp2
,False
);
4099 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
4104 /****************************************************************************
4105 reply to a file copy.
4106 ****************************************************************************/
4107 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4112 pstring mask
,newname
;
4115 int error
= ERRnoaccess
;
4119 int tid2
= SVAL(inbuf
,smb_vwv0
);
4120 int ofun
= SVAL(inbuf
,smb_vwv1
);
4121 int flags
= SVAL(inbuf
,smb_vwv2
);
4122 BOOL target_is_directory
=False
;
4123 BOOL bad_path1
= False
;
4124 BOOL bad_path2
= False
;
4126 SMB_STRUCT_STAT sbuf1
, sbuf2
;
4127 START_PROFILE(SMBcopy
);
4129 *directory
= *mask
= 0;
4131 pstrcpy(name
,smb_buf(inbuf
));
4132 pstrcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
4134 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
4136 if (tid2
!= conn
->cnum
) {
4137 /* can't currently handle inter share copies XXXX */
4138 DEBUG(3,("Rejecting inter-share copy\n"));
4139 END_PROFILE(SMBcopy
);
4140 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
4143 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
4144 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
4146 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
4147 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
4149 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
4151 if ((flags
&1) && target_is_directory
) {
4152 END_PROFILE(SMBcopy
);
4153 return ERROR_DOS(ERRDOS
,ERRbadfile
);
4156 if ((flags
&2) && !target_is_directory
) {
4157 END_PROFILE(SMBcopy
);
4158 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4161 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
4162 /* wants a tree copy! XXXX */
4163 DEBUG(3,("Rejecting tree copy\n"));
4164 END_PROFILE(SMBcopy
);
4165 return ERROR_DOS(ERRSRV
,ERRerror
);
4168 p
= strrchr(name
,'/');
4170 pstrcpy(directory
,"./");
4174 pstrcpy(directory
,name
);
4179 * We should only check the mangled cache
4180 * here if unix_convert failed. This means
4181 * that the path in 'mask' doesn't exist
4182 * on the file system and so we need to look
4183 * for a possible mangle. This patch from
4184 * Tine Smukavec <valentin.smukavec@hermes.si>.
4187 if (!rc
&& mangle_is_mangled(mask
))
4188 mangle_check_cache( mask
);
4190 has_wild
= ms_has_wild(mask
);
4193 pstrcat(directory
,"/");
4194 pstrcat(directory
,mask
);
4195 if (resolve_wildcards(directory
,newname
) &&
4196 copy_file(directory
,newname
,conn
,ofun
,
4197 count
,target_is_directory
,&err
)) count
++;
4200 END_PROFILE(SMBcopy
);
4201 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4203 if (!count
) exists
= vfs_file_exist(conn
,directory
,NULL
);
4205 void *dirptr
= NULL
;
4209 if (check_name(directory
,conn
))
4210 dirptr
= OpenDir(conn
, directory
, True
);
4215 if (strequal(mask
,"????????.???"))
4218 while ((dname
= ReadDirName(dirptr
))) {
4220 pstrcpy(fname
,dname
);
4222 if(!mask_match(fname
, mask
, case_sensitive
))
4225 error
= ERRnoaccess
;
4226 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
4227 pstrcpy(destname
,newname
);
4228 if (resolve_wildcards(fname
,destname
) &&
4229 copy_file(fname
,destname
,conn
,ofun
,
4230 count
,target_is_directory
,&err
)) count
++;
4231 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
4239 /* Error on close... */
4241 END_PROFILE(SMBcopy
);
4242 return(UNIXERROR(ERRHRD
,ERRgeneral
));
4246 END_PROFILE(SMBcopy
);
4247 return ERROR_DOS(ERRDOS
,error
);
4250 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
4252 unix_ERR_class
= ERRDOS
;
4253 unix_ERR_code
= ERRbadpath
;
4255 END_PROFILE(SMBcopy
);
4256 return(UNIXERROR(ERRDOS
,error
));
4260 outsize
= set_message(outbuf
,1,0,True
);
4261 SSVAL(outbuf
,smb_vwv0
,count
);
4263 END_PROFILE(SMBcopy
);
4267 /****************************************************************************
4269 ****************************************************************************/
4270 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4276 START_PROFILE(pathworks_setdir
);
4279 if (!CAN_SETDIR(snum
)) {
4280 END_PROFILE(pathworks_setdir
);
4281 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4284 pstrcpy(newdir
,smb_buf(inbuf
) + 1);
4287 if (strlen(newdir
) == 0) {
4290 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
4292 string_set(&conn
->connectpath
,newdir
);
4297 END_PROFILE(pathworks_setdir
);
4298 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4301 outsize
= set_message(outbuf
,0,0,True
);
4302 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
4304 DEBUG(3,("setdir %s\n", newdir
));
4306 END_PROFILE(pathworks_setdir
);
4310 /****************************************************************************
4311 Get a lock pid, dealing with large count requests.
4312 ****************************************************************************/
4314 uint16
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
4316 if(!large_file_format
)
4317 return SVAL(data
,SMB_LPID_OFFSET(data_offset
));
4319 return SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
4322 /****************************************************************************
4323 Get a lock count, dealing with large count requests.
4324 ****************************************************************************/
4326 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
4328 SMB_BIG_UINT count
= 0;
4330 if(!large_file_format
) {
4331 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
4334 #if defined(HAVE_LONGLONG)
4335 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
4336 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
4337 #else /* HAVE_LONGLONG */
4340 * NT4.x seems to be broken in that it sends large file (64 bit)
4341 * lockingX calls even if the CAP_LARGE_FILES was *not*
4342 * negotiated. For boxes without large unsigned ints truncate the
4343 * lock count by dropping the top 32 bits.
4346 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
4347 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4348 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
4349 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
4350 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
4353 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
4354 #endif /* HAVE_LONGLONG */
4360 #if !defined(HAVE_LONGLONG)
4361 /****************************************************************************
4362 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4363 ****************************************************************************/
4365 static uint32
map_lock_offset(uint32 high
, uint32 low
)
4369 uint32 highcopy
= high
;
4372 * Try and find out how many significant bits there are in high.
4375 for(i
= 0; highcopy
; i
++)
4379 * We use 31 bits not 32 here as POSIX
4380 * lock offsets may not be negative.
4383 mask
= (~0) << (31 - i
);
4386 return 0; /* Fail. */
4392 #endif /* !defined(HAVE_LONGLONG) */
4394 /****************************************************************************
4395 Get a lock offset, dealing with large offset requests.
4396 ****************************************************************************/
4398 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
4400 SMB_BIG_UINT offset
= 0;
4404 if(!large_file_format
) {
4405 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
4408 #if defined(HAVE_LONGLONG)
4409 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
4410 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
4411 #else /* HAVE_LONGLONG */
4414 * NT4.x seems to be broken in that it sends large file (64 bit)
4415 * lockingX calls even if the CAP_LARGE_FILES was *not*
4416 * negotiated. For boxes without large unsigned ints mangle the
4417 * lock offset by mapping the top 32 bits onto the lower 32.
4420 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
4421 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4422 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
4425 if((new_low
= map_lock_offset(high
, low
)) == 0) {
4427 return (SMB_BIG_UINT
)-1;
4430 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4431 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
4432 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
4433 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
4436 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4437 #endif /* HAVE_LONGLONG */
4443 /****************************************************************************
4444 reply to a lockingX request
4445 ****************************************************************************/
4447 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4449 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
4450 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
4451 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
4452 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
4453 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
4454 SMB_BIG_UINT count
= 0, offset
= 0;
4456 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
4459 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
4463 START_PROFILE(SMBlockingX
);
4465 CHECK_FSP(fsp
,conn
);
4467 data
= smb_buf(inbuf
);
4469 if (locktype
& (LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_CHANGE_LOCKTYPE
)) {
4470 /* we don't support these - and CANCEL_LOCK makes w2k
4471 and XP reboot so I don't really want to be
4472 compatible! (tridge) */
4473 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
4476 /* Check if this is an oplock break on a file
4477 we have granted an oplock on.
4479 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
4480 /* Client can insist on breaking to none. */
4481 BOOL break_to_none
= (oplocklevel
== 0);
4483 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4484 (unsigned int)oplocklevel
, fsp
->fnum
));
4487 * Make sure we have granted an exclusive or batch oplock on this file.
4490 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
4491 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4492 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
4494 /* if this is a pure oplock break request then don't send a reply */
4495 if (num_locks
== 0 && num_ulocks
== 0) {
4496 END_PROFILE(SMBlockingX
);
4499 END_PROFILE(SMBlockingX
);
4500 return ERROR_DOS(ERRDOS
,ERRlock
);
4504 if (remove_oplock(fsp
, break_to_none
) == False
) {
4505 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4509 /* if this is a pure oplock break request then don't send a reply */
4510 if (num_locks
== 0 && num_ulocks
== 0) {
4511 /* Sanity check - ensure a pure oplock break is not a
4513 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
4514 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4515 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
4516 END_PROFILE(SMBlockingX
);
4522 * We do this check *after* we have checked this is not a oplock break
4523 * response message. JRA.
4526 release_level_2_oplocks_on_change(fsp
);
4528 /* Data now points at the beginning of the list
4529 of smb_unlkrng structs */
4530 for(i
= 0; i
< (int)num_ulocks
; i
++) {
4531 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4532 count
= get_lock_count( data
, i
, large_file_format
);
4533 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4536 * There is no error code marked "stupid client bug".... :-).
4539 END_PROFILE(SMBlockingX
);
4540 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4543 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4544 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
4546 status
= do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4547 if (NT_STATUS_V(status
)) {
4548 END_PROFILE(SMBlockingX
);
4549 return ERROR_NT(status
);
4553 /* Setup the timeout in seconds. */
4555 lock_timeout
= ((lock_timeout
== -1) ? -1 : (lock_timeout
+999)/1000);
4557 /* Now do any requested locks */
4558 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
4560 /* Data now points at the beginning of the list
4561 of smb_lkrng structs */
4563 for(i
= 0; i
< (int)num_locks
; i
++) {
4564 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4565 count
= get_lock_count( data
, i
, large_file_format
);
4566 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4569 * There is no error code marked "stupid client bug".... :-).
4572 END_PROFILE(SMBlockingX
);
4573 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4576 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4577 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
,
4578 (int)lock_timeout
));
4580 status
= do_lock_spin(fsp
,conn
,lock_pid
, count
,offset
,
4581 ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
));
4583 if (NT_STATUS_V(status
)) {
4584 if ((lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
))) {
4586 * A blocking lock was requested. Package up
4587 * this smb into a queued request and push it
4588 * onto the blocking lock queue.
4590 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
)) {
4591 END_PROFILE(SMBlockingX
);
4599 /* If any of the above locks failed, then we must unlock
4600 all of the previous locks (X/Open spec). */
4601 if(i
!= num_locks
&& num_locks
!= 0) {
4603 * Ensure we don't do a remove on the lock that just failed,
4604 * as under POSIX rules, if we have a lock already there, we
4605 * will delete it (and we shouldn't) .....
4607 for(i
--; i
>= 0; i
--) {
4608 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4609 count
= get_lock_count( data
, i
, large_file_format
);
4610 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4613 * There is no error code marked "stupid client bug".... :-).
4616 END_PROFILE(SMBlockingX
);
4617 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4620 do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4622 END_PROFILE(SMBlockingX
);
4623 return ERROR_NT(status
);
4626 set_message(outbuf
,2,0,True
);
4628 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4629 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4631 END_PROFILE(SMBlockingX
);
4632 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4635 /* Back from the dead for OS/2..... JRA. */
4637 /****************************************************************************
4638 Reply to a SMBreadbmpx (read block multiplex) request
4639 ****************************************************************************/
4641 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4652 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4653 START_PROFILE(SMBreadBmpx
);
4655 /* this function doesn't seem to work - disable by default */
4656 if (!lp_readbmpx()) {
4657 END_PROFILE(SMBreadBmpx
);
4658 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
4661 outsize
= set_message(outbuf
,8,0,True
);
4663 CHECK_FSP(fsp
,conn
);
4667 startpos
= IVAL(inbuf
,smb_vwv1
);
4668 maxcount
= SVAL(inbuf
,smb_vwv3
);
4670 data
= smb_buf(outbuf
);
4671 pad
= ((long)data
)%4;
4676 max_per_packet
= bufsize
-(outsize
+pad
);
4680 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
, False
)) {
4681 END_PROFILE(SMBreadBmpx
);
4682 return ERROR_DOS(ERRDOS
,ERRlock
);
4686 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4688 nread
= read_file(fsp
,data
,startpos
,N
);
4693 if (nread
< (ssize_t
)N
)
4694 tcount
= total_read
+ nread
;
4696 set_message(outbuf
,8,nread
,False
);
4697 SIVAL(outbuf
,smb_vwv0
,startpos
);
4698 SSVAL(outbuf
,smb_vwv2
,tcount
);
4699 SSVAL(outbuf
,smb_vwv6
,nread
);
4700 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4702 if (!send_smb(smbd_server_fd(),outbuf
))
4703 exit_server("reply_readbmpx: send_smb failed.");
4705 total_read
+= nread
;
4707 } while (total_read
< (ssize_t
)tcount
);
4709 END_PROFILE(SMBreadBmpx
);
4713 /****************************************************************************
4714 Reply to a SMBsetattrE.
4715 ****************************************************************************/
4717 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4719 struct utimbuf unix_times
;
4721 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4722 START_PROFILE(SMBsetattrE
);
4724 outsize
= set_message(outbuf
,0,0,True
);
4726 if(!fsp
|| (fsp
->conn
!= conn
)) {
4727 END_PROFILE(SMBgetattrE
);
4728 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4732 * Convert the DOS times into unix times. Ignore create
4733 * time as UNIX can't set this.
4735 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4736 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4739 * Patch from Ray Frush <frush@engr.colostate.edu>
4740 * Sometimes times are sent as zero - ignore them.
4743 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0)) {
4744 /* Ignore request */
4745 if( DEBUGLVL( 3 ) ) {
4746 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4747 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4749 END_PROFILE(SMBsetattrE
);
4751 } else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0)) {
4752 /* set modify time = to access time if modify time was 0 */
4753 unix_times
.modtime
= unix_times
.actime
;
4756 /* Set the date on this file */
4757 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4758 END_PROFILE(SMBsetattrE
);
4759 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4762 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4763 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4765 END_PROFILE(SMBsetattrE
);
4770 /* Back from the dead for OS/2..... JRA. */
4772 /****************************************************************************
4773 Reply to a SMBwritebmpx (write block multiplex primary) request.
4774 ****************************************************************************/
4776 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4779 ssize_t nwritten
= -1;
4786 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4787 START_PROFILE(SMBwriteBmpx
);
4789 CHECK_FSP(fsp
,conn
);
4793 tcount
= SVAL(inbuf
,smb_vwv1
);
4794 startpos
= IVAL(inbuf
,smb_vwv3
);
4795 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
4796 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4797 smb_doff
= SVAL(inbuf
,smb_vwv11
);
4799 data
= smb_base(inbuf
) + smb_doff
;
4801 /* If this fails we need to send an SMBwriteC response,
4802 not an SMBwritebmpx - set this up now so we don't forget */
4803 SCVAL(outbuf
,smb_com
,SMBwritec
);
4805 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
,False
)) {
4806 END_PROFILE(SMBwriteBmpx
);
4807 return(ERROR_DOS(ERRDOS
,ERRlock
));
4810 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4812 if(lp_syncalways(SNUM(conn
)) || write_through
)
4813 sync_file(conn
,fsp
);
4815 if(nwritten
< (ssize_t
)numtowrite
) {
4816 END_PROFILE(SMBwriteBmpx
);
4817 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
4820 /* If the maximum to be written to this file
4821 is greater than what we just wrote then set
4822 up a secondary struct to be attached to this
4823 fd, we will use this to cache error messages etc. */
4825 if((ssize_t
)tcount
> nwritten
) {
4826 write_bmpx_struct
*wbms
;
4827 if(fsp
->wbmpx_ptr
!= NULL
)
4828 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
4830 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
4833 DEBUG(0,("Out of memory in reply_readmpx\n"));
4834 END_PROFILE(SMBwriteBmpx
);
4835 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
4837 wbms
->wr_mode
= write_through
;
4838 wbms
->wr_discard
= False
; /* No errors yet */
4839 wbms
->wr_total_written
= nwritten
;
4840 wbms
->wr_errclass
= 0;
4842 fsp
->wbmpx_ptr
= wbms
;
4845 /* We are returning successfully, set the message type back to
4847 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
4849 outsize
= set_message(outbuf
,1,0,True
);
4851 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
4853 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4854 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
4856 if (write_through
&& tcount
==nwritten
) {
4857 /* We need to send both a primary and a secondary response */
4858 smb_setlen(outbuf
,outsize
- 4);
4859 if (!send_smb(smbd_server_fd(),outbuf
))
4860 exit_server("reply_writebmpx: send_smb failed.");
4862 /* Now the secondary */
4863 outsize
= set_message(outbuf
,1,0,True
);
4864 SCVAL(outbuf
,smb_com
,SMBwritec
);
4865 SSVAL(outbuf
,smb_vwv0
,nwritten
);
4868 END_PROFILE(SMBwriteBmpx
);
4872 /****************************************************************************
4873 Reply to a SMBwritebs (write block multiplex secondary) request.
4874 ****************************************************************************/
4876 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4879 ssize_t nwritten
= -1;
4886 write_bmpx_struct
*wbms
;
4887 BOOL send_response
= False
;
4888 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4889 START_PROFILE(SMBwriteBs
);
4891 CHECK_FSP(fsp
,conn
);
4894 tcount
= SVAL(inbuf
,smb_vwv1
);
4895 startpos
= IVAL(inbuf
,smb_vwv2
);
4896 numtowrite
= SVAL(inbuf
,smb_vwv6
);
4897 smb_doff
= SVAL(inbuf
,smb_vwv7
);
4899 data
= smb_base(inbuf
) + smb_doff
;
4901 /* We need to send an SMBwriteC response, not an SMBwritebs */
4902 SCVAL(outbuf
,smb_com
,SMBwritec
);
4904 /* This fd should have an auxiliary struct attached,
4905 check that it does */
4906 wbms
= fsp
->wbmpx_ptr
;
4908 END_PROFILE(SMBwriteBs
);
4912 /* If write through is set we can return errors, else we must cache them */
4913 write_through
= wbms
->wr_mode
;
4915 /* Check for an earlier error */
4916 if(wbms
->wr_discard
) {
4917 END_PROFILE(SMBwriteBs
);
4918 return -1; /* Just discard the packet */
4921 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4923 if(lp_syncalways(SNUM(conn
)) || write_through
)
4924 sync_file(conn
,fsp
);
4926 if (nwritten
< (ssize_t
)numtowrite
) {
4928 /* We are returning an error - we can delete the aux struct */
4930 fsp
->wbmpx_ptr
= NULL
;
4931 END_PROFILE(SMBwriteBs
);
4932 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
4934 END_PROFILE(SMBwriteBs
);
4935 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4938 /* Increment the total written, if this matches tcount
4939 we can discard the auxiliary struct (hurrah !) and return a writeC */
4940 wbms
->wr_total_written
+= nwritten
;
4941 if(wbms
->wr_total_written
>= tcount
) {
4942 if (write_through
) {
4943 outsize
= set_message(outbuf
,1,0,True
);
4944 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4945 send_response
= True
;
4949 fsp
->wbmpx_ptr
= NULL
;
4953 END_PROFILE(SMBwriteBs
);
4957 END_PROFILE(SMBwriteBs
);
4961 /****************************************************************************
4962 Reply to a SMBgetattrE.
4963 ****************************************************************************/
4965 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4967 SMB_STRUCT_STAT sbuf
;
4970 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4971 START_PROFILE(SMBgetattrE
);
4973 outsize
= set_message(outbuf
,11,0,True
);
4975 if(!fsp
|| (fsp
->conn
!= conn
)) {
4976 END_PROFILE(SMBgetattrE
);
4977 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4980 /* Do an stat on this file */
4982 if(fsp_stat(fsp
, &sbuf
)) {
4983 END_PROFILE(SMBgetattrE
);
4984 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4987 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4989 /* Convert the times into dos times. Set create
4990 * date to be last modify date as UNIX doesn't save
4994 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4995 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4996 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4998 SIVAL(outbuf
,smb_vwv6
,0);
4999 SIVAL(outbuf
,smb_vwv8
,0);
5001 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
5002 SIVAL(outbuf
,smb_vwv8
,SMB_ROUNDUP(sbuf
.st_size
,1024));
5004 SSVAL(outbuf
,smb_vwv10
, mode
);
5006 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
5008 END_PROFILE(SMBgetattrE
);