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
31 /* look in server.c for some explanation of these variables */
33 extern int DEBUGLEVEL;
36 extern char magic_char;
37 extern BOOL case_sensitive;
38 extern BOOL case_preserve;
39 extern BOOL short_case_preserve;
40 extern pstring sesssetup_user;
41 extern pstring global_myname;
42 extern fstring global_myworkgroup;
44 extern int global_oplock_break;
45 uint32 global_client_caps = 0;
46 unsigned int smb_echo_count = 0;
48 /****************************************************************************
49 report a possible attack via the password buffer overflow bug
50 ****************************************************************************/
52 static void overflow_attack(int len)
55 dbgtext( "ERROR: Invalid password length %d.\n", len );
56 dbgtext( "Your machine may be under attack by someone " );
57 dbgtext( "attempting to exploit an old bug.\n" );
58 dbgtext( "Attack was from IP = %s.\n", client_addr(Client) );
60 exit_server("possible attack");
64 /****************************************************************************
65 reply to an special message
66 ****************************************************************************/
68 int reply_special(char *inbuf,char *outbuf)
71 int msg_type = CVAL(inbuf,0);
72 int msg_flags = CVAL(inbuf,1);
74 extern fstring remote_machine;
75 extern fstring local_machine;
81 memset(outbuf,'\0',smb_size);
86 case 0x81: /* session request */
87 CVAL(outbuf,0) = 0x82;
89 if (name_len(inbuf+4) > 50 ||
90 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
91 DEBUG(0,("Invalid name length in session request\n"));
94 name_extract(inbuf,4,name1);
95 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
96 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
99 fstrcpy(remote_machine,name2);
100 remote_machine[15] = 0;
101 trim_string(remote_machine," "," ");
102 strlower(remote_machine);
104 fstrcpy(local_machine,name1);
105 len = strlen(local_machine);
107 name_type = local_machine[15];
108 local_machine[15] = 0;
110 trim_string(local_machine," "," ");
111 strlower(local_machine);
113 if (name_type == 'R') {
114 /* We are being asked for a pathworks session ---
116 CVAL(outbuf, 0) = 0x83;
120 add_session_user(remote_machine);
122 reload_services(True);
126 claim_connection(NULL,"",MAXSTATUS,True);
131 case 0x89: /* session keepalive request
132 (some old clients produce this?) */
133 CVAL(outbuf,0) = 0x85;
137 case 0x82: /* positive session response */
138 case 0x83: /* negative session response */
139 case 0x84: /* retarget session response */
140 DEBUG(0,("Unexpected session response\n"));
143 case 0x85: /* session keepalive */
148 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
149 msg_type, msg_flags));
155 /*******************************************************************
156 work out what error to give to a failed connection
157 ********************************************************************/
159 static int connection_error(char *inbuf,char *outbuf,int ecode)
161 if (ecode == ERRnoipc)
162 return(ERROR(ERRDOS,ERRnoipc));
164 return(ERROR(ERRSRV,ecode));
169 /****************************************************************************
170 parse a share descriptor string
171 ****************************************************************************/
172 static void parse_connect(char *p,char *service,char *user,
173 char *password,int *pwlen,char *dev)
177 DEBUG(4,("parsing connect string %s\n",p));
179 p2 = strrchr(p,'\\');
183 fstrcpy(service,p2+1);
188 *pwlen = strlen(password);
195 p = strchr(service,'%');
203 /****************************************************************************
205 ****************************************************************************/
207 int reply_tcon(connection_struct *conn,
208 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
210 BOOL doencrypt = SMBENCRYPT();
216 uint16 vuid = SVAL(inbuf,smb_uid);
220 *service = *user = *password = *dev = 0;
222 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
225 * Ensure the user and password names are in UNIX codepage format.
228 dos_to_unix(user,True);
230 dos_to_unix(password,True);
233 * Pass the user through the NT -> unix user mapping
237 (void)map_username(user);
240 * Do any UNIX username case mangling.
242 (void)Get_Pwnam( user, True);
244 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
247 return(connection_error(inbuf,outbuf,ecode));
250 outsize = set_message(outbuf,2,0,True);
251 SSVAL(outbuf,smb_vwv0,max_recv);
252 SSVAL(outbuf,smb_vwv1,conn->cnum);
253 SSVAL(outbuf,smb_tid,conn->cnum);
255 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
256 service, user, conn->cnum));
261 /****************************************************************************
262 Reply to a tcon and X.
263 ****************************************************************************/
265 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
271 BOOL doencrypt = SMBENCRYPT();
273 uint16 vuid = SVAL(inbuf,smb_uid);
274 int passlen = SVAL(inbuf,smb_vwv3);
278 *service = *user = *password = *devicename = 0;
280 /* we might have to close an old one */
281 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
282 close_cnum(conn,vuid);
285 if (passlen > MAX_PASS_LEN) {
286 overflow_attack(passlen);
289 memcpy(password,smb_buf(inbuf),passlen);
291 path = smb_buf(inbuf) + passlen;
294 if (strequal(password," "))
296 passlen = strlen(password);
299 fstrcpy(service,path+2);
300 p = strchr(service,'\\');
302 return(ERROR(ERRSRV,ERRinvnetname));
304 fstrcpy(service,p+1);
305 p = strchr(service,'%');
310 StrnCpy(devicename,path + strlen(path) + 1,6);
311 DEBUG(4,("Got device type %s\n",devicename));
314 * Ensure the user and password names are in UNIX codepage format.
317 dos_to_unix(user,True);
319 dos_to_unix(password,True);
322 * Pass the user through the NT -> unix user mapping
326 (void)map_username(user);
329 * Do any UNIX username case mangling.
331 (void)Get_Pwnam(user, True);
333 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
336 return(connection_error(inbuf,outbuf,ecode));
338 if (Protocol < PROTOCOL_NT1) {
339 set_message(outbuf,2,strlen(devicename)+1,True);
340 pstrcpy(smb_buf(outbuf),devicename);
342 char *fsname = lp_fstype(SNUM(conn));
344 set_message(outbuf,3,3,True);
347 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
348 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
350 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
352 /* what does setting this bit do? It is set by NT4 and
353 may affect the ability to autorun mounted cdroms */
354 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
357 DEBUG(3,("tconX service=%s user=%s\n",
360 /* set the incoming and outgoing tid to the just created one */
361 SSVAL(inbuf,smb_tid,conn->cnum);
362 SSVAL(outbuf,smb_tid,conn->cnum);
364 return chain_reply(inbuf,outbuf,length,bufsize);
368 /****************************************************************************
369 reply to an unknown type
370 ****************************************************************************/
371 int reply_unknown(char *inbuf,char *outbuf)
374 type = CVAL(inbuf,smb_com);
376 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
377 smb_fn_name(type), type, type));
379 return(ERROR(ERRSRV,ERRunknownsmb));
383 /****************************************************************************
385 ****************************************************************************/
386 int reply_ioctl(connection_struct *conn,
387 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
389 uint16 device = SVAL(inbuf,smb_vwv1);
390 uint16 function = SVAL(inbuf,smb_vwv2);
391 uint32 ioctl_code = (device << 16) + function;
392 int replysize, outsize;
395 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
399 case IOCTL_QUERY_JOB_INFO:
403 return(ERROR(ERRSRV,ERRnosupport));
406 outsize = set_message(outbuf,8,replysize+1,True);
407 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
408 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
409 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
410 p = smb_buf(outbuf) + 1; /* Allow for alignment */
414 case IOCTL_QUERY_JOB_INFO:
415 SSVAL(p,0,1); /* Job number */
416 StrnCpy(p+2, global_myname, 15); /* Our NetBIOS name */
417 StrnCpy(p+18, lp_servicename(SNUM(conn)), 13); /* Service name */
424 /****************************************************************************
425 always return an error: it's just a matter of which one...
426 ****************************************************************************/
427 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
428 char *smb_passwd, int smb_passlen,
429 char *smb_nt_passwd, int smb_nt_passlen)
431 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
432 if (lp_security() == SEC_USER)
434 smb_trust_acct = getsmbpwnam(user);
438 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
439 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
440 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
443 if (smb_trust_acct == NULL)
445 /* lkclXXXX: workstation entry doesn't exist */
446 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
447 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
448 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
452 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
454 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
455 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
456 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
459 if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
461 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
462 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
463 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
466 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
468 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
469 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
470 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
473 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
475 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
476 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
477 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
480 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
482 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
483 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
484 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
488 /* don't know what to do: indicate logon failure */
489 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
490 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
493 /****************************************************************************
494 Create a UNIX user on demand.
495 ****************************************************************************/
497 static int smb_create_user(char *unix_user)
502 pstrcpy(add_script, lp_adduser_script());
503 pstring_sub(add_script, "%u", unix_user);
504 ret = smbrun(add_script,NULL,False);
505 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
509 /****************************************************************************
510 Delete a UNIX user on demand.
511 ****************************************************************************/
513 static int smb_delete_user(char *unix_user)
518 pstrcpy(del_script, lp_deluser_script());
519 pstring_sub(del_script, "%u", unix_user);
520 ret = smbrun(del_script,NULL,False);
521 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
525 /****************************************************************************
526 Check user is in correct domain if required
527 ****************************************************************************/
529 static BOOL check_domain_match(char *user, char *domain)
532 * If we aren't serving to trusted domains, we must make sure that
533 * the validation request comes from an account in the same domain
534 * as the Samba server
537 if (!lp_allow_trusted_domains() &&
538 !strequal(lp_workgroup(), domain) ) {
539 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
546 /****************************************************************************
547 Check for a valid username and password in security=server mode.
548 ****************************************************************************/
550 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
551 char *smb_apasswd, int smb_apasslen,
552 char *smb_ntpasswd, int smb_ntpasslen)
556 if(lp_security() != SEC_SERVER)
559 if (!check_domain_match(orig_user, domain))
562 ret = server_validate(orig_user, domain,
563 smb_apasswd, smb_apasslen,
564 smb_ntpasswd, smb_ntpasslen);
567 * User validated ok against Domain controller.
568 * If the admin wants us to try and create a UNIX
569 * user on the fly, do so.
570 * Note that we can never delete users when in server
571 * level security as we never know if it was a failure
572 * due to a bad password, or the user really doesn't exist.
574 if(lp_adduser_script() && !Get_Pwnam(unix_user,True)) {
575 smb_create_user(unix_user);
582 /****************************************************************************
583 Check for a valid username and password in security=domain mode.
584 ****************************************************************************/
586 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
587 char *smb_apasswd, int smb_apasslen,
588 char *smb_ntpasswd, int smb_ntpasslen)
591 BOOL user_exists = True;
593 if(lp_security() != SEC_DOMAIN)
596 if (!check_domain_match(orig_user, domain))
599 ret = domain_client_validate(orig_user, domain,
600 smb_apasswd, smb_apasslen,
601 smb_ntpasswd, smb_ntpasslen,
606 * User validated ok against Domain controller.
607 * If the admin wants us to try and create a UNIX
608 * user on the fly, do so.
610 if(user_exists && lp_adduser_script() && !Get_Pwnam(unix_user,True)) {
611 smb_create_user(unix_user);
615 * User failed to validate ok against Domain controller.
616 * If the failure was "user doesn't exist" and admin
617 * wants us to try and delete that UNIX user on the fly,
620 if(!user_exists && lp_deluser_script() && Get_Pwnam(unix_user,True)) {
621 smb_delete_user(unix_user);
628 /****************************************************************************
629 Return a bad password error configured for the correct client type.
630 ****************************************************************************/
632 static int bad_password_error(char *inbuf,char *outbuf)
634 enum remote_arch_types ra_type = get_remote_arch();
636 if(ra_type == RA_WINNT && (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
637 SSVAL(outbuf,smb_flg2,FLAGS2_32_BIT_ERROR_CODES);
638 return(ERROR(0,0xc0000000|NT_STATUS_LOGON_FAILURE));
641 return(ERROR(ERRSRV,ERRbadpw));
644 /****************************************************************************
645 reply to a session setup command
646 ****************************************************************************/
648 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
654 int smb_apasslen = 0;
656 int smb_ntpasslen = 0;
657 pstring smb_ntpasswd;
658 BOOL valid_nt_password = False;
662 static BOOL done_sesssetup = False;
663 BOOL doencrypt = SMBENCRYPT();
669 smb_bufsize = SVAL(inbuf,smb_vwv2);
671 if (Protocol < PROTOCOL_NT1) {
672 smb_apasslen = SVAL(inbuf,smb_vwv7);
673 if (smb_apasslen > MAX_PASS_LEN)
674 overflow_attack(smb_apasslen);
676 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
677 smb_apasswd[smb_apasslen] = 0;
678 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
680 * Incoming user is in DOS codepage format. Convert
683 dos_to_unix(user,True);
685 if (!doencrypt && (lp_security() != SEC_SERVER)) {
686 smb_apasslen = strlen(smb_apasswd);
689 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
690 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
691 enum remote_arch_types ra_type = get_remote_arch();
692 char *p = smb_buf(inbuf);
694 if(global_client_caps == 0)
695 global_client_caps = IVAL(inbuf,smb_vwv11);
697 /* client_caps is used as final determination if client is NT or Win95.
698 This is needed to return the correct error codes in some
702 if(ra_type == RA_WINNT || ra_type == RA_WIN95) {
703 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
704 set_remote_arch( RA_WINNT);
706 set_remote_arch( RA_WIN95);
709 if (passlen1 != 24 && passlen2 != 24)
712 if (passlen1 > MAX_PASS_LEN) {
713 overflow_attack(passlen1);
716 passlen1 = MIN(passlen1, MAX_PASS_LEN);
717 passlen2 = MIN(passlen2, MAX_PASS_LEN);
720 /* both Win95 and WinNT stuff up the password lengths for
721 non-encrypting systems. Uggh.
723 if passlen1==24 its a win95 system, and its setting the
724 password length incorrectly. Luckily it still works with the
725 default code because Win95 will null terminate the password
728 if passlen1>0 and passlen2>0 then maybe its a NT box and its
729 setting passlen2 to some random value which really stuffs
730 things up. we need to fix that one. */
732 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
736 if (lp_restrict_anonymous()) {
737 /* there seems to be no reason behind the differences in MS clients formatting
738 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
739 * in particular seems to have an extra null byte between the username and the
740 * domain, or the password length calculation is wrong, which throws off the
741 * string extraction routines below. This makes the value of domain be the
742 * empty string, which fails the restrict anonymous check further down.
743 * This compensates for that, and allows browsing to work in mixed NT and
744 * win95 environments even when restrict anonymous is true. AAB
746 dump_data(100, p, 0x70);
747 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
748 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
749 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
750 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
751 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
756 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
757 /* Save the lanman2 password and the NT md4 password. */
758 smb_apasslen = passlen1;
759 memcpy(smb_apasswd,p,smb_apasslen);
760 smb_apasswd[smb_apasslen] = 0;
761 smb_ntpasslen = passlen2;
762 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
763 smb_ntpasswd[smb_ntpasslen] = 0;
766 * Ensure the plaintext passwords are in UNIX format.
769 dos_to_unix(smb_apasswd,True);
770 dos_to_unix(smb_ntpasswd,True);
774 /* we use the first password that they gave */
775 smb_apasslen = passlen1;
776 StrnCpy(smb_apasswd,p,smb_apasslen);
778 * Ensure the plaintext password is in UNIX format.
780 dos_to_unix(smb_apasswd,True);
782 /* trim the password */
783 smb_apasslen = strlen(smb_apasswd);
785 /* wfwg sometimes uses a space instead of a null */
786 if (strequal(smb_apasswd," ")) {
792 p += passlen1 + passlen2;
794 p = skip_string(p,1);
796 * Incoming user is in DOS codepage format. Convert
799 dos_to_unix(user,True);
802 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
803 domain,skip_string(p,1),skip_string(p,2)));
807 DEBUG(3,("sesssetupX:name=[%s]\n",user));
809 /* If name ends in $ then I think it's asking about whether a */
810 /* computer with that name (minus the $) has access. For now */
811 /* say yes to everything ending in $. */
813 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
814 return session_trust_account(conn, inbuf, outbuf, user,
815 smb_apasswd, smb_apasslen,
816 smb_ntpasswd, smb_ntpasslen);
819 if (done_sesssetup && lp_restrict_anonymous()) {
820 /* tests show that even if browsing is done over already validated connections
821 * without a username and password the domain is still provided, which it
822 * wouldn't be if it was a purely anonymous connection. So, in order to
823 * restrict anonymous, we only deny connections that have no session
824 * information. If a domain has been provided, then it's not a purely
825 * anonymous connection. AAB
827 if (!*user && !*smb_apasswd && !*domain) {
828 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
829 return(ERROR(ERRDOS,ERRnoaccess));
833 /* If no username is sent use the guest account */
835 pstrcpy(user,lp_guestaccount(-1));
836 /* If no user and no password then set guest flag. */
837 if( *smb_apasswd == 0)
844 * In share level security, only overwrite sesssetup_use if
845 * it's a non null-session share. Helps keep %U and %G
849 if((lp_security() != SEC_SHARE) || (*user && !guest))
850 pstrcpy(sesssetup_user,user);
852 reload_services(True);
855 * Save the username before mapping. We will use
856 * the original username sent to us for security=server
857 * and security=domain checking.
860 pstrcpy( orig_user, user);
863 * Pass the user through the NT -> unix user mapping
867 (void)map_username(user);
870 * Do any UNIX username case mangling.
872 (void)Get_Pwnam( user, True);
874 add_session_user(user);
877 * Check if the given username was the guest user with no password.
880 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
884 * Check with orig_user for security=server and
889 !check_server_security(orig_user, domain, user,
890 smb_apasswd, smb_apasslen,
891 smb_ntpasswd, smb_ntpasslen) &&
892 !check_domain_security(orig_user, domain, user,
893 smb_apasswd, smb_apasslen,
894 smb_ntpasswd, smb_ntpasslen) &&
895 !check_hosts_equiv(user)
900 * If we get here then the user wasn't guest and the remote
901 * authentication methods failed. Check the authentication
902 * methods on this local server.
904 * If an NT password was supplied try and validate with that
905 * first. This is superior as the passwords are mixed case
906 * 128 length unicode.
911 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
912 DEBUG(2,("NT Password did not match for user '%s' ! Defaulting to Lanman\n", user));
914 valid_nt_password = True;
917 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL))
919 if (lp_security() >= SEC_USER)
921 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
923 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
924 return bad_password_error(inbuf,outbuf);
927 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
929 if (Get_Pwnam(user,True))
931 DEBUG(1,("Rejecting user '%s': bad password\n", user));
932 return bad_password_error(inbuf,outbuf);
937 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
938 * Then always map to guest account - as done below.
942 if (*smb_apasswd || !Get_Pwnam(user,True))
943 pstrcpy(user,lp_guestaccount(-1));
944 DEBUG(3,("Registered username %s for guest access\n",user));
949 if (!Get_Pwnam(user,True)) {
950 DEBUG(3,("No such user %s - using guest account\n",user));
951 pstrcpy(user,lp_guestaccount(-1));
955 if (!strequal(user,lp_guestaccount(-1)) &&
956 lp_servicenumber(user) < 0)
958 int homes = lp_servicenumber(HOMES_NAME);
959 char *home = get_user_home_dir(user);
960 if (homes >= 0 && home)
961 lp_add_home(user,homes,home);
965 /* it's ok - setup a reply */
966 if (Protocol < PROTOCOL_NT1) {
967 set_message(outbuf,3,0,True);
970 set_message(outbuf,3,3,True);
972 pstrcpy(p,"Unix"); p = skip_string(p,1);
973 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
974 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
975 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
976 /* perhaps grab OS version here?? */
979 /* Set the correct uid in the outgoing and incoming packets
980 We will use this on future requests to determine which
981 user we should become.
984 struct passwd *pw = Get_Pwnam(user,False);
986 DEBUG(1,("Username %s is invalid on this system\n",user));
987 return bad_password_error(inbuf,outbuf);
994 SSVAL(outbuf,smb_vwv2,1);
996 /* register the name and uid as being validated, so further connections
997 to a uid can get through without a password, on the same VC */
998 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
1000 SSVAL(outbuf,smb_uid,sess_vuid);
1001 SSVAL(inbuf,smb_uid,sess_vuid);
1003 if (!done_sesssetup)
1004 max_send = MIN(max_send,smb_bufsize);
1006 DEBUG(6,("Client requested max send size of %d\n", max_send));
1008 done_sesssetup = True;
1010 return chain_reply(inbuf,outbuf,length,bufsize);
1014 /****************************************************************************
1016 ****************************************************************************/
1017 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1023 BOOL bad_path = False;
1026 pstrcpy(name,smb_buf(inbuf) + 1);
1027 unix_convert(name,conn,0,&bad_path,&st);
1029 mode = SVAL(inbuf,smb_vwv0);
1031 if (check_name(name,conn)) {
1033 ok = S_ISDIR(st.st_mode);
1035 ok = dos_directory_exist(name,NULL);
1040 /* We special case this - as when a Windows machine
1041 is parsing a path is steps through the components
1042 one at a time - if a component fails it expects
1043 ERRbadpath, not ERRbadfile.
1047 unix_ERR_class = ERRDOS;
1048 unix_ERR_code = ERRbadpath;
1052 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1053 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1054 (get_remote_arch() == RA_WINNT))
1056 unix_ERR_class = ERRDOS;
1057 unix_ERR_code = ERRbaddirectory;
1061 return(UNIXERROR(ERRDOS,ERRbadpath));
1064 outsize = set_message(outbuf,0,0,True);
1066 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1072 /****************************************************************************
1074 ****************************************************************************/
1075 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1079 SMB_STRUCT_STAT sbuf;
1084 BOOL bad_path = False;
1086 pstrcpy(fname,smb_buf(inbuf) + 1);
1088 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1089 under WfWg - weird! */
1092 mode = aHIDDEN | aDIR;
1093 if (!CAN_WRITE(conn)) mode |= aRONLY;
1100 unix_convert(fname,conn,0,&bad_path,&sbuf);
1101 if (check_name(fname,conn))
1103 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
1105 mode = dos_mode(conn,fname,&sbuf);
1106 size = sbuf.st_size;
1107 mtime = sbuf.st_mtime;
1113 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1119 if((errno == ENOENT) && bad_path)
1121 unix_ERR_class = ERRDOS;
1122 unix_ERR_code = ERRbadpath;
1125 return(UNIXERROR(ERRDOS,ERRbadfile));
1128 outsize = set_message(outbuf,10,0,True);
1130 SSVAL(outbuf,smb_vwv0,mode);
1131 if(lp_dos_filetime_resolution(SNUM(conn)) )
1132 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1134 put_dos_date3(outbuf,smb_vwv1,mtime);
1135 SIVAL(outbuf,smb_vwv3,(uint32)size);
1137 if (Protocol >= PROTOCOL_NT1) {
1138 char *p = strrchr(fname,'/');
1139 uint16 flg2 = SVAL(outbuf,smb_flg2);
1141 if (!is_8_3(fname, True))
1142 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1145 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1151 /****************************************************************************
1153 ****************************************************************************/
1154 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1162 BOOL bad_path = False;
1164 pstrcpy(fname,smb_buf(inbuf) + 1);
1165 unix_convert(fname,conn,0,&bad_path,&st);
1167 mode = SVAL(inbuf,smb_vwv0);
1168 mtime = make_unix_date3(inbuf+smb_vwv1);
1170 if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
1172 if (check_name(fname,conn))
1173 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1175 ok = set_filetime(conn,fname,mtime);
1179 if((errno == ENOENT) && bad_path)
1181 unix_ERR_class = ERRDOS;
1182 unix_ERR_code = ERRbadpath;
1185 return(UNIXERROR(ERRDOS,ERRnoaccess));
1188 outsize = set_message(outbuf,0,0,True);
1190 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1196 /****************************************************************************
1198 ****************************************************************************/
1199 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1202 SMB_BIG_UINT dfree,dsize,bsize;
1204 sys_disk_free(".",True,&bsize,&dfree,&dsize);
1206 outsize = set_message(outbuf,5,0,True);
1208 SSVAL(outbuf,smb_vwv0,dsize);
1209 SSVAL(outbuf,smb_vwv1,bsize/512);
1210 SSVAL(outbuf,smb_vwv2,512);
1211 SSVAL(outbuf,smb_vwv3,dfree);
1213 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1219 /****************************************************************************
1221 Can be called from SMBsearch, SMBffirst or SMBfunique.
1222 ****************************************************************************/
1223 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1234 BOOL finished = False;
1243 BOOL check_descend = False;
1244 BOOL expect_close = False;
1245 BOOL can_open = True;
1246 BOOL bad_path = False;
1248 *mask = *directory = *fname = 0;
1250 /* If we were called as SMBffirst then we must expect close. */
1251 if(CVAL(inbuf,smb_com) == SMBffirst)
1252 expect_close = True;
1254 outsize = set_message(outbuf,1,3,True);
1255 maxentries = SVAL(inbuf,smb_vwv0);
1256 dirtype = SVAL(inbuf,smb_vwv1);
1257 path = smb_buf(inbuf) + 1;
1258 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1261 /* dirtype &= ~aDIR; */
1263 DEBUG(5,("reply_search: path=%s status_len=%d\n",path,status_len));
1266 if (status_len == 0)
1270 pstrcpy(directory,smb_buf(inbuf)+1);
1271 pstrcpy(dir2,smb_buf(inbuf)+1);
1272 unix_convert(directory,conn,0,&bad_path,NULL);
1275 if (!check_name(directory,conn))
1278 p = strrchr(dir2,'/');
1290 p = strrchr(directory,'/');
1296 if (strlen(directory) == 0)
1297 pstrcpy(directory,"./");
1298 memset((char *)status,'\0',21);
1299 CVAL(status,0) = dirtype;
1303 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1304 memcpy(mask,status+1,11);
1306 dirtype = CVAL(status,0) & 0x1F;
1307 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1310 string_set(&conn->dirpath,dptr_path(dptr_num));
1311 if (!case_sensitive)
1315 /* turn strings of spaces into a . */
1317 trim_string(mask,NULL," ");
1318 if ((p = strrchr(mask,' ')))
1323 trim_string(mask,NULL," ");
1329 /* Convert the formatted mask. (This code lives in trans2.c) */
1337 if((skip = skip_multibyte_char( *p )) != 0 )
1343 if (*p != '?' && *p != '*' && !isdoschar(*p))
1345 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1353 if (!strchr(mask,'.') && strlen(mask)>8)
1356 fstrcpy(tmp,&mask[8]);
1362 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1366 p = smb_buf(outbuf) + 3;
1370 if (status_len == 0)
1372 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1377 if((errno == ENOENT) && bad_path)
1379 unix_ERR_class = ERRDOS;
1380 unix_ERR_code = ERRbadpath;
1382 return (UNIXERROR(ERRDOS,ERRnofids));
1384 return(ERROR(ERRDOS,ERRnofids));
1388 DEBUG(4,("dptr_num is %d\n",dptr_num));
1392 if ((dirtype&0x1F) == aVOLID)
1394 memcpy(p,status,21);
1395 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1396 dptr_fill(p+12,dptr_num);
1397 if (dptr_zero(p+12) && (status_len==0))
1401 p += DIR_STRUCT_SIZE;
1405 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1406 conn->dirpath,lp_dontdescend(SNUM(conn))));
1407 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1408 check_descend = True;
1410 for (i=numentries;(i<maxentries) && !finished;i++)
1413 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1416 memcpy(p,status,21);
1417 make_dir_struct(p,mask,fname,size,mode,date);
1418 dptr_fill(p+12,dptr_num);
1421 p += DIR_STRUCT_SIZE;
1430 if (numentries == 0 || !ok)
1432 CVAL(outbuf,smb_rcls) = ERRDOS;
1433 SSVAL(outbuf,smb_err,ERRnofiles);
1434 dptr_close(&dptr_num);
1437 /* If we were called as SMBffirst with smb_search_id == NULL
1438 and no entries were found then return error and close dirptr
1441 if(ok && expect_close && numentries == 0 && status_len == 0)
1443 CVAL(outbuf,smb_rcls) = ERRDOS;
1444 SSVAL(outbuf,smb_err,ERRnofiles);
1445 /* Also close the dptr - we know it's gone */
1446 dptr_close(&dptr_num);
1449 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1450 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1451 dptr_close(&dptr_num);
1453 SSVAL(outbuf,smb_vwv0,numentries);
1454 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1455 CVAL(smb_buf(outbuf),0) = 5;
1456 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1458 if (Protocol >= PROTOCOL_NT1) {
1459 uint16 flg2 = SVAL(outbuf,smb_flg2);
1460 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1463 outsize += DIR_STRUCT_SIZE*numentries;
1464 smb_setlen(outbuf,outsize - 4);
1466 if ((! *directory) && dptr_path(dptr_num))
1467 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1469 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1470 smb_fn_name(CVAL(inbuf,smb_com)),
1471 mask, directory, dirtype, numentries, maxentries ) );
1477 /****************************************************************************
1478 reply to a fclose (stop directory search)
1479 ****************************************************************************/
1480 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1488 outsize = set_message(outbuf,1,0,True);
1489 path = smb_buf(inbuf) + 1;
1490 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1493 if (status_len == 0)
1494 return(ERROR(ERRSRV,ERRsrverror));
1496 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1498 if(dptr_fetch(status+12,&dptr_num)) {
1499 /* Close the dptr - we know it's gone */
1500 dptr_close(&dptr_num);
1503 SSVAL(outbuf,smb_vwv0,0);
1505 DEBUG(3,("search close\n"));
1511 /****************************************************************************
1513 ****************************************************************************/
1515 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1525 SMB_STRUCT_STAT sbuf;
1526 BOOL bad_path = False;
1528 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1530 share_mode = SVAL(inbuf,smb_vwv0);
1532 pstrcpy(fname,smb_buf(inbuf)+1);
1533 unix_convert(fname,conn,0,&bad_path,NULL);
1537 return(ERROR(ERRSRV,ERRnofids));
1539 if (!check_name(fname,conn))
1541 if((errno == ENOENT) && bad_path)
1543 unix_ERR_class = ERRDOS;
1544 unix_ERR_code = ERRbadpath;
1547 return(UNIXERROR(ERRDOS,ERRnoaccess));
1550 unixmode = unix_mode(conn,aARCH);
1552 open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1553 unixmode, oplock_request,&rmode,NULL);
1557 if((errno == ENOENT) && bad_path)
1559 unix_ERR_class = ERRDOS;
1560 unix_ERR_code = ERRbadpath;
1563 return(UNIXERROR(ERRDOS,ERRnoaccess));
1566 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1567 close_file(fsp,False);
1568 return(ERROR(ERRDOS,ERRnoaccess));
1571 size = sbuf.st_size;
1572 fmode = dos_mode(conn,fname,&sbuf);
1573 mtime = sbuf.st_mtime;
1576 DEBUG(3,("attempt to open a directory %s\n",fname));
1577 close_file(fsp,False);
1578 return(ERROR(ERRDOS,ERRnoaccess));
1581 outsize = set_message(outbuf,7,0,True);
1582 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1583 SSVAL(outbuf,smb_vwv1,fmode);
1584 if(lp_dos_filetime_resolution(SNUM(conn)) )
1585 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1587 put_dos_date3(outbuf,smb_vwv2,mtime);
1588 SIVAL(outbuf,smb_vwv4,(uint32)size);
1589 SSVAL(outbuf,smb_vwv6,rmode);
1591 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1592 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1595 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1596 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1601 /****************************************************************************
1602 reply to an open and X
1603 ****************************************************************************/
1604 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1607 int smb_mode = SVAL(inbuf,smb_vwv3);
1608 int smb_attr = SVAL(inbuf,smb_vwv5);
1609 /* Breakout the oplock request bits so we can set the
1610 reply bits separately. */
1611 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1612 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1613 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1615 int open_flags = SVAL(inbuf,smb_vwv2);
1616 int smb_sattr = SVAL(inbuf,smb_vwv4);
1617 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1619 int smb_ofun = SVAL(inbuf,smb_vwv8);
1622 int fmode=0,mtime=0,rmode=0;
1623 SMB_STRUCT_STAT sbuf;
1625 BOOL bad_path = False;
1628 /* If it's an IPC, pass off the pipe handler. */
1629 if (IS_IPC(conn) && lp_nt_pipe_support())
1630 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1632 /* XXXX we need to handle passed times, sattr and flags */
1634 pstrcpy(fname,smb_buf(inbuf));
1635 unix_convert(fname,conn,0,&bad_path,NULL);
1639 return(ERROR(ERRSRV,ERRnofids));
1641 if (!check_name(fname,conn))
1643 if((errno == ENOENT) && bad_path)
1645 unix_ERR_class = ERRDOS;
1646 unix_ERR_code = ERRbadpath;
1649 return(UNIXERROR(ERRDOS,ERRnoaccess));
1652 unixmode = unix_mode(conn,smb_attr | aARCH);
1654 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1655 oplock_request, &rmode,&smb_action);
1659 if((errno == ENOENT) && bad_path)
1661 unix_ERR_class = ERRDOS;
1662 unix_ERR_code = ERRbadpath;
1665 return(UNIXERROR(ERRDOS,ERRnoaccess));
1668 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1669 close_file(fsp,False);
1670 return(ERROR(ERRDOS,ERRnoaccess));
1673 size = sbuf.st_size;
1674 fmode = dos_mode(conn,fname,&sbuf);
1675 mtime = sbuf.st_mtime;
1677 close_file(fsp,False);
1678 return(ERROR(ERRDOS,ERRnoaccess));
1681 /* If the caller set the extended oplock request bit
1682 and we granted one (by whatever means) - set the
1683 correct bit for extended oplock reply.
1686 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1687 smb_action |= EXTENDED_OPLOCK_GRANTED;
1690 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1691 smb_action |= EXTENDED_OPLOCK_GRANTED;
1694 /* If the caller set the core oplock request bit
1695 and we granted one (by whatever means) - set the
1696 correct bit for core oplock reply.
1699 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1700 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1703 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1704 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1707 set_message(outbuf,15,0,True);
1708 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1709 SSVAL(outbuf,smb_vwv3,fmode);
1710 if(lp_dos_filetime_resolution(SNUM(conn)) )
1711 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1713 put_dos_date3(outbuf,smb_vwv4,mtime);
1714 SIVAL(outbuf,smb_vwv6,(uint32)size);
1715 SSVAL(outbuf,smb_vwv8,rmode);
1716 SSVAL(outbuf,smb_vwv11,smb_action);
1718 return chain_reply(inbuf,outbuf,length,bufsize);
1722 /****************************************************************************
1723 reply to a SMBulogoffX
1724 ****************************************************************************/
1725 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1727 uint16 vuid = SVAL(inbuf,smb_uid);
1728 user_struct *vuser = get_valid_user_struct(vuid);
1731 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1734 /* in user level security we are supposed to close any files
1735 open by this user */
1736 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1737 file_close_user(vuid);
1740 invalidate_vuid(vuid);
1742 set_message(outbuf,2,0,True);
1744 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1746 return chain_reply(inbuf,outbuf,length,bufsize);
1750 /****************************************************************************
1751 reply to a mknew or a create
1752 ****************************************************************************/
1753 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1761 BOOL bad_path = False;
1763 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1765 com = SVAL(inbuf,smb_com);
1767 createmode = SVAL(inbuf,smb_vwv0);
1768 pstrcpy(fname,smb_buf(inbuf)+1);
1769 unix_convert(fname,conn,0,&bad_path,NULL);
1771 if (createmode & aVOLID)
1773 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1776 unixmode = unix_mode(conn,createmode);
1780 return(ERROR(ERRSRV,ERRnofids));
1782 if (!check_name(fname,conn))
1784 if((errno == ENOENT) && bad_path)
1786 unix_ERR_class = ERRDOS;
1787 unix_ERR_code = ERRbadpath;
1790 return(UNIXERROR(ERRDOS,ERRnoaccess));
1795 /* We should fail if file exists. */
1796 ofun = FILE_CREATE_IF_NOT_EXIST;
1800 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1801 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1804 /* Open file in dos compatibility share mode. */
1805 open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1806 ofun, unixmode, oplock_request, NULL, NULL);
1810 if((errno == ENOENT) && bad_path)
1812 unix_ERR_class = ERRDOS;
1813 unix_ERR_code = ERRbadpath;
1816 return(UNIXERROR(ERRDOS,ERRnoaccess));
1819 outsize = set_message(outbuf,1,0,True);
1820 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1822 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1823 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1826 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1827 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1829 DEBUG( 2, ( "new file %s\n", fname ) );
1830 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1831 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1837 /****************************************************************************
1838 reply to a create temporary file
1839 ****************************************************************************/
1840 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1847 BOOL bad_path = False;
1849 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1851 createmode = SVAL(inbuf,smb_vwv0);
1852 pstrcpy(fname,smb_buf(inbuf)+1);
1853 pstrcat(fname,"/TMXXXXXX");
1854 unix_convert(fname,conn,0,&bad_path,NULL);
1856 unixmode = unix_mode(conn,createmode);
1860 return(ERROR(ERRSRV,ERRnofids));
1862 if (!check_name(fname,conn))
1864 if((errno == ENOENT) && bad_path)
1866 unix_ERR_class = ERRDOS;
1867 unix_ERR_code = ERRbadpath;
1870 return(UNIXERROR(ERRDOS,ERRnoaccess));
1873 pstrcpy(fname2,(char *)smbd_mktemp(fname));
1875 /* Open file in dos compatibility share mode. */
1876 /* We should fail if file exists. */
1877 open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1878 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1882 if((errno == ENOENT) && bad_path)
1884 unix_ERR_class = ERRDOS;
1885 unix_ERR_code = ERRbadpath;
1888 return(UNIXERROR(ERRDOS,ERRnoaccess));
1891 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1892 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1893 CVAL(smb_buf(outbuf),0) = 4;
1894 pstrcpy(smb_buf(outbuf) + 1,fname2);
1896 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1897 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1900 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1901 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1903 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1904 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1905 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1911 /*******************************************************************
1912 check if a user is allowed to delete a file
1913 ********************************************************************/
1914 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1916 SMB_STRUCT_STAT sbuf;
1919 if (!CAN_WRITE(conn)) return(False);
1921 if (dos_lstat(fname,&sbuf) != 0) return(False);
1922 fmode = dos_mode(conn,fname,&sbuf);
1923 if (fmode & aDIR) return(False);
1924 if (!lp_delete_readonly(SNUM(conn))) {
1925 if (fmode & aRONLY) return(False);
1927 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1929 if (!check_file_sharing(conn,fname,False)) return(False);
1933 /****************************************************************************
1935 ****************************************************************************/
1937 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1946 int error = ERRnoaccess;
1949 BOOL bad_path = False;
1952 *directory = *mask = 0;
1954 dirtype = SVAL(inbuf,smb_vwv0);
1956 pstrcpy(name,smb_buf(inbuf) + 1);
1958 DEBUG(3,("reply_unlink : %s\n",name));
1960 rc = unix_convert(name,conn,0,&bad_path,NULL);
1962 p = strrchr(name,'/');
1964 pstrcpy(directory,"./");
1968 pstrcpy(directory,name);
1973 * We should only check the mangled cache
1974 * here if unix_convert failed. This means
1975 * that the path in 'mask' doesn't exist
1976 * on the file system and so we need to look
1977 * for a possible mangle. This patch from
1978 * Tine Smukavec <valentin.smukavec@hermes.si>.
1981 if (!rc && is_mangled(mask))
1982 check_mangled_cache( mask );
1984 has_wild = strchr(mask,'*') || strchr(mask,'?');
1987 pstrcat(directory,"/");
1988 pstrcat(directory,mask);
1989 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
1992 exists = dos_file_exist(directory,NULL);
1994 void *dirptr = NULL;
1997 if (check_name(directory,conn))
1998 dirptr = OpenDir(conn, directory, True);
2000 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2001 the pattern matches against the long name, otherwise the short name
2002 We don't implement this yet XXXX
2009 if (strequal(mask,"????????.???"))
2012 while ((dname = ReadDirName(dirptr)))
2015 pstrcpy(fname,dname);
2017 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2019 error = ERRnoaccess;
2020 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2021 if (!can_delete(fname,conn,dirtype)) continue;
2022 if (!dos_unlink(fname)) count++;
2023 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
2031 return(ERROR(ERRDOS,error));
2034 if((errno == ENOENT) && bad_path)
2036 unix_ERR_class = ERRDOS;
2037 unix_ERR_code = ERRbadpath;
2039 return(UNIXERROR(ERRDOS,error));
2043 outsize = set_message(outbuf,0,0,True);
2049 /****************************************************************************
2050 reply to a readbraw (core+ protocol)
2051 ****************************************************************************/
2053 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2055 size_t maxcount,mincount;
2058 char *header = outbuf;
2063 * Special check if an oplock break has been issued
2064 * and the readraw request croses on the wire, we must
2065 * return a zero length response here.
2068 if(global_oplock_break)
2070 _smb_setlen(header,0);
2071 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
2072 DEBUG(5,("readbraw - oplock break finished\n"));
2076 fsp = file_fsp(inbuf,smb_vwv0);
2078 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2080 * fsp could be NULL here so use the value from the packet. JRA.
2082 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2083 _smb_setlen(header,0);
2084 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
2088 CHECK_FSP(fsp,conn);
2090 flush_write_cache(fsp, READRAW_FLUSH);
2092 startpos = IVAL(inbuf,smb_vwv1);
2093 if(CVAL(inbuf,smb_wct) == 10) {
2095 * This is a large offset (64 bit) read.
2097 #ifdef LARGE_SMB_OFF_T
2099 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2101 #else /* !LARGE_SMB_OFF_T */
2104 * Ensure we haven't been sent a >32 bit offset.
2107 if(IVAL(inbuf,smb_vwv8) != 0) {
2108 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2109 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2110 _smb_setlen(header,0);
2111 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
2115 #endif /* LARGE_SMB_OFF_T */
2118 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2119 (double)startpos ));
2120 _smb_setlen(header,0);
2121 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
2125 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2126 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2128 /* ensure we don't overrun the packet size */
2129 maxcount = MIN(65535,maxcount);
2130 maxcount = MAX(mincount,maxcount);
2132 if (!is_locked(fsp,conn,maxcount,startpos, READ_LOCK))
2134 SMB_OFF_T size = fsp->size;
2135 SMB_OFF_T sizeneeded = startpos + maxcount;
2137 if (size < sizeneeded)
2140 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
2142 if (!fsp->can_write)
2146 nread = MIN(maxcount,(size - startpos));
2149 if (nread < mincount)
2152 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2153 fsp->fnum, (double)startpos,
2154 (int)maxcount, (int)mincount, (int)nread ) );
2158 BOOL seek_fail = False;
2160 _smb_setlen(header,nread);
2162 #if USE_READ_PREDICTION
2163 if (!fsp->can_write)
2164 predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
2165 #endif /* USE_READ_PREDICTION */
2167 if ((nread-predict) > 0) {
2168 if(seek_file(fsp,startpos + predict) == -1) {
2169 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2176 ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,
2177 (SMB_OFF_T)(nread-predict),header,4+predict,
2182 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2183 fsp->fsp_name,startpos,nread,ret));
2185 #else /* UNSAFE_READRAW */
2186 ret = read_file(fsp,header+4,startpos,nread);
2187 if (ret < mincount) ret = 0;
2189 _smb_setlen(header,ret);
2190 transfer_file(0,Client,0,header,4+ret,0);
2191 #endif /* UNSAFE_READRAW */
2193 DEBUG(5,("readbraw finished\n"));
2198 /****************************************************************************
2199 reply to a lockread (core+ protocol)
2200 ****************************************************************************/
2201 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2210 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2212 CHECK_FSP(fsp,conn);
2216 numtoread = SVAL(inbuf,smb_vwv1);
2217 startpos = IVAL(inbuf,smb_vwv2);
2219 outsize = set_message(outbuf,5,3,True);
2220 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2221 data = smb_buf(outbuf) + 3;
2224 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2225 * protocol request that predates the read/write lock concept.
2226 * Thus instead of asking for a read lock here we need to ask
2227 * for a write lock. JRA.
2230 if(!do_lock( fsp, conn, numtoread, startpos, WRITE_LOCK, &eclass, &ecode)) {
2231 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2233 * A blocking lock was requested. Package up
2234 * this smb into a queued request and push it
2235 * onto the blocking lock queue.
2237 if(push_blocking_lock_request(inbuf, length, -1, 0))
2240 return (ERROR(eclass,ecode));
2243 nread = read_file(fsp,data,startpos,numtoread);
2246 return(UNIXERROR(ERRDOS,ERRnoaccess));
2249 SSVAL(outbuf,smb_vwv0,nread);
2250 SSVAL(outbuf,smb_vwv5,nread+3);
2251 SSVAL(smb_buf(outbuf),1,nread);
2253 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2254 fsp->fnum, (int)numtoread, (int)nread ) );
2260 /****************************************************************************
2262 ****************************************************************************/
2264 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2271 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2273 CHECK_FSP(fsp,conn);
2277 numtoread = SVAL(inbuf,smb_vwv1);
2278 startpos = IVAL(inbuf,smb_vwv2);
2280 outsize = set_message(outbuf,5,3,True);
2281 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2282 data = smb_buf(outbuf) + 3;
2284 if (is_locked(fsp,conn,numtoread,startpos, READ_LOCK))
2285 return(ERROR(ERRDOS,ERRlock));
2288 nread = read_file(fsp,data,startpos,numtoread);
2291 return(UNIXERROR(ERRDOS,ERRnoaccess));
2294 SSVAL(outbuf,smb_vwv0,nread);
2295 SSVAL(outbuf,smb_vwv5,nread+3);
2296 CVAL(smb_buf(outbuf),0) = 1;
2297 SSVAL(smb_buf(outbuf),1,nread);
2299 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2300 fsp->fnum, (int)numtoread, (int)nread ) );
2306 /****************************************************************************
2307 reply to a read and X
2308 ****************************************************************************/
2309 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2311 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2312 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2313 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2314 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2318 /* If it's an IPC, pass off the pipe handler. */
2320 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2322 CHECK_FSP(fsp,conn);
2326 set_message(outbuf,12,0,True);
2327 data = smb_buf(outbuf);
2329 if(CVAL(inbuf,smb_wct) == 12) {
2330 #ifdef LARGE_SMB_OFF_T
2332 * This is a large offset (64 bit) read.
2334 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2336 #else /* !LARGE_SMB_OFF_T */
2339 * Ensure we haven't been sent a >32 bit offset.
2342 if(IVAL(inbuf,smb_vwv10) != 0) {
2343 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2344 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2345 return(ERROR(ERRDOS,ERRbadaccess));
2348 #endif /* LARGE_SMB_OFF_T */
2352 if (is_locked(fsp,conn,smb_maxcnt,startpos, READ_LOCK))
2353 return(ERROR(ERRDOS,ERRlock));
2354 nread = read_file(fsp,data,startpos,smb_maxcnt);
2357 return(UNIXERROR(ERRDOS,ERRnoaccess));
2359 SSVAL(outbuf,smb_vwv5,nread);
2360 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2361 SSVAL(smb_buf(outbuf),-2,nread);
2363 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2364 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2366 return chain_reply(inbuf,outbuf,length,bufsize);
2369 /****************************************************************************
2370 reply to a writebraw (core+ or LANMAN1.0 protocol)
2371 ****************************************************************************/
2373 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2376 ssize_t total_written=0;
2377 size_t numtowrite=0;
2382 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2385 CHECK_FSP(fsp,conn);
2389 tcount = IVAL(inbuf,smb_vwv1);
2390 startpos = IVAL(inbuf,smb_vwv3);
2391 write_through = BITSETW(inbuf+smb_vwv7,0);
2393 /* We have to deal with slightly different formats depending
2394 on whether we are using the core+ or lanman1.0 protocol */
2395 if(Protocol <= PROTOCOL_COREPLUS) {
2396 numtowrite = SVAL(smb_buf(inbuf),-2);
2397 data = smb_buf(inbuf);
2399 numtowrite = SVAL(inbuf,smb_vwv10);
2400 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2403 /* force the error type */
2404 CVAL(inbuf,smb_com) = SMBwritec;
2405 CVAL(outbuf,smb_com) = SMBwritec;
2407 if (is_locked(fsp,conn,tcount,startpos, WRITE_LOCK))
2408 return(ERROR(ERRDOS,ERRlock));
2411 nwritten = write_file(fsp,data,startpos,numtowrite);
2413 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2414 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2416 if (nwritten < numtowrite)
2417 return(UNIXERROR(ERRHRD,ERRdiskfull));
2419 total_written = nwritten;
2421 /* Return a message to the redirector to tell it
2422 to send more bytes */
2423 CVAL(outbuf,smb_com) = SMBwritebraw;
2424 SSVALS(outbuf,smb_vwv0,-1);
2425 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2426 send_smb(Client,outbuf);
2428 /* Now read the raw data into the buffer and write it */
2429 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2430 exit_server("secondary writebraw failed");
2433 /* Even though this is not an smb message, smb_len
2434 returns the generic length of an smb message */
2435 numtowrite = smb_len(inbuf);
2437 if (tcount > nwritten+numtowrite) {
2438 DEBUG(3,("Client overestimated the write %d %d %d\n",
2439 (int)tcount,(int)nwritten,(int)numtowrite));
2442 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2444 total_written += nwritten;
2446 /* Set up outbuf to return the correct return */
2447 outsize = set_message(outbuf,1,0,True);
2448 CVAL(outbuf,smb_com) = SMBwritec;
2449 SSVAL(outbuf,smb_vwv0,total_written);
2451 if (nwritten < (ssize_t)numtowrite) {
2452 CVAL(outbuf,smb_rcls) = ERRHRD;
2453 SSVAL(outbuf,smb_err,ERRdiskfull);
2456 if (lp_syncalways(SNUM(conn)) || write_through)
2457 sync_file(conn,fsp);
2459 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2460 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2462 /* we won't return a status if write through is not selected - this
2463 follows what WfWg does */
2464 if (!write_through && total_written==tcount)
2470 /****************************************************************************
2471 reply to a writeunlock (core+)
2472 ****************************************************************************/
2474 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2476 ssize_t nwritten = -1;
2482 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2485 CHECK_FSP(fsp,conn);
2489 numtowrite = SVAL(inbuf,smb_vwv1);
2490 startpos = IVAL(inbuf,smb_vwv2);
2491 data = smb_buf(inbuf) + 3;
2493 if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK))
2494 return(ERROR(ERRDOS,ERRlock));
2496 /* The special X/Open SMB protocol handling of
2497 zero length writes is *NOT* done for
2502 nwritten = write_file(fsp,data,startpos,numtowrite);
2504 if (lp_syncalways(SNUM(conn)))
2505 sync_file(conn,fsp);
2507 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2508 return(UNIXERROR(ERRDOS,ERRnoaccess));
2510 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2511 return(ERROR(eclass,ecode));
2513 outsize = set_message(outbuf,1,0,True);
2515 SSVAL(outbuf,smb_vwv0,nwritten);
2517 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2518 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2523 /****************************************************************************
2525 ****************************************************************************/
2526 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2529 ssize_t nwritten = -1;
2532 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2535 /* If it's an IPC, pass off the pipe handler. */
2537 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2539 CHECK_FSP(fsp,conn);
2543 numtowrite = SVAL(inbuf,smb_vwv1);
2544 startpos = IVAL(inbuf,smb_vwv2);
2545 data = smb_buf(inbuf) + 3;
2547 if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK))
2548 return(ERROR(ERRDOS,ERRlock));
2550 /* X/Open SMB protocol says that if smb_vwv1 is
2551 zero then the file size should be extended or
2552 truncated to the size given in smb_vwv[2-3] */
2553 if(numtowrite == 0) {
2554 if((nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos)) >= 0)
2555 set_filelen_write_cache(fsp, startpos);
2557 nwritten = write_file(fsp,data,startpos,numtowrite);
2559 if (lp_syncalways(SNUM(conn)))
2560 sync_file(conn,fsp);
2562 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2563 return(UNIXERROR(ERRDOS,ERRnoaccess));
2565 outsize = set_message(outbuf,1,0,True);
2567 SSVAL(outbuf,smb_vwv0,nwritten);
2569 if (nwritten < (ssize_t)numtowrite) {
2570 CVAL(outbuf,smb_rcls) = ERRHRD;
2571 SSVAL(outbuf,smb_err,ERRdiskfull);
2574 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2575 fsp->fnum, (int)numtowrite, (int)nwritten));
2581 /****************************************************************************
2582 reply to a write and X
2583 ****************************************************************************/
2584 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2586 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2587 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2588 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2589 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2590 ssize_t nwritten = -1;
2591 int smb_doff = SVAL(inbuf,smb_vwv11);
2594 /* If it's an IPC, pass off the pipe handler. */
2596 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2598 CHECK_FSP(fsp,conn);
2602 data = smb_base(inbuf) + smb_doff;
2604 if(CVAL(inbuf,smb_wct) == 14) {
2605 #ifdef LARGE_SMB_OFF_T
2607 * This is a large offset (64 bit) write.
2609 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2611 #else /* !LARGE_SMB_OFF_T */
2614 * Ensure we haven't been sent a >32 bit offset.
2617 if(IVAL(inbuf,smb_vwv12) != 0) {
2618 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2619 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2620 return(ERROR(ERRDOS,ERRbadaccess));
2623 #endif /* LARGE_SMB_OFF_T */
2626 if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK))
2627 return(ERROR(ERRDOS,ERRlock));
2629 /* X/Open SMB protocol says that, unlike SMBwrite
2630 if the length is zero then NO truncation is
2631 done, just a write of zero. To truncate a file,
2636 nwritten = write_file(fsp,data,startpos,numtowrite);
2638 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2639 return(UNIXERROR(ERRDOS,ERRnoaccess));
2641 set_message(outbuf,6,0,True);
2643 SSVAL(outbuf,smb_vwv2,nwritten);
2645 if (nwritten < (ssize_t)numtowrite) {
2646 CVAL(outbuf,smb_rcls) = ERRHRD;
2647 SSVAL(outbuf,smb_err,ERRdiskfull);
2650 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2651 fsp->fnum, (int)numtowrite, (int)nwritten));
2653 if (lp_syncalways(SNUM(conn)) || write_through)
2654 sync_file(conn,fsp);
2656 return chain_reply(inbuf,outbuf,length,bufsize);
2660 /****************************************************************************
2662 ****************************************************************************/
2664 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2670 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2672 CHECK_FSP(fsp,conn);
2675 flush_write_cache(fsp, SEEK_FLUSH);
2677 mode = SVAL(inbuf,smb_vwv1) & 3;
2678 startpos = IVALS(inbuf,smb_vwv2);
2681 case 0: umode = SEEK_SET; break;
2682 case 1: umode = SEEK_CUR; break;
2683 case 2: umode = SEEK_END; break;
2685 umode = SEEK_SET; break;
2688 if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1) {
2690 * Check for the special case where a seek before the start
2691 * of the file sets the offset to zero. Added in the CIFS spec,
2695 if(errno == EINVAL) {
2696 SMB_OFF_T current_pos = startpos;
2698 if(umode == SEEK_CUR) {
2700 if((current_pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1)
2701 return(UNIXERROR(ERRDOS,ERRnoaccess));
2703 current_pos += startpos;
2705 } else if (umode == SEEK_END) {
2707 SMB_STRUCT_STAT sbuf;
2709 if(sys_fstat( fsp->fd_ptr->fd, &sbuf) == -1)
2710 return(UNIXERROR(ERRDOS,ERRnoaccess));
2712 current_pos += sbuf.st_size;
2716 res = sys_lseek(fsp->fd_ptr->fd,0,SEEK_SET);
2720 return(UNIXERROR(ERRDOS,ERRnoaccess));
2725 outsize = set_message(outbuf,2,0,True);
2726 SIVAL(outbuf,smb_vwv0,res);
2728 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2729 fsp->fnum, (double)startpos, (double)res, mode));
2734 /****************************************************************************
2736 ****************************************************************************/
2738 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2740 int outsize = set_message(outbuf,0,0,True);
2741 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2744 CHECK_FSP(fsp,conn);
2749 file_sync_all(conn);
2751 sync_file(conn,fsp);
2754 DEBUG(3,("flush\n"));
2759 /****************************************************************************
2761 ****************************************************************************/
2762 int reply_exit(connection_struct *conn,
2763 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2765 int outsize = set_message(outbuf,0,0,True);
2766 DEBUG(3,("exit\n"));
2772 /****************************************************************************
2773 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2774 ****************************************************************************/
2775 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2780 int32 eclass = 0, err = 0;
2781 files_struct *fsp = NULL;
2783 outsize = set_message(outbuf,0,0,True);
2785 /* If it's an IPC, pass off to the pipe handler. */
2787 return reply_pipe_close(conn, inbuf,outbuf);
2789 fsp = file_fsp(inbuf,smb_vwv0);
2792 * We can only use CHECK_FSP if we know it's not a directory.
2795 if(!fsp || !fsp->open || (fsp->conn != conn))
2796 return(ERROR(ERRDOS,ERRbadfid));
2798 if(HAS_CACHED_ERROR(fsp)) {
2799 eclass = fsp->wbmpx_ptr->wr_errclass;
2800 err = fsp->wbmpx_ptr->wr_error;
2803 if(fsp->is_directory || fsp->stat_open) {
2805 * Special case - close NT SMB directory or stat file
2808 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2809 close_file(fsp,True);
2812 * Close ordinary file.
2817 * If there was a modify time outstanding,
2818 * try and set it here.
2820 if(fsp->pending_modtime)
2821 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2824 * Now take care of any time sent in the close.
2826 mtime = make_unix_date3(inbuf+smb_vwv1);
2828 /* try and set the date */
2829 set_filetime(conn, fsp->fsp_name,mtime);
2831 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2832 fsp->fd_ptr ? fsp->fd_ptr->fd : -1, fsp->fnum,
2833 conn->num_files_open));
2836 * close_file() returns the unix errno if an error
2837 * was detected on close - normally this is due to
2838 * a disk full error. If not then it was probably an I/O error.
2841 if((close_err = close_file(fsp,True)) != 0) {
2843 return (UNIXERROR(ERRHRD,ERRgeneral));
2847 /* We have a cached error */
2849 return(ERROR(eclass,err));
2855 /****************************************************************************
2856 reply to a writeclose (Core+ protocol)
2857 ****************************************************************************/
2859 int reply_writeclose(connection_struct *conn,
2860 char *inbuf,char *outbuf, int size, int dum_buffsize)
2863 ssize_t nwritten = -1;
2869 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2871 CHECK_FSP(fsp,conn);
2875 numtowrite = SVAL(inbuf,smb_vwv1);
2876 startpos = IVAL(inbuf,smb_vwv2);
2877 mtime = make_unix_date3(inbuf+smb_vwv4);
2878 data = smb_buf(inbuf) + 1;
2880 if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK))
2881 return(ERROR(ERRDOS,ERRlock));
2883 nwritten = write_file(fsp,data,startpos,numtowrite);
2885 set_filetime(conn, fsp->fsp_name,mtime);
2887 close_err = close_file(fsp,True);
2889 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2890 fsp->fnum, (int)numtowrite, (int)nwritten,
2891 conn->num_files_open));
2894 return(UNIXERROR(ERRDOS,ERRnoaccess));
2896 if(close_err != 0) {
2898 return(UNIXERROR(ERRHRD,ERRgeneral));
2901 outsize = set_message(outbuf,1,0,True);
2903 SSVAL(outbuf,smb_vwv0,nwritten);
2908 /****************************************************************************
2910 ****************************************************************************/
2911 int reply_lock(connection_struct *conn,
2912 char *inbuf,char *outbuf, int length, int dum_buffsize)
2914 int outsize = set_message(outbuf,0,0,True);
2915 SMB_OFF_T count,offset;
2918 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2920 CHECK_FSP(fsp,conn);
2923 count = IVAL(inbuf,smb_vwv1);
2924 offset = IVAL(inbuf,smb_vwv3);
2926 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2927 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2929 if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) {
2930 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2932 * A blocking lock was requested. Package up
2933 * this smb into a queued request and push it
2934 * onto the blocking lock queue.
2936 if(push_blocking_lock_request(inbuf, length, -1, 0))
2939 return (ERROR(eclass,ecode));
2946 /****************************************************************************
2948 ****************************************************************************/
2949 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2951 int outsize = set_message(outbuf,0,0,True);
2952 SMB_OFF_T count,offset;
2955 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2957 CHECK_FSP(fsp,conn);
2960 count = IVAL(inbuf,smb_vwv1);
2961 offset = IVAL(inbuf,smb_vwv3);
2963 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2964 return (ERROR(eclass,ecode));
2966 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2967 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2973 /****************************************************************************
2975 ****************************************************************************/
2976 int reply_tdis(connection_struct *conn,
2977 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2979 int outsize = set_message(outbuf,0,0,True);
2982 vuid = SVAL(inbuf,smb_uid);
2985 DEBUG(4,("Invalid connection in tdis\n"));
2986 return(ERROR(ERRSRV,ERRinvnid));
2991 close_cnum(conn,vuid);
2998 /****************************************************************************
3000 ****************************************************************************/
3001 int reply_echo(connection_struct *conn,
3002 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3004 int smb_reverb = SVAL(inbuf,smb_vwv0);
3006 int data_len = smb_buflen(inbuf);
3007 int outsize = set_message(outbuf,1,data_len,True);
3009 /* copy any incoming data back out */
3011 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3013 if (smb_reverb > 100) {
3014 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3018 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3019 SSVAL(outbuf,smb_vwv0,seq_num);
3021 smb_setlen(outbuf,outsize - 4);
3023 send_smb(Client,outbuf);
3026 DEBUG(3,("echo %d times\n", smb_reverb));
3034 /****************************************************************************
3035 reply to a printopen
3036 ****************************************************************************/
3037 int reply_printopen(connection_struct *conn,
3038 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3045 *fname = *fname2 = 0;
3047 if (!CAN_PRINT(conn))
3048 return(ERROR(ERRDOS,ERRnoaccess));
3053 pstrcpy(s,smb_buf(inbuf)+1);
3056 if (!(isalnum((int)*p) || strchr("._-",*p)))
3061 if (strlen(s) > 10) s[10] = 0;
3063 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
3068 return(ERROR(ERRSRV,ERRnofids));
3070 pstrcpy(fname2,(char *)smbd_mktemp(fname));
3072 if (!check_name(fname2,conn)) {
3074 return(ERROR(ERRDOS,ERRnoaccess));
3077 /* Open for exclusive use, write only. */
3078 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3079 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
3083 return(UNIXERROR(ERRDOS,ERRnoaccess));
3086 /* force it to be a print file */
3087 fsp->print_file = True;
3089 outsize = set_message(outbuf,1,0,True);
3090 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3092 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
3093 fname2, fsp->fd_ptr->fd, fsp->fnum));
3099 /****************************************************************************
3100 reply to a printclose
3101 ****************************************************************************/
3102 int reply_printclose(connection_struct *conn,
3103 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3105 int outsize = set_message(outbuf,0,0,True);
3106 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3109 CHECK_FSP(fsp,conn);
3112 if (!CAN_PRINT(conn))
3113 return(ERROR(ERRDOS,ERRnoaccess));
3115 DEBUG(3,("printclose fd=%d fnum=%d\n",
3116 fsp->fd_ptr->fd,fsp->fnum));
3118 close_err = close_file(fsp,True);
3120 if(close_err != 0) {
3122 return(UNIXERROR(ERRHRD,ERRgeneral));
3129 /****************************************************************************
3130 reply to a printqueue
3131 ****************************************************************************/
3132 int reply_printqueue(connection_struct *conn,
3133 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3135 int outsize = set_message(outbuf,2,3,True);
3136 int max_count = SVAL(inbuf,smb_vwv0);
3137 int start_index = SVAL(inbuf,smb_vwv1);
3139 /* we used to allow the client to get the cnum wrong, but that
3140 is really quite gross and only worked when there was only
3141 one printer - I think we should now only accept it if they
3142 get it right (tridge) */
3143 if (!CAN_PRINT(conn))
3144 return(ERROR(ERRDOS,ERRnoaccess));
3146 SSVAL(outbuf,smb_vwv0,0);
3147 SSVAL(outbuf,smb_vwv1,0);
3148 CVAL(smb_buf(outbuf),0) = 1;
3149 SSVAL(smb_buf(outbuf),1,0);
3151 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3152 start_index, max_count));
3155 print_queue_struct *queue = NULL;
3156 char *p = smb_buf(outbuf) + 3;
3157 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
3158 int num_to_get = ABS(max_count);
3159 int first = (max_count>0?start_index:start_index+max_count+1);
3165 num_to_get = MIN(num_to_get,count-first);
3168 for (i=first;i<first+num_to_get;i++) {
3169 put_dos_date2(p,0,queue[i].time);
3170 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3171 SSVAL(p,5,printjob_encode(SNUM(conn),
3173 SIVAL(p,7,queue[i].size);
3175 StrnCpy(p+12,queue[i].user,16);
3180 outsize = set_message(outbuf,2,28*count+3,False);
3181 SSVAL(outbuf,smb_vwv0,count);
3182 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3183 CVAL(smb_buf(outbuf),0) = 1;
3184 SSVAL(smb_buf(outbuf),1,28*count);
3187 if (queue) free(queue);
3189 DEBUG(3,("%d entries returned in queue\n",count));
3196 /****************************************************************************
3197 reply to a printwrite
3198 ****************************************************************************/
3199 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3202 int outsize = set_message(outbuf,0,0,True);
3204 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3206 if (!CAN_PRINT(conn))
3207 return(ERROR(ERRDOS,ERRnoaccess));
3209 CHECK_FSP(fsp,conn);
3213 numtowrite = SVAL(smb_buf(inbuf),1);
3214 data = smb_buf(inbuf) + 3;
3216 if (write_file(fsp,data,-1,numtowrite) != numtowrite)
3217 return(UNIXERROR(ERRDOS,ERRnoaccess));
3219 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3225 /****************************************************************************
3227 ****************************************************************************/
3228 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3231 int outsize,ret= -1;
3232 BOOL bad_path = False;
3234 pstrcpy(directory,smb_buf(inbuf) + 1);
3235 unix_convert(directory,conn,0,&bad_path,NULL);
3237 if (check_name(directory, conn))
3238 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
3242 if((errno == ENOENT) && bad_path)
3244 unix_ERR_class = ERRDOS;
3245 unix_ERR_code = ERRbadpath;
3247 return(UNIXERROR(ERRDOS,ERRnoaccess));
3250 outsize = set_message(outbuf,0,0,True);
3252 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
3257 /****************************************************************************
3258 Static function used by reply_rmdir to delete an entire directory
3260 ****************************************************************************/
3262 static BOOL recursive_rmdir(char *directory)
3266 void *dirptr = OpenDir(NULL, directory, False);
3271 while((dname = ReadDirName(dirptr)))
3276 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3279 /* Construct the full name. */
3280 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3286 pstrcpy(fullname, directory);
3287 pstrcat(fullname, "/");
3288 pstrcat(fullname, dname);
3290 if(dos_lstat(fullname, &st) != 0)
3296 if(st.st_mode & S_IFDIR)
3298 if(recursive_rmdir(fullname)!=0)
3303 if(dos_rmdir(fullname) != 0)
3309 else if(dos_unlink(fullname) != 0)
3319 /****************************************************************************
3320 The internals of the rmdir code - called elsewhere.
3321 ****************************************************************************/
3323 BOOL rmdir_internals(connection_struct *conn, char *directory)
3327 ok = (dos_rmdir(directory) == 0);
3328 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3331 * Check to see if the only thing in this directory are
3332 * vetoed files/directories. If so then delete them and
3333 * retry. If we fail to delete any of them (and we *don't*
3334 * do a recursive delete) then fail the rmdir.
3336 BOOL all_veto_files = True;
3338 void *dirptr = OpenDir(conn, directory, False);
3342 int dirpos = TellDir(dirptr);
3343 while ((dname = ReadDirName(dirptr)))
3345 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3347 if(!IS_VETO_PATH(conn, dname))
3349 all_veto_files = False;
3355 SeekDir(dirptr,dirpos);
3356 while ((dname = ReadDirName(dirptr)))
3361 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3364 /* Construct the full name. */
3365 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3370 pstrcpy(fullname, directory);
3371 pstrcat(fullname, "/");
3372 pstrcat(fullname, dname);
3374 if(dos_lstat(fullname, &st) != 0)
3376 if(st.st_mode & S_IFDIR)
3378 if(lp_recursive_veto_delete(SNUM(conn)))
3380 if(recursive_rmdir(fullname) != 0)
3383 if(dos_rmdir(fullname) != 0)
3386 else if(dos_unlink(fullname) != 0)
3390 /* Retry the rmdir */
3391 ok = (dos_rmdir(directory) == 0);
3401 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3402 directory,strerror(errno)));
3407 /****************************************************************************
3409 ****************************************************************************/
3411 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3416 BOOL bad_path = False;
3418 pstrcpy(directory,smb_buf(inbuf) + 1);
3419 unix_convert(directory,conn, NULL,&bad_path,NULL);
3421 if (check_name(directory,conn))
3423 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3424 ok = rmdir_internals(conn, directory);
3429 if((errno == ENOENT) && bad_path)
3431 unix_ERR_class = ERRDOS;
3432 unix_ERR_code = ERRbadpath;
3434 return(UNIXERROR(ERRDOS,ERRbadpath));
3437 outsize = set_message(outbuf,0,0,True);
3439 DEBUG( 3, ( "rmdir %s\n", directory ) );
3445 /*******************************************************************
3446 resolve wildcards in a filename rename
3447 ********************************************************************/
3448 static BOOL resolve_wildcards(char *name1,char *name2)
3450 fstring root1,root2;
3454 name1 = strrchr(name1,'/');
3455 name2 = strrchr(name2,'/');
3457 if (!name1 || !name2) return(False);
3459 fstrcpy(root1,name1);
3460 fstrcpy(root2,name2);
3461 p = strrchr(root1,'.');
3468 p = strrchr(root2,'.');
3500 pstrcpy(name2,root2);
3503 pstrcat(name2,ext2);
3509 /*******************************************************************
3510 check if a user is allowed to rename a file
3511 ********************************************************************/
3512 static BOOL can_rename(char *fname,connection_struct *conn)
3514 SMB_STRUCT_STAT sbuf;
3516 if (!CAN_WRITE(conn)) return(False);
3518 if (dos_lstat(fname,&sbuf) != 0) return(False);
3519 if (!check_file_sharing(conn,fname,True)) return(False);
3524 /****************************************************************************
3525 The guts of the rename command, split out so it may be called by the NT SMB
3527 ****************************************************************************/
3528 int rename_internals(connection_struct *conn,
3529 char *inbuf, char *outbuf, char *name,
3530 char *newname, BOOL replace_if_exists)
3534 pstring newname_last_component;
3537 BOOL bad_path1 = False;
3538 BOOL bad_path2 = False;
3540 int error = ERRnoaccess;
3544 *directory = *mask = 0;
3546 rc = unix_convert(name,conn,0,&bad_path1,NULL);
3547 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3550 * Split the old name into directory and last component
3551 * strings. Note that unix_convert may have stripped off a
3552 * leading ./ from both name and newname if the rename is
3553 * at the root of the share. We need to make sure either both
3554 * name and newname contain a / character or neither of them do
3555 * as this is checked in resolve_wildcards().
3558 p = strrchr(name,'/');
3560 pstrcpy(directory,".");
3564 pstrcpy(directory,name);
3566 *p = '/'; /* Replace needed for exceptional test below. */
3570 * We should only check the mangled cache
3571 * here if unix_convert failed. This means
3572 * that the path in 'mask' doesn't exist
3573 * on the file system and so we need to look
3574 * for a possible mangle. This patch from
3575 * Tine Smukavec <valentin.smukavec@hermes.si>.
3578 if (!rc && is_mangled(mask))
3579 check_mangled_cache( mask );
3581 has_wild = strchr(mask,'*') || strchr(mask,'?');
3585 * No wildcards - just process the one file.
3587 BOOL is_short_name = is_8_3(name, True);
3589 /* Add a terminating '/' to the directory name. */
3590 pstrcat(directory,"/");
3591 pstrcat(directory,mask);
3593 /* Ensure newname contains a '/' also */
3594 if(strrchr(newname,'/') == 0) {
3597 pstrcpy(tmpstr, "./");
3598 pstrcat(tmpstr, newname);
3599 pstrcpy(newname, tmpstr);
3602 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3603 case_sensitive, case_preserve, short_case_preserve, directory,
3604 newname, newname_last_component, is_short_name));
3607 * Check for special case with case preserving and not
3608 * case sensitive, if directory and newname are identical,
3609 * and the old last component differs from the original
3610 * last component only by case, then we should allow
3611 * the rename (user is trying to change the case of the
3614 if((case_sensitive == False) &&
3615 (((case_preserve == True) &&
3616 (is_short_name == False)) ||
3617 ((short_case_preserve == True) &&
3618 (is_short_name == True))) &&
3619 strcsequal(directory, newname)) {
3620 pstring newname_modified_last_component;
3623 * Get the last component of the modified name.
3624 * Note that we guarantee that newname contains a '/'
3627 p = strrchr(newname,'/');
3628 pstrcpy(newname_modified_last_component,p+1);
3630 if(strcsequal(newname_modified_last_component,
3631 newname_last_component) == False) {
3633 * Replace the modified last component with
3636 pstrcpy(p+1, newname_last_component);
3640 if(replace_if_exists) {
3642 * NT SMB specific flag - rename can overwrite
3643 * file with the same name so don't check for
3646 if(resolve_wildcards(directory,newname) &&
3647 can_rename(directory,conn) &&
3648 !dos_rename(directory,newname))
3651 if (resolve_wildcards(directory,newname) &&
3652 can_rename(directory,conn) &&
3653 !dos_file_exist(newname,NULL) &&
3654 !dos_rename(directory,newname))
3658 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3659 directory,newname));
3661 if (!count) exists = dos_file_exist(directory,NULL);
3662 if (!count && exists && dos_file_exist(newname,NULL)) {
3668 * Wildcards - process each file that matches.
3670 void *dirptr = NULL;
3674 if (check_name(directory,conn))
3675 dirptr = OpenDir(conn, directory, True);
3680 if (strequal(mask,"????????.???"))
3683 while ((dname = ReadDirName(dirptr))) {
3685 pstrcpy(fname,dname);
3687 if(!mask_match(fname, mask, case_sensitive, False))
3690 error = ERRnoaccess;
3691 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3692 if (!can_rename(fname,conn)) {
3693 DEBUG(6,("rename %s refused\n", fname));
3696 pstrcpy(destname,newname);
3698 if (!resolve_wildcards(fname,destname)) {
3699 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3703 if (!replace_if_exists && dos_file_exist(destname,NULL)) {
3704 DEBUG(6,("dos_file_exist %s\n", destname));
3709 if (!dos_rename(fname,destname))
3711 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3719 return(ERROR(ERRDOS,error));
3721 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3722 unix_ERR_class = ERRDOS;
3723 unix_ERR_code = ERRbadpath;
3725 return(UNIXERROR(ERRDOS,error));
3732 /****************************************************************************
3734 ****************************************************************************/
3736 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3742 pstrcpy(name,smb_buf(inbuf) + 1);
3743 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3745 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3747 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3749 outsize = set_message(outbuf,0,0,True);
3754 /*******************************************************************
3755 copy a file as part of a reply_copy
3756 ******************************************************************/
3758 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3759 int count,BOOL target_is_directory, int *err_ret)
3764 files_struct *fsp1,*fsp2;
3769 pstrcpy(dest,dest1);
3770 if (target_is_directory) {
3771 char *p = strrchr(src,'/');
3780 if (!dos_file_exist(src,&st))
3787 open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3788 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3795 if (!target_is_directory && count)
3800 close_file(fsp1,False);
3803 open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3804 ofun,st.st_mode,0,&Access,&action);
3807 close_file(fsp1,False);
3812 if ((ofun&3) == 1) {
3813 if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3814 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3817 * Stop the copy from occurring.
3825 ret = transfer_file(fsp1->fd_ptr->fd,
3826 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3828 close_file(fsp1,False);
3830 * As we are opening fsp1 read-only we only expect
3831 * an error on close on fsp2 if we are out of space.
3832 * Thus we don't look at the error return from the
3835 *err_ret = close_file(fsp2,False);
3837 return(ret == (SMB_OFF_T)st.st_size);
3842 /****************************************************************************
3843 reply to a file copy.
3844 ****************************************************************************/
3845 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3850 pstring mask,newname;
3853 int error = ERRnoaccess;
3857 int tid2 = SVAL(inbuf,smb_vwv0);
3858 int ofun = SVAL(inbuf,smb_vwv1);
3859 int flags = SVAL(inbuf,smb_vwv2);
3860 BOOL target_is_directory=False;
3861 BOOL bad_path1 = False;
3862 BOOL bad_path2 = False;
3865 *directory = *mask = 0;
3867 pstrcpy(name,smb_buf(inbuf));
3868 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3870 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3872 if (tid2 != conn->cnum) {
3873 /* can't currently handle inter share copies XXXX */
3874 DEBUG(3,("Rejecting inter-share copy\n"));
3875 return(ERROR(ERRSRV,ERRinvdevice));
3878 rc = unix_convert(name,conn,0,&bad_path1,NULL);
3879 unix_convert(newname,conn,0,&bad_path2,NULL);
3881 target_is_directory = dos_directory_exist(newname,NULL);
3883 if ((flags&1) && target_is_directory) {
3884 return(ERROR(ERRDOS,ERRbadfile));
3887 if ((flags&2) && !target_is_directory) {
3888 return(ERROR(ERRDOS,ERRbadpath));
3891 if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
3892 /* wants a tree copy! XXXX */
3893 DEBUG(3,("Rejecting tree copy\n"));
3894 return(ERROR(ERRSRV,ERRerror));
3897 p = strrchr(name,'/');
3899 pstrcpy(directory,"./");
3903 pstrcpy(directory,name);
3908 * We should only check the mangled cache
3909 * here if unix_convert failed. This means
3910 * that the path in 'mask' doesn't exist
3911 * on the file system and so we need to look
3912 * for a possible mangle. This patch from
3913 * Tine Smukavec <valentin.smukavec@hermes.si>.
3916 if (!rc && is_mangled(mask))
3917 check_mangled_cache( mask );
3919 has_wild = strchr(mask,'*') || strchr(mask,'?');
3922 pstrcat(directory,"/");
3923 pstrcat(directory,mask);
3924 if (resolve_wildcards(directory,newname) &&
3925 copy_file(directory,newname,conn,ofun,
3926 count,target_is_directory,&err)) count++;
3929 return(UNIXERROR(ERRHRD,ERRgeneral));
3931 if (!count) exists = dos_file_exist(directory,NULL);
3933 void *dirptr = NULL;
3937 if (check_name(directory,conn))
3938 dirptr = OpenDir(conn, directory, True);
3943 if (strequal(mask,"????????.???"))
3946 while ((dname = ReadDirName(dirptr))) {
3948 pstrcpy(fname,dname);
3950 if(!mask_match(fname, mask, case_sensitive, False))
3953 error = ERRnoaccess;
3954 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3955 pstrcpy(destname,newname);
3956 if (resolve_wildcards(fname,destname) &&
3957 copy_file(fname,destname,conn,ofun,
3958 count,target_is_directory,&err)) count++;
3959 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3967 /* Error on close... */
3969 return(UNIXERROR(ERRHRD,ERRgeneral));
3973 return(ERROR(ERRDOS,error));
3976 if((errno == ENOENT) && (bad_path1 || bad_path2))
3978 unix_ERR_class = ERRDOS;
3979 unix_ERR_code = ERRbadpath;
3981 return(UNIXERROR(ERRDOS,error));
3985 outsize = set_message(outbuf,1,0,True);
3986 SSVAL(outbuf,smb_vwv0,count);
3991 /****************************************************************************
3993 ****************************************************************************/
3994 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4002 if (!CAN_SETDIR(snum))
4003 return(ERROR(ERRDOS,ERRnoaccess));
4005 pstrcpy(newdir,smb_buf(inbuf) + 1);
4008 if (strlen(newdir) == 0) {
4011 ok = dos_directory_exist(newdir,NULL);
4013 string_set(&conn->connectpath,newdir);
4018 return(ERROR(ERRDOS,ERRbadpath));
4020 outsize = set_message(outbuf,0,0,True);
4021 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4023 DEBUG(3,("setdir %s\n", newdir));
4028 /****************************************************************************
4029 Get a lock count, dealing with large count requests.
4030 ****************************************************************************/
4032 SMB_OFF_T get_lock_count( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4034 SMB_OFF_T count = 0;
4038 if(!large_file_format) {
4039 count = (SMB_OFF_T)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4042 #if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
4044 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4045 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4047 #else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
4050 * NT4.x seems to be broken in that it sends large file
4051 * lockingX calls even if the CAP_LARGE_FILES was *not*
4052 * negotiated. For boxes without large file locks truncate the
4053 * lock count by dropping the top 32 bits.
4056 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4057 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4058 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4059 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4060 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4063 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4065 * Before we error out, see if we can sensibly map the top bits
4066 * down to the lower bits - or lose the top bits if they are all 1's.
4067 * It seems that NT has this horrible bug where it will send 64 bit
4068 * lock requests even if told not to. JRA.
4071 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) == (uint32)0xFFFFFFFF)
4072 count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset));
4073 else if (IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) == (uint32)0xFFFFFFFF)
4074 count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4077 DEBUG(0,("get_lock_count: Error : a large file count (%x << 32 | %x) was sent and we don't \
4078 support large counts.\n", (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4079 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4082 return (SMB_OFF_T)-1;
4086 count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4088 #endif /* LARGE_SMB_OFF_T */
4093 /****************************************************************************
4094 Get a lock offset, dealing with large offset requests.
4095 ****************************************************************************/
4097 SMB_OFF_T get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4099 SMB_OFF_T offset = 0;
4103 if(!large_file_format) {
4104 offset = (SMB_OFF_T)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4107 #if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
4109 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4110 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4112 #else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
4115 * NT4.x seems to be broken in that it sends large file
4116 * lockingX calls even if the CAP_LARGE_FILES was *not*
4117 * negotiated. For boxes without large file locks mangle the
4118 * lock offset by mapping the top 32 bits onto the lower 32.
4121 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4122 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4123 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4126 if((new_low = map_lock_offset(high, low)) == 0) {
4128 return (SMB_OFF_T)-1;
4131 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4132 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4133 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4134 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4137 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0){
4139 * Before we error out, see if we can sensibly map the top bits
4140 * down to the lower bits - or lose the top bits if they are all 1's.
4141 * It seems that NT has this horrible bug where it will send 64 bit
4142 * lock requests even if told not to. JRA.
4145 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)) == (uint32)0xFFFFFFFF)
4146 offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4147 else if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) == (uint32)0xFFFFFFFF)
4148 offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4151 DEBUG(0,("get_lock_count: Error : a large file offset (%x << 32 | %x) was sent and we don't \
4152 support large offsets.\n", (unsigned int)IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)),
4153 (unsigned int)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)) ));
4156 return (SMB_OFF_T)-1;
4160 offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4162 #endif /* LARGE_SMB_OFF_T */
4167 /****************************************************************************
4168 reply to a lockingX request
4169 ****************************************************************************/
4171 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4173 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4174 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4176 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4178 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4179 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4180 SMB_OFF_T count = 0, offset = 0;
4181 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4184 uint32 ecode=0, dummy2;
4185 int eclass=0, dummy1;
4186 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
4189 CHECK_FSP(fsp,conn);
4192 data = smb_buf(inbuf);
4194 /* Check if this is an oplock break on a file
4195 we have granted an oplock on.
4197 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4199 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
4203 * Make sure we have granted an exclusive or batch oplock on this file.
4206 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4208 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4209 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4211 /* if this is a pure oplock break request then don't send a reply */
4212 if (num_locks == 0 && num_ulocks == 0)
4215 return ERROR(ERRDOS,ERRlock);
4218 if (remove_oplock(fsp) == False) {
4219 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4223 /* if this is a pure oplock break request then don't send a reply */
4224 if (num_locks == 0 && num_ulocks == 0)
4226 /* Sanity check - ensure a pure oplock break is not a
4228 if(CVAL(inbuf,smb_vwv0) != 0xff)
4229 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4230 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4235 /* Data now points at the beginning of the list
4236 of smb_unlkrng structs */
4237 for(i = 0; i < (int)num_ulocks; i++) {
4238 count = get_lock_count( data, i, large_file_format, &err1);
4239 offset = get_lock_offset( data, i, large_file_format, &err2);
4242 * There is no error code marked "stupid client bug".... :-).
4245 return ERROR(ERRDOS,ERRnoaccess);
4247 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
4248 (double)offset, (double)count, fsp->fsp_name ));
4250 if(!do_unlock(fsp,conn,count,offset, &eclass, &ecode))
4251 return ERROR(eclass,ecode);
4254 /* Setup the timeout in seconds. */
4255 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4257 /* Now do any requested locks */
4258 data += ((large_file_format ? 20 : 10)*num_ulocks);
4260 /* Data now points at the beginning of the list
4261 of smb_lkrng structs */
4263 for(i = 0; i < (int)num_locks; i++) {
4264 count = get_lock_count( data, i, large_file_format, &err1);
4265 offset = get_lock_offset( data, i, large_file_format, &err2);
4268 * There is no error code marked "stupid client bug".... :-).
4271 return ERROR(ERRDOS,ERRnoaccess);
4273 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
4274 (double)offset, (double)count, fsp->fsp_name ));
4276 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4278 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4280 * A blocking lock was requested. Package up
4281 * this smb into a queued request and push it
4282 * onto the blocking lock queue.
4284 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
4291 /* If any of the above locks failed, then we must unlock
4292 all of the previous locks (X/Open spec). */
4293 if(i != num_locks && num_locks != 0) {
4294 for(; i >= 0; i--) {
4295 count = get_lock_count( data, i, large_file_format, &err1);
4296 offset = get_lock_offset( data, i, large_file_format, &err2);
4299 * There is no error code marked "stupid client bug".... :-).
4302 return ERROR(ERRDOS,ERRnoaccess);
4304 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
4306 return ERROR(eclass,ecode);
4309 set_message(outbuf,2,0,True);
4311 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4312 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4314 return chain_reply(inbuf,outbuf,length,bufsize);
4318 /****************************************************************************
4319 reply to a SMBreadbmpx (read block multiplex) request
4320 ****************************************************************************/
4321 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4332 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4334 /* this function doesn't seem to work - disable by default */
4336 return(ERROR(ERRSRV,ERRuseSTD));
4338 outsize = set_message(outbuf,8,0,True);
4340 CHECK_FSP(fsp,conn);
4344 startpos = IVAL(inbuf,smb_vwv1);
4345 maxcount = SVAL(inbuf,smb_vwv3);
4347 data = smb_buf(outbuf);
4348 pad = ((long)data)%4;
4349 if (pad) pad = 4 - pad;
4352 max_per_packet = bufsize-(outsize+pad);
4356 if (is_locked(fsp,conn,maxcount,startpos, READ_LOCK))
4357 return(ERROR(ERRDOS,ERRlock));
4361 size_t N = MIN(max_per_packet,tcount-total_read);
4363 nread = read_file(fsp,data,startpos,N);
4365 if (nread <= 0) nread = 0;
4367 if (nread < (ssize_t)N)
4368 tcount = total_read + nread;
4370 set_message(outbuf,8,nread,False);
4371 SIVAL(outbuf,smb_vwv0,startpos);
4372 SSVAL(outbuf,smb_vwv2,tcount);
4373 SSVAL(outbuf,smb_vwv6,nread);
4374 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4376 send_smb(Client,outbuf);
4378 total_read += nread;
4381 while (total_read < (ssize_t)tcount);
4386 /****************************************************************************
4387 reply to a SMBwritebmpx (write block multiplex primary) request
4388 ****************************************************************************/
4390 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4393 ssize_t nwritten = -1;
4400 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4402 CHECK_FSP(fsp,conn);
4406 tcount = SVAL(inbuf,smb_vwv1);
4407 startpos = IVAL(inbuf,smb_vwv3);
4408 write_through = BITSETW(inbuf+smb_vwv7,0);
4409 numtowrite = SVAL(inbuf,smb_vwv10);
4410 smb_doff = SVAL(inbuf,smb_vwv11);
4412 data = smb_base(inbuf) + smb_doff;
4414 /* If this fails we need to send an SMBwriteC response,
4415 not an SMBwritebmpx - set this up now so we don't forget */
4416 CVAL(outbuf,smb_com) = SMBwritec;
4418 if (is_locked(fsp,conn,tcount,startpos,WRITE_LOCK))
4419 return(ERROR(ERRDOS,ERRlock));
4421 nwritten = write_file(fsp,data,startpos,numtowrite);
4423 if(lp_syncalways(SNUM(conn)) || write_through)
4424 sync_file(conn,fsp);
4426 if(nwritten < (ssize_t)numtowrite)
4427 return(UNIXERROR(ERRHRD,ERRdiskfull));
4429 /* If the maximum to be written to this file
4430 is greater than what we just wrote then set
4431 up a secondary struct to be attached to this
4432 fd, we will use this to cache error messages etc. */
4433 if((ssize_t)tcount > nwritten)
4435 write_bmpx_struct *wbms;
4436 if(fsp->wbmpx_ptr != NULL)
4437 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4439 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4442 DEBUG(0,("Out of memory in reply_readmpx\n"));
4443 return(ERROR(ERRSRV,ERRnoresource));
4445 wbms->wr_mode = write_through;
4446 wbms->wr_discard = False; /* No errors yet */
4447 wbms->wr_total_written = nwritten;
4448 wbms->wr_errclass = 0;
4450 fsp->wbmpx_ptr = wbms;
4453 /* We are returning successfully, set the message type back to
4455 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4457 outsize = set_message(outbuf,1,0,True);
4459 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4461 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4462 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4464 if (write_through && tcount==nwritten) {
4465 /* we need to send both a primary and a secondary response */
4466 smb_setlen(outbuf,outsize - 4);
4467 send_smb(Client,outbuf);
4469 /* now the secondary */
4470 outsize = set_message(outbuf,1,0,True);
4471 CVAL(outbuf,smb_com) = SMBwritec;
4472 SSVAL(outbuf,smb_vwv0,nwritten);
4479 /****************************************************************************
4480 reply to a SMBwritebs (write block multiplex secondary) request
4481 ****************************************************************************/
4482 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4485 ssize_t nwritten = -1;
4492 write_bmpx_struct *wbms;
4493 BOOL send_response = False;
4494 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4496 CHECK_FSP(fsp,conn);
4499 tcount = SVAL(inbuf,smb_vwv1);
4500 startpos = IVAL(inbuf,smb_vwv2);
4501 numtowrite = SVAL(inbuf,smb_vwv6);
4502 smb_doff = SVAL(inbuf,smb_vwv7);
4504 data = smb_base(inbuf) + smb_doff;
4506 /* We need to send an SMBwriteC response, not an SMBwritebs */
4507 CVAL(outbuf,smb_com) = SMBwritec;
4509 /* This fd should have an auxiliary struct attached,
4510 check that it does */
4511 wbms = fsp->wbmpx_ptr;
4512 if(!wbms) return(-1);
4514 /* If write through is set we can return errors, else we must
4516 write_through = wbms->wr_mode;
4518 /* Check for an earlier error */
4519 if(wbms->wr_discard)
4520 return -1; /* Just discard the packet */
4522 nwritten = write_file(fsp,data,startpos,numtowrite);
4524 if(lp_syncalways(SNUM(conn)) || write_through)
4525 sync_file(conn,fsp);
4527 if (nwritten < (ssize_t)numtowrite)
4531 /* We are returning an error - we can delete the aux struct */
4532 if (wbms) free((char *)wbms);
4533 fsp->wbmpx_ptr = NULL;
4534 return(ERROR(ERRHRD,ERRdiskfull));
4536 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4539 /* Increment the total written, if this matches tcount
4540 we can discard the auxiliary struct (hurrah !) and return a writeC */
4541 wbms->wr_total_written += nwritten;
4542 if(wbms->wr_total_written >= tcount)
4546 outsize = set_message(outbuf,1,0,True);
4547 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4548 send_response = True;
4552 fsp->wbmpx_ptr = NULL;
4562 /****************************************************************************
4563 reply to a SMBsetattrE
4564 ****************************************************************************/
4566 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4568 struct utimbuf unix_times;
4570 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4572 outsize = set_message(outbuf,0,0,True);
4574 CHECK_FSP(fsp,conn);
4577 /* Convert the DOS times into unix times. Ignore create
4578 time as UNIX can't set this.
4580 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4581 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4584 * Patch from Ray Frush <frush@engr.colostate.edu>
4585 * Sometimes times are sent as zero - ignore them.
4588 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4590 /* Ignore request */
4593 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4594 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4598 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4600 /* set modify time = to access time if modify time was 0 */
4601 unix_times.modtime = unix_times.actime;
4604 /* Set the date on this file */
4605 if(file_utime(conn, fsp->fsp_name, &unix_times))
4606 return(ERROR(ERRDOS,ERRnoaccess));
4608 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4609 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4615 /****************************************************************************
4616 reply to a SMBgetattrE
4617 ****************************************************************************/
4619 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4621 SMB_STRUCT_STAT sbuf;
4624 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4626 outsize = set_message(outbuf,11,0,True);
4628 CHECK_FSP(fsp,conn);
4631 /* Do an fstat on this file */
4632 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4633 return(UNIXERROR(ERRDOS,ERRnoaccess));
4635 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4637 /* Convert the times into dos times. Set create
4638 date to be last modify date as UNIX doesn't save
4640 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4641 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4642 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4645 SIVAL(outbuf,smb_vwv6,0);
4646 SIVAL(outbuf,smb_vwv8,0);
4650 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4651 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4653 SSVAL(outbuf,smb_vwv10, mode);
4655 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));