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);
356 init_dfsroot(conn, inbuf, outbuf);
360 DEBUG(3,("tconX service=%s user=%s\n",
363 /* set the incoming and outgoing tid to the just created one */
364 SSVAL(inbuf,smb_tid,conn->cnum);
365 SSVAL(outbuf,smb_tid,conn->cnum);
367 return chain_reply(inbuf,outbuf,length,bufsize);
371 /****************************************************************************
372 reply to an unknown type
373 ****************************************************************************/
374 int reply_unknown(char *inbuf,char *outbuf)
377 type = CVAL(inbuf,smb_com);
379 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
380 smb_fn_name(type), type, type));
382 return(ERROR(ERRSRV,ERRunknownsmb));
386 /****************************************************************************
388 ****************************************************************************/
389 int reply_ioctl(connection_struct *conn,
390 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
392 uint16 device = SVAL(inbuf,smb_vwv1);
393 uint16 function = SVAL(inbuf,smb_vwv2);
394 uint32 ioctl_code = (device << 16) + function;
395 int replysize, outsize;
398 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
402 case IOCTL_QUERY_JOB_INFO:
406 return(ERROR(ERRSRV,ERRnosupport));
409 outsize = set_message(outbuf,8,replysize+1,True);
410 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
411 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
412 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
413 p = smb_buf(outbuf) + 1; /* Allow for alignment */
417 case IOCTL_QUERY_JOB_INFO:
418 SSVAL(p,0,1); /* Job number */
419 StrnCpy(p+2, global_myname, 15); /* Our NetBIOS name */
420 StrnCpy(p+18, lp_servicename(SNUM(conn)), 13); /* Service name */
427 /****************************************************************************
428 always return an error: it's just a matter of which one...
429 ****************************************************************************/
430 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
431 char *smb_passwd, int smb_passlen,
432 char *smb_nt_passwd, int smb_nt_passlen)
434 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
435 if (lp_security() == SEC_USER)
437 smb_trust_acct = getsmbpwnam(user);
441 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
442 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
443 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
446 if (smb_trust_acct == NULL)
448 /* lkclXXXX: workstation entry doesn't exist */
449 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
450 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
451 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
455 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
457 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
458 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
459 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
462 if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
464 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
465 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
466 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
469 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
471 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
472 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
473 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
476 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
478 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
479 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
480 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
483 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
485 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
486 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
487 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
491 /* don't know what to do: indicate logon failure */
492 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
493 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
496 /****************************************************************************
497 Create a UNIX user on demand.
498 ****************************************************************************/
500 static int smb_create_user(char *unix_user)
505 pstrcpy(add_script, lp_adduser_script());
506 pstring_sub(add_script, "%u", unix_user);
507 ret = smbrun(add_script,NULL,False);
508 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
512 /****************************************************************************
513 Delete a UNIX user on demand.
514 ****************************************************************************/
516 static int smb_delete_user(char *unix_user)
521 pstrcpy(del_script, lp_deluser_script());
522 pstring_sub(del_script, "%u", unix_user);
523 ret = smbrun(del_script,NULL,False);
524 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
528 /****************************************************************************
529 Check user is in correct domain if required
530 ****************************************************************************/
532 static BOOL check_domain_match(char *user, char *domain)
535 * If we aren't serving to trusted domains, we must make sure that
536 * the validation request comes from an account in the same domain
537 * as the Samba server
540 if (!lp_allow_trusted_domains() &&
541 !strequal(lp_workgroup(), domain) ) {
542 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
549 /****************************************************************************
550 Check for a valid username and password in security=server mode.
551 ****************************************************************************/
553 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
554 char *smb_apasswd, int smb_apasslen,
555 char *smb_ntpasswd, int smb_ntpasslen)
559 if(lp_security() != SEC_SERVER)
562 if (!check_domain_match(orig_user, domain))
565 ret = server_validate(orig_user, domain,
566 smb_apasswd, smb_apasslen,
567 smb_ntpasswd, smb_ntpasslen);
570 * User validated ok against Domain controller.
571 * If the admin wants us to try and create a UNIX
572 * user on the fly, do so.
573 * Note that we can never delete users when in server
574 * level security as we never know if it was a failure
575 * due to a bad password, or the user really doesn't exist.
577 if(lp_adduser_script() && !Get_Pwnam(unix_user,True)) {
578 smb_create_user(unix_user);
585 /****************************************************************************
586 Check for a valid username and password in security=domain mode.
587 ****************************************************************************/
589 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
590 char *smb_apasswd, int smb_apasslen,
591 char *smb_ntpasswd, int smb_ntpasslen)
594 BOOL user_exists = True;
596 if(lp_security() != SEC_DOMAIN)
599 if (!check_domain_match(orig_user, domain))
602 ret = domain_client_validate(orig_user, domain,
603 smb_apasswd, smb_apasslen,
604 smb_ntpasswd, smb_ntpasslen,
609 * User validated ok against Domain controller.
610 * If the admin wants us to try and create a UNIX
611 * user on the fly, do so.
613 if(user_exists && lp_adduser_script() && !Get_Pwnam(unix_user,True)) {
614 smb_create_user(unix_user);
618 * User failed to validate ok against Domain controller.
619 * If the failure was "user doesn't exist" and admin
620 * wants us to try and delete that UNIX user on the fly,
623 if(!user_exists && lp_deluser_script() && Get_Pwnam(unix_user,True)) {
624 smb_delete_user(unix_user);
631 /****************************************************************************
632 Return a bad password error configured for the correct client type.
633 ****************************************************************************/
635 static int bad_password_error(char *inbuf,char *outbuf)
637 enum remote_arch_types ra_type = get_remote_arch();
639 if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
640 (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
641 SSVAL(outbuf,smb_flg2,FLAGS2_32_BIT_ERROR_CODES);
642 return(ERROR(0,0xc0000000|NT_STATUS_LOGON_FAILURE));
645 return(ERROR(ERRSRV,ERRbadpw));
648 /****************************************************************************
649 reply to a session setup command
650 ****************************************************************************/
652 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
658 int smb_apasslen = 0;
660 int smb_ntpasslen = 0;
661 pstring smb_ntpasswd;
662 BOOL valid_nt_password = False;
666 static BOOL done_sesssetup = False;
667 BOOL doencrypt = SMBENCRYPT();
673 smb_bufsize = SVAL(inbuf,smb_vwv2);
675 if (Protocol < PROTOCOL_NT1) {
676 smb_apasslen = SVAL(inbuf,smb_vwv7);
677 if (smb_apasslen > MAX_PASS_LEN)
678 overflow_attack(smb_apasslen);
680 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
681 smb_apasswd[smb_apasslen] = 0;
682 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
684 * Incoming user is in DOS codepage format. Convert
687 dos_to_unix(user,True);
689 if (!doencrypt && (lp_security() != SEC_SERVER)) {
690 smb_apasslen = strlen(smb_apasswd);
693 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
694 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
695 enum remote_arch_types ra_type = get_remote_arch();
696 char *p = smb_buf(inbuf);
698 if(global_client_caps == 0)
699 global_client_caps = IVAL(inbuf,smb_vwv11);
701 /* client_caps is used as final determination if client is NT or Win95.
702 This is needed to return the correct error codes in some
706 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
707 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
708 set_remote_arch( RA_WIN95);
712 if (passlen1 != 24 && passlen2 != 24)
715 if (passlen1 > MAX_PASS_LEN) {
716 overflow_attack(passlen1);
719 passlen1 = MIN(passlen1, MAX_PASS_LEN);
720 passlen2 = MIN(passlen2, MAX_PASS_LEN);
723 /* both Win95 and WinNT stuff up the password lengths for
724 non-encrypting systems. Uggh.
726 if passlen1==24 its a win95 system, and its setting the
727 password length incorrectly. Luckily it still works with the
728 default code because Win95 will null terminate the password
731 if passlen1>0 and passlen2>0 then maybe its a NT box and its
732 setting passlen2 to some random value which really stuffs
733 things up. we need to fix that one. */
735 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
739 if (lp_restrict_anonymous()) {
740 /* there seems to be no reason behind the differences in MS clients formatting
741 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
742 * in particular seems to have an extra null byte between the username and the
743 * domain, or the password length calculation is wrong, which throws off the
744 * string extraction routines below. This makes the value of domain be the
745 * empty string, which fails the restrict anonymous check further down.
746 * This compensates for that, and allows browsing to work in mixed NT and
747 * win95 environments even when restrict anonymous is true. AAB
749 dump_data(100, p, 0x70);
750 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
751 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
752 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
753 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
754 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
759 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
760 /* Save the lanman2 password and the NT md4 password. */
761 smb_apasslen = passlen1;
762 memcpy(smb_apasswd,p,smb_apasslen);
763 smb_apasswd[smb_apasslen] = 0;
764 smb_ntpasslen = passlen2;
765 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
766 smb_ntpasswd[smb_ntpasslen] = 0;
769 * Ensure the plaintext passwords are in UNIX format.
772 dos_to_unix(smb_apasswd,True);
773 dos_to_unix(smb_ntpasswd,True);
777 /* we use the first password that they gave */
778 smb_apasslen = passlen1;
779 StrnCpy(smb_apasswd,p,smb_apasslen);
781 * Ensure the plaintext password is in UNIX format.
783 dos_to_unix(smb_apasswd,True);
785 /* trim the password */
786 smb_apasslen = strlen(smb_apasswd);
788 /* wfwg sometimes uses a space instead of a null */
789 if (strequal(smb_apasswd," ")) {
795 p += passlen1 + passlen2;
797 p = skip_string(p,1);
799 * Incoming user is in DOS codepage format. Convert
802 dos_to_unix(user,True);
805 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
806 domain,skip_string(p,1),skip_string(p,2)));
810 DEBUG(3,("sesssetupX:name=[%s]\n",user));
812 /* If name ends in $ then I think it's asking about whether a */
813 /* computer with that name (minus the $) has access. For now */
814 /* say yes to everything ending in $. */
816 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
817 return session_trust_account(conn, inbuf, outbuf, user,
818 smb_apasswd, smb_apasslen,
819 smb_ntpasswd, smb_ntpasslen);
822 if (done_sesssetup && lp_restrict_anonymous()) {
823 /* tests show that even if browsing is done over already validated connections
824 * without a username and password the domain is still provided, which it
825 * wouldn't be if it was a purely anonymous connection. So, in order to
826 * restrict anonymous, we only deny connections that have no session
827 * information. If a domain has been provided, then it's not a purely
828 * anonymous connection. AAB
830 if (!*user && !*smb_apasswd && !*domain) {
831 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
832 return(ERROR(ERRDOS,ERRnoaccess));
836 /* If no username is sent use the guest account */
838 pstrcpy(user,lp_guestaccount(-1));
839 /* If no user and no password then set guest flag. */
840 if( *smb_apasswd == 0)
847 * In share level security, only overwrite sesssetup_use if
848 * it's a non null-session share. Helps keep %U and %G
852 if((lp_security() != SEC_SHARE) || (*user && !guest))
853 pstrcpy(sesssetup_user,user);
855 reload_services(True);
858 * Save the username before mapping. We will use
859 * the original username sent to us for security=server
860 * and security=domain checking.
863 pstrcpy( orig_user, user);
866 * Pass the user through the NT -> unix user mapping
870 (void)map_username(user);
873 * Do any UNIX username case mangling.
875 (void)Get_Pwnam( user, True);
877 add_session_user(user);
880 * Check if the given username was the guest user with no password.
883 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
887 * Check with orig_user for security=server and
892 !check_server_security(orig_user, domain, user,
893 smb_apasswd, smb_apasslen,
894 smb_ntpasswd, smb_ntpasslen) &&
895 !check_domain_security(orig_user, domain, user,
896 smb_apasswd, smb_apasslen,
897 smb_ntpasswd, smb_ntpasslen) &&
898 !check_hosts_equiv(user)
903 * If we get here then the user wasn't guest and the remote
904 * authentication methods failed. Check the authentication
905 * methods on this local server.
907 * If an NT password was supplied try and validate with that
908 * first. This is superior as the passwords are mixed case
909 * 128 length unicode.
914 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
915 DEBUG(2,("NT Password did not match for user '%s' ! Defaulting to Lanman\n", user));
917 valid_nt_password = True;
920 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL))
922 if (lp_security() >= SEC_USER)
924 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
926 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
927 return bad_password_error(inbuf,outbuf);
930 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
932 if (Get_Pwnam(user,True))
934 DEBUG(1,("Rejecting user '%s': bad password\n", user));
935 return bad_password_error(inbuf,outbuf);
940 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
941 * Then always map to guest account - as done below.
945 if (*smb_apasswd || !Get_Pwnam(user,True))
946 pstrcpy(user,lp_guestaccount(-1));
947 DEBUG(3,("Registered username %s for guest access\n",user));
952 if (!Get_Pwnam(user,True)) {
953 DEBUG(3,("No such user %s - using guest account\n",user));
954 pstrcpy(user,lp_guestaccount(-1));
958 if (!strequal(user,lp_guestaccount(-1)) &&
959 lp_servicenumber(user) < 0)
961 int homes = lp_servicenumber(HOMES_NAME);
962 char *home = get_user_home_dir(user);
963 if (homes >= 0 && home)
964 lp_add_home(user,homes,home);
968 /* it's ok - setup a reply */
969 if (Protocol < PROTOCOL_NT1) {
970 set_message(outbuf,3,0,True);
973 set_message(outbuf,3,3,True);
975 pstrcpy(p,"Unix"); p = skip_string(p,1);
976 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
977 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
978 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
979 /* perhaps grab OS version here?? */
982 /* Set the correct uid in the outgoing and incoming packets
983 We will use this on future requests to determine which
984 user we should become.
987 const struct passwd *pw = Get_Pwnam(user,False);
989 DEBUG(1,("Username %s is invalid on this system\n",user));
990 return bad_password_error(inbuf,outbuf);
997 SSVAL(outbuf,smb_vwv2,1);
999 /* register the name and uid as being validated, so further connections
1000 to a uid can get through without a password, on the same VC */
1001 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
1003 SSVAL(outbuf,smb_uid,sess_vuid);
1004 SSVAL(inbuf,smb_uid,sess_vuid);
1006 if (!done_sesssetup)
1007 max_send = MIN(max_send,smb_bufsize);
1009 DEBUG(6,("Client requested max send size of %d\n", max_send));
1011 done_sesssetup = True;
1013 return chain_reply(inbuf,outbuf,length,bufsize);
1017 /****************************************************************************
1019 ****************************************************************************/
1020 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1026 BOOL bad_path = False;
1029 pstrcpy(name,smb_buf(inbuf) + 1);
1031 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1033 unix_convert(name,conn,0,&bad_path,&st);
1035 mode = SVAL(inbuf,smb_vwv0);
1037 if (check_name(name,conn)) {
1039 ok = S_ISDIR(st.st_mode);
1041 ok = vfs_directory_exist(conn,name,NULL);
1046 /* We special case this - as when a Windows machine
1047 is parsing a path is steps through the components
1048 one at a time - if a component fails it expects
1049 ERRbadpath, not ERRbadfile.
1053 unix_ERR_class = ERRDOS;
1054 unix_ERR_code = ERRbadpath;
1058 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1059 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1060 (get_remote_arch() == RA_WINNT))
1062 unix_ERR_class = ERRDOS;
1063 unix_ERR_code = ERRbaddirectory;
1067 return(UNIXERROR(ERRDOS,ERRbadpath));
1070 outsize = set_message(outbuf,0,0,True);
1072 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1078 /****************************************************************************
1080 ****************************************************************************/
1081 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1085 SMB_STRUCT_STAT sbuf;
1090 BOOL bad_path = False;
1092 pstrcpy(fname,smb_buf(inbuf) + 1);
1094 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1096 /* if((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && dfs_redirect(fname,conn)) return(dfs_path_error(inbuf,outbuf));
1098 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1099 under WfWg - weird! */
1102 mode = aHIDDEN | aDIR;
1103 if (!CAN_WRITE(conn)) mode |= aRONLY;
1110 unix_convert(fname,conn,0,&bad_path,&sbuf);
1111 if (check_name(fname,conn))
1113 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
1115 mode = dos_mode(conn,fname,&sbuf);
1116 size = sbuf.st_size;
1117 mtime = sbuf.st_mtime;
1123 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1129 if((errno == ENOENT) && bad_path)
1131 unix_ERR_class = ERRDOS;
1132 unix_ERR_code = ERRbadpath;
1135 return(UNIXERROR(ERRDOS,ERRbadfile));
1138 outsize = set_message(outbuf,10,0,True);
1140 SSVAL(outbuf,smb_vwv0,mode);
1141 if(lp_dos_filetime_resolution(SNUM(conn)) )
1142 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1144 put_dos_date3(outbuf,smb_vwv1,mtime);
1145 SIVAL(outbuf,smb_vwv3,(uint32)size);
1147 if (Protocol >= PROTOCOL_NT1) {
1148 char *p = strrchr(fname,'/');
1149 uint16 flg2 = SVAL(outbuf,smb_flg2);
1151 if (!is_8_3(fname, True))
1152 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1155 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1161 /****************************************************************************
1163 ****************************************************************************/
1164 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1172 BOOL bad_path = False;
1174 pstrcpy(fname,smb_buf(inbuf) + 1);
1175 unix_convert(fname,conn,0,&bad_path,&st);
1177 mode = SVAL(inbuf,smb_vwv0);
1178 mtime = make_unix_date3(inbuf+smb_vwv1);
1180 if (VALID_STAT_OF_DIR(st) || vfs_directory_exist(conn, fname, NULL))
1182 if (check_name(fname,conn))
1183 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1185 ok = set_filetime(conn,fname,mtime);
1189 if((errno == ENOENT) && bad_path)
1191 unix_ERR_class = ERRDOS;
1192 unix_ERR_code = ERRbadpath;
1195 return(UNIXERROR(ERRDOS,ERRnoaccess));
1198 outsize = set_message(outbuf,0,0,True);
1200 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1206 /****************************************************************************
1208 ****************************************************************************/
1209 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1212 SMB_BIG_UINT dfree,dsize,bsize;
1214 conn->vfs_ops.disk_free(".",True,&bsize,&dfree,&dsize);
1216 outsize = set_message(outbuf,5,0,True);
1218 SSVAL(outbuf,smb_vwv0,dsize);
1219 SSVAL(outbuf,smb_vwv1,bsize/512);
1220 SSVAL(outbuf,smb_vwv2,512);
1221 SSVAL(outbuf,smb_vwv3,dfree);
1223 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1229 /****************************************************************************
1231 Can be called from SMBsearch, SMBffirst or SMBfunique.
1232 ****************************************************************************/
1233 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1244 BOOL finished = False;
1253 BOOL check_descend = False;
1254 BOOL expect_close = False;
1255 BOOL can_open = True;
1256 BOOL bad_path = False;
1258 *mask = *directory = *fname = 0;
1260 /* If we were called as SMBffirst then we must expect close. */
1261 if(CVAL(inbuf,smb_com) == SMBffirst)
1262 expect_close = True;
1264 outsize = set_message(outbuf,1,3,True);
1265 maxentries = SVAL(inbuf,smb_vwv0);
1266 dirtype = SVAL(inbuf,smb_vwv1);
1267 path = smb_buf(inbuf) + 1;
1268 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1271 /* dirtype &= ~aDIR; */
1273 DEBUG(5,("reply_search: path=%s status_len=%d\n",path,status_len));
1276 if (status_len == 0)
1280 pstrcpy(directory,smb_buf(inbuf)+1);
1281 pstrcpy(dir2,smb_buf(inbuf)+1);
1282 unix_convert(directory,conn,0,&bad_path,NULL);
1285 if (!check_name(directory,conn))
1288 p = strrchr(dir2,'/');
1300 p = strrchr(directory,'/');
1306 if (strlen(directory) == 0)
1307 pstrcpy(directory,"./");
1308 memset((char *)status,'\0',21);
1309 CVAL(status,0) = dirtype;
1313 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1314 memcpy(mask,status+1,11);
1316 dirtype = CVAL(status,0) & 0x1F;
1317 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1320 string_set(&conn->dirpath,dptr_path(dptr_num));
1321 if (!case_sensitive)
1325 /* turn strings of spaces into a . */
1327 trim_string(mask,NULL," ");
1328 if ((p = strrchr(mask,' ')))
1333 trim_string(mask,NULL," ");
1339 /* Convert the formatted mask. (This code lives in trans2.c) */
1347 if((skip = get_character_len( *p )) != 0 )
1353 if (*p != '?' && *p != '*' && !isdoschar(*p))
1355 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1363 if (!strchr(mask,'.') && strlen(mask)>8)
1366 fstrcpy(tmp,&mask[8]);
1372 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1376 p = smb_buf(outbuf) + 3;
1380 if (status_len == 0)
1382 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1387 if((errno == ENOENT) && bad_path)
1389 unix_ERR_class = ERRDOS;
1390 unix_ERR_code = ERRbadpath;
1392 return (UNIXERROR(ERRDOS,ERRnofids));
1394 return(ERROR(ERRDOS,ERRnofids));
1398 DEBUG(4,("dptr_num is %d\n",dptr_num));
1402 if ((dirtype&0x1F) == aVOLID)
1404 memcpy(p,status,21);
1405 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1406 dptr_fill(p+12,dptr_num);
1407 if (dptr_zero(p+12) && (status_len==0))
1411 p += DIR_STRUCT_SIZE;
1415 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1416 conn->dirpath,lp_dontdescend(SNUM(conn))));
1417 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1418 check_descend = True;
1420 for (i=numentries;(i<maxentries) && !finished;i++)
1423 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1426 memcpy(p,status,21);
1427 make_dir_struct(p,mask,fname,size,mode,date);
1428 dptr_fill(p+12,dptr_num);
1431 p += DIR_STRUCT_SIZE;
1440 if (numentries == 0 || !ok)
1442 CVAL(outbuf,smb_rcls) = ERRDOS;
1443 SSVAL(outbuf,smb_err,ERRnofiles);
1444 dptr_close(&dptr_num);
1447 /* If we were called as SMBffirst with smb_search_id == NULL
1448 and no entries were found then return error and close dirptr
1451 if(ok && expect_close && numentries == 0 && status_len == 0)
1453 CVAL(outbuf,smb_rcls) = ERRDOS;
1454 SSVAL(outbuf,smb_err,ERRnofiles);
1455 /* Also close the dptr - we know it's gone */
1456 dptr_close(&dptr_num);
1459 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1460 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1461 dptr_close(&dptr_num);
1463 SSVAL(outbuf,smb_vwv0,numentries);
1464 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1465 CVAL(smb_buf(outbuf),0) = 5;
1466 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1468 if (Protocol >= PROTOCOL_NT1) {
1469 uint16 flg2 = SVAL(outbuf,smb_flg2);
1470 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1473 outsize += DIR_STRUCT_SIZE*numentries;
1474 smb_setlen(outbuf,outsize - 4);
1476 if ((! *directory) && dptr_path(dptr_num))
1477 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1479 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1480 smb_fn_name(CVAL(inbuf,smb_com)),
1481 mask, directory, dirtype, numentries, maxentries ) );
1487 /****************************************************************************
1488 reply to a fclose (stop directory search)
1489 ****************************************************************************/
1490 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1498 outsize = set_message(outbuf,1,0,True);
1499 path = smb_buf(inbuf) + 1;
1500 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1503 if (status_len == 0)
1504 return(ERROR(ERRSRV,ERRsrverror));
1506 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1508 if(dptr_fetch(status+12,&dptr_num)) {
1509 /* Close the dptr - we know it's gone */
1510 dptr_close(&dptr_num);
1513 SSVAL(outbuf,smb_vwv0,0);
1515 DEBUG(3,("search close\n"));
1521 /****************************************************************************
1523 ****************************************************************************/
1525 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1535 SMB_STRUCT_STAT sbuf;
1536 BOOL bad_path = False;
1538 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1540 share_mode = SVAL(inbuf,smb_vwv0);
1542 pstrcpy(fname,smb_buf(inbuf)+1);
1544 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1546 unix_convert(fname,conn,0,&bad_path,NULL);
1550 return(ERROR(ERRSRV,ERRnofids));
1552 if (!check_name(fname,conn))
1554 if((errno == ENOENT) && bad_path)
1556 unix_ERR_class = ERRDOS;
1557 unix_ERR_code = ERRbadpath;
1560 return(UNIXERROR(ERRDOS,ERRnoaccess));
1563 unixmode = unix_mode(conn,aARCH,fname);
1565 open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1566 unixmode, oplock_request,&rmode,NULL);
1570 if((errno == ENOENT) && bad_path)
1572 unix_ERR_class = ERRDOS;
1573 unix_ERR_code = ERRbadpath;
1576 return(UNIXERROR(ERRDOS,ERRnoaccess));
1579 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1580 close_file(fsp,False);
1581 return(ERROR(ERRDOS,ERRnoaccess));
1584 size = sbuf.st_size;
1585 fmode = dos_mode(conn,fname,&sbuf);
1586 mtime = sbuf.st_mtime;
1589 DEBUG(3,("attempt to open a directory %s\n",fname));
1590 close_file(fsp,False);
1591 return(ERROR(ERRDOS,ERRnoaccess));
1594 outsize = set_message(outbuf,7,0,True);
1595 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1596 SSVAL(outbuf,smb_vwv1,fmode);
1597 if(lp_dos_filetime_resolution(SNUM(conn)) )
1598 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1600 put_dos_date3(outbuf,smb_vwv2,mtime);
1601 SIVAL(outbuf,smb_vwv4,(uint32)size);
1602 SSVAL(outbuf,smb_vwv6,rmode);
1604 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1605 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1608 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1609 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1614 /****************************************************************************
1615 reply to an open and X
1616 ****************************************************************************/
1617 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1620 int smb_mode = SVAL(inbuf,smb_vwv3);
1621 int smb_attr = SVAL(inbuf,smb_vwv5);
1622 /* Breakout the oplock request bits so we can set the
1623 reply bits separately. */
1624 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1625 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1626 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1628 int open_flags = SVAL(inbuf,smb_vwv2);
1629 int smb_sattr = SVAL(inbuf,smb_vwv4);
1630 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1632 int smb_ofun = SVAL(inbuf,smb_vwv8);
1635 int fmode=0,mtime=0,rmode=0;
1636 SMB_STRUCT_STAT sbuf;
1638 BOOL bad_path = False;
1641 /* If it's an IPC, pass off the pipe handler. */
1642 if (IS_IPC(conn) && lp_nt_pipe_support())
1643 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1645 /* XXXX we need to handle passed times, sattr and flags */
1647 pstrcpy(fname,smb_buf(inbuf));
1649 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1651 unix_convert(fname,conn,0,&bad_path,NULL);
1655 return(ERROR(ERRSRV,ERRnofids));
1657 if (!check_name(fname,conn))
1659 if((errno == ENOENT) && bad_path)
1661 unix_ERR_class = ERRDOS;
1662 unix_ERR_code = ERRbadpath;
1665 return(UNIXERROR(ERRDOS,ERRnoaccess));
1668 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1670 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1671 oplock_request, &rmode,&smb_action);
1675 if((errno == ENOENT) && bad_path)
1677 unix_ERR_class = ERRDOS;
1678 unix_ERR_code = ERRbadpath;
1681 return(UNIXERROR(ERRDOS,ERRnoaccess));
1684 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1685 close_file(fsp,False);
1686 return(ERROR(ERRDOS,ERRnoaccess));
1689 size = sbuf.st_size;
1690 fmode = dos_mode(conn,fname,&sbuf);
1691 mtime = sbuf.st_mtime;
1693 close_file(fsp,False);
1694 return(ERROR(ERRDOS,ERRnoaccess));
1697 /* If the caller set the extended oplock request bit
1698 and we granted one (by whatever means) - set the
1699 correct bit for extended oplock reply.
1702 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1703 smb_action |= EXTENDED_OPLOCK_GRANTED;
1706 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1707 smb_action |= EXTENDED_OPLOCK_GRANTED;
1710 /* If the caller set the core oplock request bit
1711 and we granted one (by whatever means) - set the
1712 correct bit for core oplock reply.
1715 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1716 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1719 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1720 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1723 set_message(outbuf,15,0,True);
1724 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1725 SSVAL(outbuf,smb_vwv3,fmode);
1726 if(lp_dos_filetime_resolution(SNUM(conn)) )
1727 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1729 put_dos_date3(outbuf,smb_vwv4,mtime);
1730 SIVAL(outbuf,smb_vwv6,(uint32)size);
1731 SSVAL(outbuf,smb_vwv8,rmode);
1732 SSVAL(outbuf,smb_vwv11,smb_action);
1734 return chain_reply(inbuf,outbuf,length,bufsize);
1738 /****************************************************************************
1739 reply to a SMBulogoffX
1740 ****************************************************************************/
1741 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1743 uint16 vuid = SVAL(inbuf,smb_uid);
1744 user_struct *vuser = get_valid_user_struct(vuid);
1747 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1750 /* in user level security we are supposed to close any files
1751 open by this user */
1752 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1753 file_close_user(vuid);
1756 invalidate_vuid(vuid);
1758 set_message(outbuf,2,0,True);
1760 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1762 return chain_reply(inbuf,outbuf,length,bufsize);
1766 /****************************************************************************
1767 reply to a mknew or a create
1768 ****************************************************************************/
1769 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1777 BOOL bad_path = False;
1779 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1781 com = SVAL(inbuf,smb_com);
1783 createmode = SVAL(inbuf,smb_vwv0);
1784 pstrcpy(fname,smb_buf(inbuf)+1);
1786 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1788 unix_convert(fname,conn,0,&bad_path,NULL);
1790 if (createmode & aVOLID)
1792 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1795 unixmode = unix_mode(conn,createmode,fname);
1799 return(ERROR(ERRSRV,ERRnofids));
1801 if (!check_name(fname,conn))
1803 if((errno == ENOENT) && bad_path)
1805 unix_ERR_class = ERRDOS;
1806 unix_ERR_code = ERRbadpath;
1809 return(UNIXERROR(ERRDOS,ERRnoaccess));
1814 /* We should fail if file exists. */
1815 ofun = FILE_CREATE_IF_NOT_EXIST;
1819 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1820 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1823 /* Open file in dos compatibility share mode. */
1824 open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1825 ofun, unixmode, oplock_request, NULL, NULL);
1829 if((errno == ENOENT) && bad_path)
1831 unix_ERR_class = ERRDOS;
1832 unix_ERR_code = ERRbadpath;
1835 return(UNIXERROR(ERRDOS,ERRnoaccess));
1838 outsize = set_message(outbuf,1,0,True);
1839 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1841 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1842 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1845 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1846 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1848 DEBUG( 2, ( "new file %s\n", fname ) );
1849 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1850 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1856 /****************************************************************************
1857 reply to a create temporary file
1858 ****************************************************************************/
1859 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1866 BOOL bad_path = False;
1868 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1870 createmode = SVAL(inbuf,smb_vwv0);
1871 pstrcpy(fname,smb_buf(inbuf)+1);
1872 pstrcat(fname,"/TMXXXXXX");
1874 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1876 unix_convert(fname,conn,0,&bad_path,NULL);
1878 unixmode = unix_mode(conn,createmode,fname);
1882 return(ERROR(ERRSRV,ERRnofids));
1884 if (!check_name(fname,conn))
1886 if((errno == ENOENT) && bad_path)
1888 unix_ERR_class = ERRDOS;
1889 unix_ERR_code = ERRbadpath;
1892 return(UNIXERROR(ERRDOS,ERRnoaccess));
1895 pstrcpy(fname2,(char *)smbd_mktemp(fname));
1897 /* Open file in dos compatibility share mode. */
1898 /* We should fail if file exists. */
1899 open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1900 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1904 if((errno == ENOENT) && bad_path)
1906 unix_ERR_class = ERRDOS;
1907 unix_ERR_code = ERRbadpath;
1910 return(UNIXERROR(ERRDOS,ERRnoaccess));
1913 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1914 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1915 CVAL(smb_buf(outbuf),0) = 4;
1916 pstrcpy(smb_buf(outbuf) + 1,fname2);
1918 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1919 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1922 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1923 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1925 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1926 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1927 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1933 /*******************************************************************
1934 check if a user is allowed to delete a file
1935 ********************************************************************/
1936 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1938 SMB_STRUCT_STAT sbuf;
1941 if (!CAN_WRITE(conn)) return(False);
1943 if (conn->vfs_ops.lstat(dos_to_unix(fname,False),&sbuf) != 0) return(False);
1944 fmode = dos_mode(conn,fname,&sbuf);
1945 if (fmode & aDIR) return(False);
1946 if (!lp_delete_readonly(SNUM(conn))) {
1947 if (fmode & aRONLY) return(False);
1949 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1951 if (!check_file_sharing(conn,fname,False)) return(False);
1955 /****************************************************************************
1957 ****************************************************************************/
1959 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1968 int error = ERRnoaccess;
1971 BOOL bad_path = False;
1974 *directory = *mask = 0;
1976 dirtype = SVAL(inbuf,smb_vwv0);
1978 pstrcpy(name,smb_buf(inbuf) + 1);
1980 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1982 DEBUG(3,("reply_unlink : %s\n",name));
1984 rc = unix_convert(name,conn,0,&bad_path,NULL);
1986 p = strrchr(name,'/');
1988 pstrcpy(directory,"./");
1992 pstrcpy(directory,name);
1997 * We should only check the mangled cache
1998 * here if unix_convert failed. This means
1999 * that the path in 'mask' doesn't exist
2000 * on the file system and so we need to look
2001 * for a possible mangle. This patch from
2002 * Tine Smukavec <valentin.smukavec@hermes.si>.
2005 if (!rc && is_mangled(mask))
2006 check_mangled_cache( mask );
2008 has_wild = strchr(mask,'*') || strchr(mask,'?');
2011 pstrcat(directory,"/");
2012 pstrcat(directory,mask);
2013 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
2016 exists = vfs_file_exist(conn,directory,NULL);
2018 void *dirptr = NULL;
2021 if (check_name(directory,conn))
2022 dirptr = OpenDir(conn, directory, True);
2024 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2025 the pattern matches against the long name, otherwise the short name
2026 We don't implement this yet XXXX
2033 if (strequal(mask,"????????.???"))
2036 while ((dname = ReadDirName(dirptr)))
2039 pstrcpy(fname,dname);
2041 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2043 error = ERRnoaccess;
2044 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2045 if (!can_delete(fname,conn,dirtype)) continue;
2046 if (!conn->vfs_ops.unlink(dos_to_unix(fname,False))) count++;
2047 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
2055 return(ERROR(ERRDOS,error));
2058 if((errno == ENOENT) && bad_path)
2060 unix_ERR_class = ERRDOS;
2061 unix_ERR_code = ERRbadpath;
2063 return(UNIXERROR(ERRDOS,error));
2067 outsize = set_message(outbuf,0,0,True);
2073 /****************************************************************************
2074 reply to a readbraw (core+ protocol)
2075 ****************************************************************************/
2077 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2079 size_t maxcount,mincount;
2082 char *header = outbuf;
2087 * Special check if an oplock break has been issued
2088 * and the readraw request croses on the wire, we must
2089 * return a zero length response here.
2092 if(global_oplock_break)
2094 _smb_setlen(header,0);
2095 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
2096 DEBUG(5,("readbraw - oplock break finished\n"));
2100 fsp = file_fsp(inbuf,smb_vwv0);
2102 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2104 * fsp could be NULL here so use the value from the packet. JRA.
2106 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2107 _smb_setlen(header,0);
2108 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
2112 CHECK_FSP(fsp,conn);
2114 flush_write_cache(fsp, READRAW_FLUSH);
2116 startpos = IVAL(inbuf,smb_vwv1);
2117 if(CVAL(inbuf,smb_wct) == 10) {
2119 * This is a large offset (64 bit) read.
2121 #ifdef LARGE_SMB_OFF_T
2123 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2125 #else /* !LARGE_SMB_OFF_T */
2128 * Ensure we haven't been sent a >32 bit offset.
2131 if(IVAL(inbuf,smb_vwv8) != 0) {
2132 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2133 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2134 _smb_setlen(header,0);
2135 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
2139 #endif /* LARGE_SMB_OFF_T */
2142 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2143 (double)startpos ));
2144 _smb_setlen(header,0);
2145 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
2149 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2150 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2152 /* ensure we don't overrun the packet size */
2153 maxcount = MIN(65535,maxcount);
2154 maxcount = MAX(mincount,maxcount);
2156 if (!is_locked(fsp,conn,maxcount,startpos, READ_LOCK))
2158 SMB_OFF_T size = fsp->size;
2159 SMB_OFF_T sizeneeded = startpos + maxcount;
2161 if (size < sizeneeded)
2164 if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&st) == 0)
2166 if (!fsp->can_write)
2170 nread = MIN(maxcount,(size - startpos));
2173 if (nread < mincount)
2176 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2177 fsp->fnum, (double)startpos,
2178 (int)maxcount, (int)mincount, (int)nread ) );
2182 BOOL seek_fail = False;
2184 _smb_setlen(header,nread);
2186 #if USE_READ_PREDICTION
2187 if (!fsp->can_write)
2188 predict = read_predict(fsp, fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
2189 #endif /* USE_READ_PREDICTION */
2191 if ((nread-predict) > 0) {
2192 if(conn->vfs_ops.seek(fsp,startpos + predict) == -1) {
2193 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2200 ret = (ssize_t)vfs_transfer_file(-1, fsp->fd_ptr->fd, Client, NULL,
2201 (SMB_OFF_T)(nread-predict),header,4+predict,
2206 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2207 fsp->fsp_name,startpos,nread,ret));
2209 #else /* UNSAFE_READRAW */
2210 ret = read_file(fsp,header+4,startpos,nread);
2211 if (ret < mincount) ret = 0;
2213 _smb_setlen(header,ret);
2214 transfer_file(0,Client,0,header,4+ret,0);
2215 #endif /* UNSAFE_READRAW */
2217 DEBUG(5,("readbraw finished\n"));
2222 /****************************************************************************
2223 reply to a lockread (core+ protocol)
2224 ****************************************************************************/
2225 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2234 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2236 CHECK_FSP(fsp,conn);
2240 numtoread = SVAL(inbuf,smb_vwv1);
2241 startpos = IVAL(inbuf,smb_vwv2);
2243 outsize = set_message(outbuf,5,3,True);
2244 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2245 data = smb_buf(outbuf) + 3;
2248 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2249 * protocol request that predates the read/write lock concept.
2250 * Thus instead of asking for a read lock here we need to ask
2251 * for a write lock. JRA.
2254 if(!do_lock( fsp, conn, numtoread, startpos, WRITE_LOCK, &eclass, &ecode)) {
2255 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2257 * A blocking lock was requested. Package up
2258 * this smb into a queued request and push it
2259 * onto the blocking lock queue.
2261 if(push_blocking_lock_request(inbuf, length, -1, 0))
2264 return (ERROR(eclass,ecode));
2267 nread = read_file(fsp,data,startpos,numtoread);
2270 return(UNIXERROR(ERRDOS,ERRnoaccess));
2273 SSVAL(outbuf,smb_vwv0,nread);
2274 SSVAL(outbuf,smb_vwv5,nread+3);
2275 SSVAL(smb_buf(outbuf),1,nread);
2277 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2278 fsp->fnum, (int)numtoread, (int)nread ) );
2284 /****************************************************************************
2286 ****************************************************************************/
2288 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2295 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2297 CHECK_FSP(fsp,conn);
2301 numtoread = SVAL(inbuf,smb_vwv1);
2302 startpos = IVAL(inbuf,smb_vwv2);
2304 outsize = set_message(outbuf,5,3,True);
2305 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2306 data = smb_buf(outbuf) + 3;
2308 if (is_locked(fsp,conn,numtoread,startpos, READ_LOCK))
2309 return(ERROR(ERRDOS,ERRlock));
2312 nread = read_file(fsp,data,startpos,numtoread);
2315 return(UNIXERROR(ERRDOS,ERRnoaccess));
2318 SSVAL(outbuf,smb_vwv0,nread);
2319 SSVAL(outbuf,smb_vwv5,nread+3);
2320 CVAL(smb_buf(outbuf),0) = 1;
2321 SSVAL(smb_buf(outbuf),1,nread);
2323 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2324 fsp->fnum, (int)numtoread, (int)nread ) );
2330 /****************************************************************************
2331 reply to a read and X
2332 ****************************************************************************/
2333 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2335 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2336 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2337 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2338 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2342 /* If it's an IPC, pass off the pipe handler. */
2344 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2346 CHECK_FSP(fsp,conn);
2350 set_message(outbuf,12,0,True);
2351 data = smb_buf(outbuf);
2353 if(CVAL(inbuf,smb_wct) == 12) {
2354 #ifdef LARGE_SMB_OFF_T
2356 * This is a large offset (64 bit) read.
2358 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2360 #else /* !LARGE_SMB_OFF_T */
2363 * Ensure we haven't been sent a >32 bit offset.
2366 if(IVAL(inbuf,smb_vwv10) != 0) {
2367 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2368 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2369 return(ERROR(ERRDOS,ERRbadaccess));
2372 #endif /* LARGE_SMB_OFF_T */
2376 if (is_locked(fsp,conn,smb_maxcnt,startpos, READ_LOCK))
2377 return(ERROR(ERRDOS,ERRlock));
2378 nread = read_file(fsp,data,startpos,smb_maxcnt);
2381 return(UNIXERROR(ERRDOS,ERRnoaccess));
2383 SSVAL(outbuf,smb_vwv5,nread);
2384 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2385 SSVAL(smb_buf(outbuf),-2,nread);
2387 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2388 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2390 return chain_reply(inbuf,outbuf,length,bufsize);
2393 /****************************************************************************
2394 reply to a writebraw (core+ or LANMAN1.0 protocol)
2395 ****************************************************************************/
2397 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2400 ssize_t total_written=0;
2401 size_t numtowrite=0;
2406 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2409 CHECK_FSP(fsp,conn);
2413 tcount = IVAL(inbuf,smb_vwv1);
2414 startpos = IVAL(inbuf,smb_vwv3);
2415 write_through = BITSETW(inbuf+smb_vwv7,0);
2417 /* We have to deal with slightly different formats depending
2418 on whether we are using the core+ or lanman1.0 protocol */
2419 if(Protocol <= PROTOCOL_COREPLUS) {
2420 numtowrite = SVAL(smb_buf(inbuf),-2);
2421 data = smb_buf(inbuf);
2423 numtowrite = SVAL(inbuf,smb_vwv10);
2424 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2427 /* force the error type */
2428 CVAL(inbuf,smb_com) = SMBwritec;
2429 CVAL(outbuf,smb_com) = SMBwritec;
2431 if (is_locked(fsp,conn,tcount,startpos, WRITE_LOCK))
2432 return(ERROR(ERRDOS,ERRlock));
2435 nwritten = write_file(fsp,data,startpos,numtowrite);
2437 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2438 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2440 if (nwritten < numtowrite)
2441 return(UNIXERROR(ERRHRD,ERRdiskfull));
2443 total_written = nwritten;
2445 /* Return a message to the redirector to tell it
2446 to send more bytes */
2447 CVAL(outbuf,smb_com) = SMBwritebraw;
2448 SSVALS(outbuf,smb_vwv0,-1);
2449 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2450 send_smb(Client,outbuf);
2452 /* Now read the raw data into the buffer and write it */
2453 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2454 exit_server("secondary writebraw failed");
2457 /* Even though this is not an smb message, smb_len
2458 returns the generic length of an smb message */
2459 numtowrite = smb_len(inbuf);
2461 if (tcount > nwritten+numtowrite) {
2462 DEBUG(3,("Client overestimated the write %d %d %d\n",
2463 (int)tcount,(int)nwritten,(int)numtowrite));
2466 nwritten = vfs_transfer_file(Client, NULL, -1, fsp,
2467 (SMB_OFF_T)numtowrite,NULL,0,
2469 total_written += nwritten;
2471 /* Set up outbuf to return the correct return */
2472 outsize = set_message(outbuf,1,0,True);
2473 CVAL(outbuf,smb_com) = SMBwritec;
2474 SSVAL(outbuf,smb_vwv0,total_written);
2476 if (nwritten < (ssize_t)numtowrite) {
2477 CVAL(outbuf,smb_rcls) = ERRHRD;
2478 SSVAL(outbuf,smb_err,ERRdiskfull);
2481 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2482 lp_strict_sync(SNUM(conn)))
2483 conn->vfs_ops.fsync(fsp->fd_ptr->fd);
2485 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2486 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2488 /* we won't return a status if write through is not selected - this
2489 follows what WfWg does */
2490 if (!write_through && total_written==tcount)
2496 /****************************************************************************
2497 reply to a writeunlock (core+)
2498 ****************************************************************************/
2500 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2502 ssize_t nwritten = -1;
2508 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2511 CHECK_FSP(fsp,conn);
2515 numtowrite = SVAL(inbuf,smb_vwv1);
2516 startpos = IVAL(inbuf,smb_vwv2);
2517 data = smb_buf(inbuf) + 3;
2519 if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK))
2520 return(ERROR(ERRDOS,ERRlock));
2522 /* The special X/Open SMB protocol handling of
2523 zero length writes is *NOT* done for
2528 nwritten = write_file(fsp,data,startpos,numtowrite);
2530 if (lp_syncalways(SNUM(conn)))
2531 conn->vfs_ops.fsync(fsp->fd_ptr->fd);
2533 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2534 return(UNIXERROR(ERRDOS,ERRnoaccess));
2536 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2537 return(ERROR(eclass,ecode));
2539 outsize = set_message(outbuf,1,0,True);
2541 SSVAL(outbuf,smb_vwv0,nwritten);
2543 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2544 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2549 /****************************************************************************
2551 ****************************************************************************/
2552 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2555 ssize_t nwritten = -1;
2558 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2561 /* If it's an IPC, pass off the pipe handler. */
2563 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2565 CHECK_FSP(fsp,conn);
2569 numtowrite = SVAL(inbuf,smb_vwv1);
2570 startpos = IVAL(inbuf,smb_vwv2);
2571 data = smb_buf(inbuf) + 3;
2573 if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK))
2574 return(ERROR(ERRDOS,ERRlock));
2576 /* X/Open SMB protocol says that if smb_vwv1 is
2577 zero then the file size should be extended or
2578 truncated to the size given in smb_vwv[2-3] */
2579 if(numtowrite == 0) {
2580 if((nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos)) >= 0) /* tpot vfs */
2581 set_filelen_write_cache(fsp, startpos);
2583 nwritten = write_file(fsp,data,startpos,numtowrite);
2585 if (lp_syncalways(SNUM(conn)))
2586 conn->vfs_ops.fsync(fsp->fd_ptr->fd);
2588 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2589 return(UNIXERROR(ERRDOS,ERRnoaccess));
2591 outsize = set_message(outbuf,1,0,True);
2593 SSVAL(outbuf,smb_vwv0,nwritten);
2595 if (nwritten < (ssize_t)numtowrite) {
2596 CVAL(outbuf,smb_rcls) = ERRHRD;
2597 SSVAL(outbuf,smb_err,ERRdiskfull);
2600 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2601 fsp->fnum, (int)numtowrite, (int)nwritten));
2607 /****************************************************************************
2608 reply to a write and X
2609 ****************************************************************************/
2610 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2612 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2613 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2614 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2615 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2616 ssize_t nwritten = -1;
2617 int smb_doff = SVAL(inbuf,smb_vwv11);
2620 /* If it's an IPC, pass off the pipe handler. */
2622 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2624 CHECK_FSP(fsp,conn);
2628 data = smb_base(inbuf) + smb_doff;
2630 if(CVAL(inbuf,smb_wct) == 14) {
2631 #ifdef LARGE_SMB_OFF_T
2633 * This is a large offset (64 bit) write.
2635 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2637 #else /* !LARGE_SMB_OFF_T */
2640 * Ensure we haven't been sent a >32 bit offset.
2643 if(IVAL(inbuf,smb_vwv12) != 0) {
2644 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2645 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2646 return(ERROR(ERRDOS,ERRbadaccess));
2649 #endif /* LARGE_SMB_OFF_T */
2652 if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK))
2653 return(ERROR(ERRDOS,ERRlock));
2655 /* X/Open SMB protocol says that, unlike SMBwrite
2656 if the length is zero then NO truncation is
2657 done, just a write of zero. To truncate a file,
2662 nwritten = write_file(fsp,data,startpos,numtowrite);
2664 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2665 return(UNIXERROR(ERRDOS,ERRnoaccess));
2667 set_message(outbuf,6,0,True);
2669 SSVAL(outbuf,smb_vwv2,nwritten);
2671 if (nwritten < (ssize_t)numtowrite) {
2672 CVAL(outbuf,smb_rcls) = ERRHRD;
2673 SSVAL(outbuf,smb_err,ERRdiskfull);
2676 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2677 fsp->fnum, (int)numtowrite, (int)nwritten));
2679 if (lp_syncalways(SNUM(conn)) || write_through)
2680 conn->vfs_ops.fsync(fsp->fd_ptr->fd);
2682 return chain_reply(inbuf,outbuf,length,bufsize);
2686 /****************************************************************************
2688 ****************************************************************************/
2690 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2696 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2698 CHECK_FSP(fsp,conn);
2701 flush_write_cache(fsp, SEEK_FLUSH);
2703 mode = SVAL(inbuf,smb_vwv1) & 3;
2704 startpos = IVALS(inbuf,smb_vwv2);
2707 case 0: umode = SEEK_SET; break;
2708 case 1: umode = SEEK_CUR; break;
2709 case 2: umode = SEEK_END; break;
2711 umode = SEEK_SET; break;
2714 if((res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,startpos,umode)) == -1) {
2716 * Check for the special case where a seek before the start
2717 * of the file sets the offset to zero. Added in the CIFS spec,
2721 if(errno == EINVAL) {
2722 SMB_OFF_T current_pos = startpos;
2724 if(umode == SEEK_CUR) {
2726 if((current_pos = conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1)
2727 return(UNIXERROR(ERRDOS,ERRnoaccess));
2729 current_pos += startpos;
2731 } else if (umode == SEEK_END) {
2733 SMB_STRUCT_STAT sbuf;
2735 if(conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf) == -1)
2736 return(UNIXERROR(ERRDOS,ERRnoaccess));
2738 current_pos += sbuf.st_size;
2742 res = conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_SET);
2746 return(UNIXERROR(ERRDOS,ERRnoaccess));
2751 outsize = set_message(outbuf,2,0,True);
2752 SIVAL(outbuf,smb_vwv0,res);
2754 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2755 fsp->fnum, (double)startpos, (double)res, mode));
2760 /****************************************************************************
2762 ****************************************************************************/
2764 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2766 int outsize = set_message(outbuf,0,0,True);
2767 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2770 CHECK_FSP(fsp,conn);
2775 file_sync_all(conn);
2777 conn->vfs_ops.fsync(fsp->fd_ptr->fd);
2780 DEBUG(3,("flush\n"));
2785 /****************************************************************************
2787 ****************************************************************************/
2788 int reply_exit(connection_struct *conn,
2789 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2791 int outsize = set_message(outbuf,0,0,True);
2792 DEBUG(3,("exit\n"));
2798 /****************************************************************************
2799 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2800 ****************************************************************************/
2801 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2806 int32 eclass = 0, err = 0;
2807 files_struct *fsp = NULL;
2809 outsize = set_message(outbuf,0,0,True);
2811 /* If it's an IPC, pass off to the pipe handler. */
2813 return reply_pipe_close(conn, inbuf,outbuf);
2815 fsp = file_fsp(inbuf,smb_vwv0);
2818 * We can only use CHECK_FSP if we know it's not a directory.
2821 if(!fsp || !fsp->open || (fsp->conn != conn))
2822 return(ERROR(ERRDOS,ERRbadfid));
2824 if(HAS_CACHED_ERROR(fsp)) {
2825 eclass = fsp->wbmpx_ptr->wr_errclass;
2826 err = fsp->wbmpx_ptr->wr_error;
2829 if(fsp->is_directory || fsp->stat_open) {
2831 * Special case - close NT SMB directory or stat file
2834 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2835 close_file(fsp,True);
2838 * Close ordinary file.
2843 * If there was a modify time outstanding,
2844 * try and set it here.
2846 if(fsp->pending_modtime)
2847 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2850 * Now take care of any time sent in the close.
2852 mtime = make_unix_date3(inbuf+smb_vwv1);
2854 /* try and set the date */
2855 set_filetime(conn, fsp->fsp_name,mtime);
2857 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2858 fsp->fd_ptr ? fsp->fd_ptr->fd : -1, fsp->fnum,
2859 conn->num_files_open));
2862 * close_file() returns the unix errno if an error
2863 * was detected on close - normally this is due to
2864 * a disk full error. If not then it was probably an I/O error.
2867 if((close_err = close_file(fsp,True)) != 0) {
2869 return (UNIXERROR(ERRHRD,ERRgeneral));
2873 /* We have a cached error */
2875 return(ERROR(eclass,err));
2881 /****************************************************************************
2882 reply to a writeclose (Core+ protocol)
2883 ****************************************************************************/
2885 int reply_writeclose(connection_struct *conn,
2886 char *inbuf,char *outbuf, int size, int dum_buffsize)
2889 ssize_t nwritten = -1;
2895 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2897 CHECK_FSP(fsp,conn);
2901 numtowrite = SVAL(inbuf,smb_vwv1);
2902 startpos = IVAL(inbuf,smb_vwv2);
2903 mtime = make_unix_date3(inbuf+smb_vwv4);
2904 data = smb_buf(inbuf) + 1;
2906 if (is_locked(fsp,conn,numtowrite,startpos, WRITE_LOCK))
2907 return(ERROR(ERRDOS,ERRlock));
2909 nwritten = write_file(fsp,data,startpos,numtowrite);
2911 set_filetime(conn, fsp->fsp_name,mtime);
2913 close_err = close_file(fsp,True);
2915 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2916 fsp->fnum, (int)numtowrite, (int)nwritten,
2917 conn->num_files_open));
2920 return(UNIXERROR(ERRDOS,ERRnoaccess));
2922 if(close_err != 0) {
2924 return(UNIXERROR(ERRHRD,ERRgeneral));
2927 outsize = set_message(outbuf,1,0,True);
2929 SSVAL(outbuf,smb_vwv0,nwritten);
2934 /****************************************************************************
2936 ****************************************************************************/
2937 int reply_lock(connection_struct *conn,
2938 char *inbuf,char *outbuf, int length, int dum_buffsize)
2940 int outsize = set_message(outbuf,0,0,True);
2941 SMB_OFF_T count,offset;
2944 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2946 CHECK_FSP(fsp,conn);
2949 count = IVAL(inbuf,smb_vwv1);
2950 offset = IVAL(inbuf,smb_vwv3);
2952 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2953 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2955 if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) {
2956 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2958 * A blocking lock was requested. Package up
2959 * this smb into a queued request and push it
2960 * onto the blocking lock queue.
2962 if(push_blocking_lock_request(inbuf, length, -1, 0))
2965 return (ERROR(eclass,ecode));
2972 /****************************************************************************
2974 ****************************************************************************/
2975 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2977 int outsize = set_message(outbuf,0,0,True);
2978 SMB_OFF_T count,offset;
2981 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2983 CHECK_FSP(fsp,conn);
2986 count = IVAL(inbuf,smb_vwv1);
2987 offset = IVAL(inbuf,smb_vwv3);
2989 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2990 return (ERROR(eclass,ecode));
2992 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2993 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2999 /****************************************************************************
3001 ****************************************************************************/
3002 int reply_tdis(connection_struct *conn,
3003 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3005 int outsize = set_message(outbuf,0,0,True);
3008 vuid = SVAL(inbuf,smb_uid);
3011 DEBUG(4,("Invalid connection in tdis\n"));
3012 return(ERROR(ERRSRV,ERRinvnid));
3017 close_cnum(conn,vuid);
3024 /****************************************************************************
3026 ****************************************************************************/
3027 int reply_echo(connection_struct *conn,
3028 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3030 int smb_reverb = SVAL(inbuf,smb_vwv0);
3032 int data_len = smb_buflen(inbuf);
3033 int outsize = set_message(outbuf,1,data_len,True);
3035 /* copy any incoming data back out */
3037 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3039 if (smb_reverb > 100) {
3040 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3044 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3045 SSVAL(outbuf,smb_vwv0,seq_num);
3047 smb_setlen(outbuf,outsize - 4);
3049 send_smb(Client,outbuf);
3052 DEBUG(3,("echo %d times\n", smb_reverb));
3060 /****************************************************************************
3061 reply to a printopen
3062 ****************************************************************************/
3063 int reply_printopen(connection_struct *conn,
3064 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3071 *fname = *fname2 = 0;
3073 if (!CAN_PRINT(conn))
3074 return(ERROR(ERRDOS,ERRnoaccess));
3079 pstrcpy(s,smb_buf(inbuf)+1);
3082 if (!(isalnum((int)*p) || strchr("._-",*p)))
3087 if (strlen(s) > 10) s[10] = 0;
3089 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
3094 return(ERROR(ERRSRV,ERRnofids));
3096 pstrcpy(fname2,(char *)smbd_mktemp(fname));
3098 if (!check_name(fname2,conn)) {
3100 return(ERROR(ERRDOS,ERRnoaccess));
3103 /* Open for exclusive use, write only. */
3104 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3105 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0,fname2), 0, NULL, NULL);
3109 return(UNIXERROR(ERRDOS,ERRnoaccess));
3112 /* force it to be a print file */
3113 fsp->print_file = True;
3115 outsize = set_message(outbuf,1,0,True);
3116 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3118 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
3119 fname2, fsp->fd_ptr->fd, fsp->fnum));
3125 /****************************************************************************
3126 reply to a printclose
3127 ****************************************************************************/
3128 int reply_printclose(connection_struct *conn,
3129 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3131 int outsize = set_message(outbuf,0,0,True);
3132 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3135 CHECK_FSP(fsp,conn);
3138 if (!CAN_PRINT(conn))
3139 return(ERROR(ERRDOS,ERRnoaccess));
3141 DEBUG(3,("printclose fd=%d fnum=%d\n",
3142 fsp->fd_ptr->fd,fsp->fnum));
3144 close_err = close_file(fsp,True);
3146 if(close_err != 0) {
3148 return(UNIXERROR(ERRHRD,ERRgeneral));
3155 /****************************************************************************
3156 reply to a printqueue
3157 ****************************************************************************/
3158 int reply_printqueue(connection_struct *conn,
3159 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3161 int outsize = set_message(outbuf,2,3,True);
3162 int max_count = SVAL(inbuf,smb_vwv0);
3163 int start_index = SVAL(inbuf,smb_vwv1);
3165 /* we used to allow the client to get the cnum wrong, but that
3166 is really quite gross and only worked when there was only
3167 one printer - I think we should now only accept it if they
3168 get it right (tridge) */
3169 if (!CAN_PRINT(conn))
3170 return(ERROR(ERRDOS,ERRnoaccess));
3172 SSVAL(outbuf,smb_vwv0,0);
3173 SSVAL(outbuf,smb_vwv1,0);
3174 CVAL(smb_buf(outbuf),0) = 1;
3175 SSVAL(smb_buf(outbuf),1,0);
3177 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3178 start_index, max_count));
3181 print_queue_struct *queue = NULL;
3182 char *p = smb_buf(outbuf) + 3;
3183 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
3184 int num_to_get = ABS(max_count);
3185 int first = (max_count>0?start_index:start_index+max_count+1);
3191 num_to_get = MIN(num_to_get,count-first);
3194 for (i=first;i<first+num_to_get;i++) {
3195 put_dos_date2(p,0,queue[i].time);
3196 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3197 SSVAL(p,5,printjob_encode(SNUM(conn),
3199 SIVAL(p,7,queue[i].size);
3201 StrnCpy(p+12,queue[i].user,16);
3206 outsize = set_message(outbuf,2,28*count+3,False);
3207 SSVAL(outbuf,smb_vwv0,count);
3208 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3209 CVAL(smb_buf(outbuf),0) = 1;
3210 SSVAL(smb_buf(outbuf),1,28*count);
3213 if (queue) free(queue);
3215 DEBUG(3,("%d entries returned in queue\n",count));
3222 /****************************************************************************
3223 reply to a printwrite
3224 ****************************************************************************/
3225 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3228 int outsize = set_message(outbuf,0,0,True);
3230 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3232 if (!CAN_PRINT(conn))
3233 return(ERROR(ERRDOS,ERRnoaccess));
3235 CHECK_FSP(fsp,conn);
3239 numtowrite = SVAL(smb_buf(inbuf),1);
3240 data = smb_buf(inbuf) + 3;
3242 if (write_file(fsp,data,-1,numtowrite) != numtowrite)
3243 return(UNIXERROR(ERRDOS,ERRnoaccess));
3245 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3251 /****************************************************************************
3253 ****************************************************************************/
3254 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3257 int outsize,ret= -1;
3258 BOOL bad_path = False;
3260 pstrcpy(directory,smb_buf(inbuf) + 1);
3261 unix_convert(directory,conn,0,&bad_path,NULL);
3263 if (check_name(directory, conn))
3264 ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
3265 unix_mode(conn,aDIR,directory));
3269 if((errno == ENOENT) && bad_path)
3271 unix_ERR_class = ERRDOS;
3272 unix_ERR_code = ERRbadpath;
3274 return(UNIXERROR(ERRDOS,ERRnoaccess));
3277 outsize = set_message(outbuf,0,0,True);
3279 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
3284 /****************************************************************************
3285 Static function used by reply_rmdir to delete an entire directory
3287 ****************************************************************************/
3289 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3293 void *dirptr = OpenDir(NULL, directory, False);
3298 while((dname = ReadDirName(dirptr)))
3303 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3306 /* Construct the full name. */
3307 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3313 pstrcpy(fullname, directory);
3314 pstrcat(fullname, "/");
3315 pstrcat(fullname, dname);
3317 if(conn->vfs_ops.lstat(dos_to_unix(fullname,False), &st) != 0)
3323 if(st.st_mode & S_IFDIR)
3325 if(recursive_rmdir(conn, fullname)!=0)
3330 if(conn->vfs_ops.rmdir(dos_to_unix(fullname,False)) != 0)
3336 else if(conn->vfs_ops.unlink(dos_to_unix(fullname,False)) != 0)
3346 /****************************************************************************
3347 The internals of the rmdir code - called elsewhere.
3348 ****************************************************************************/
3350 BOOL rmdir_internals(connection_struct *conn, char *directory)
3354 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory, False)) == 0);
3355 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3358 * Check to see if the only thing in this directory are
3359 * vetoed files/directories. If so then delete them and
3360 * retry. If we fail to delete any of them (and we *don't*
3361 * do a recursive delete) then fail the rmdir.
3363 BOOL all_veto_files = True;
3365 void *dirptr = OpenDir(conn, directory, False);
3369 int dirpos = TellDir(dirptr);
3370 while ((dname = ReadDirName(dirptr)))
3372 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3374 if(!IS_VETO_PATH(conn, dname))
3376 all_veto_files = False;
3382 SeekDir(dirptr,dirpos);
3383 while ((dname = ReadDirName(dirptr)))
3388 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3391 /* Construct the full name. */
3392 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3397 pstrcpy(fullname, directory);
3398 pstrcat(fullname, "/");
3399 pstrcat(fullname, dname);
3401 if(conn->vfs_ops.lstat(dos_to_unix(fullname, False), &st) != 0)
3403 if(st.st_mode & S_IFDIR)
3405 if(lp_recursive_veto_delete(SNUM(conn)))
3407 if(recursive_rmdir(conn, fullname) != 0)
3410 if(conn->vfs_ops.rmdir(dos_to_unix(fullname, False)) != 0)
3413 else if(conn->vfs_ops.unlink(dos_to_unix(fullname, False)) != 0)
3417 /* Retry the rmdir */
3418 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory, False)) == 0);
3428 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3429 directory,strerror(errno)));
3434 /****************************************************************************
3436 ****************************************************************************/
3438 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3443 BOOL bad_path = False;
3445 pstrcpy(directory,smb_buf(inbuf) + 1);
3447 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3449 unix_convert(directory,conn, NULL,&bad_path,NULL);
3451 if (check_name(directory,conn))
3453 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3454 ok = rmdir_internals(conn, directory);
3459 if((errno == ENOENT) && bad_path)
3461 unix_ERR_class = ERRDOS;
3462 unix_ERR_code = ERRbadpath;
3464 return(UNIXERROR(ERRDOS,ERRbadpath));
3467 outsize = set_message(outbuf,0,0,True);
3469 DEBUG( 3, ( "rmdir %s\n", directory ) );
3475 /*******************************************************************
3476 resolve wildcards in a filename rename
3477 ********************************************************************/
3478 static BOOL resolve_wildcards(char *name1,char *name2)
3480 fstring root1,root2;
3484 name1 = strrchr(name1,'/');
3485 name2 = strrchr(name2,'/');
3487 if (!name1 || !name2) return(False);
3489 fstrcpy(root1,name1);
3490 fstrcpy(root2,name2);
3491 p = strrchr(root1,'.');
3498 p = strrchr(root2,'.');
3530 pstrcpy(name2,root2);
3533 pstrcat(name2,ext2);
3539 /*******************************************************************
3540 check if a user is allowed to rename a file
3541 ********************************************************************/
3542 static BOOL can_rename(char *fname,connection_struct *conn)
3544 SMB_STRUCT_STAT sbuf;
3546 if (!CAN_WRITE(conn)) return(False);
3548 if (conn->vfs_ops.lstat(dos_to_unix(fname,False),&sbuf) != 0) return(False);
3549 if (!check_file_sharing(conn,fname,True)) return(False);
3554 /****************************************************************************
3555 The guts of the rename command, split out so it may be called by the NT SMB
3557 ****************************************************************************/
3558 int rename_internals(connection_struct *conn,
3559 char *inbuf, char *outbuf, char *name,
3560 char *newname, BOOL replace_if_exists)
3564 pstring newname_last_component;
3567 BOOL bad_path1 = False;
3568 BOOL bad_path2 = False;
3570 int error = ERRnoaccess;
3575 *directory = *mask = 0;
3577 rc = unix_convert(name,conn,0,&bad_path1,NULL);
3578 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3581 * Split the old name into directory and last component
3582 * strings. Note that unix_convert may have stripped off a
3583 * leading ./ from both name and newname if the rename is
3584 * at the root of the share. We need to make sure either both
3585 * name and newname contain a / character or neither of them do
3586 * as this is checked in resolve_wildcards().
3589 p = strrchr(name,'/');
3591 pstrcpy(directory,".");
3595 pstrcpy(directory,name);
3597 *p = '/'; /* Replace needed for exceptional test below. */
3601 * We should only check the mangled cache
3602 * here if unix_convert failed. This means
3603 * that the path in 'mask' doesn't exist
3604 * on the file system and so we need to look
3605 * for a possible mangle. This patch from
3606 * Tine Smukavec <valentin.smukavec@hermes.si>.
3609 if (!rc && is_mangled(mask))
3610 check_mangled_cache( mask );
3612 has_wild = strchr(mask,'*') || strchr(mask,'?');
3616 * No wildcards - just process the one file.
3618 BOOL is_short_name = is_8_3(name, True);
3620 /* Add a terminating '/' to the directory name. */
3621 pstrcat(directory,"/");
3622 pstrcat(directory,mask);
3624 /* Ensure newname contains a '/' also */
3625 if(strrchr(newname,'/') == 0) {
3628 pstrcpy(tmpstr, "./");
3629 pstrcat(tmpstr, newname);
3630 pstrcpy(newname, tmpstr);
3633 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",
3634 case_sensitive, case_preserve, short_case_preserve, directory,
3635 newname, newname_last_component, is_short_name));
3638 * Check for special case with case preserving and not
3639 * case sensitive, if directory and newname are identical,
3640 * and the old last component differs from the original
3641 * last component only by case, then we should allow
3642 * the rename (user is trying to change the case of the
3645 if((case_sensitive == False) &&
3646 (((case_preserve == True) &&
3647 (is_short_name == False)) ||
3648 ((short_case_preserve == True) &&
3649 (is_short_name == True))) &&
3650 strcsequal(directory, newname)) {
3651 pstring newname_modified_last_component;
3654 * Get the last component of the modified name.
3655 * Note that we guarantee that newname contains a '/'
3658 p = strrchr(newname,'/');
3659 pstrcpy(newname_modified_last_component,p+1);
3661 if(strcsequal(newname_modified_last_component,
3662 newname_last_component) == False) {
3664 * Replace the modified last component with
3667 pstrcpy(p+1, newname_last_component);
3671 pstrcpy(zdirectory, dos_to_unix(directory, False));
3672 if(replace_if_exists) {
3674 * NT SMB specific flag - rename can overwrite
3675 * file with the same name so don't check for
3678 if(resolve_wildcards(directory,newname) &&
3679 can_rename(directory,conn) &&
3680 !conn->vfs_ops.rename(zdirectory,
3681 dos_to_unix(newname,False)))
3684 if (resolve_wildcards(directory,newname) &&
3685 can_rename(directory,conn) &&
3686 !vfs_file_exist(conn,newname,NULL) &&
3687 !conn->vfs_ops.rename(zdirectory,
3688 dos_to_unix(newname,False)))
3692 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3693 directory,newname));
3695 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3696 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3702 * Wildcards - process each file that matches.
3704 void *dirptr = NULL;
3708 if (check_name(directory,conn))
3709 dirptr = OpenDir(conn, directory, True);
3714 if (strequal(mask,"????????.???"))
3717 while ((dname = ReadDirName(dirptr))) {
3720 pstrcpy(fname,dname);
3722 if(!mask_match(fname, mask, case_sensitive, False))
3725 error = ERRnoaccess;
3726 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3727 if (!can_rename(fname,conn)) {
3728 DEBUG(6,("rename %s refused\n", fname));
3731 pstrcpy(destname,newname);
3733 if (!resolve_wildcards(fname,destname)) {
3734 DEBUG(6,("resolve_wildcards %s %s failed\n",
3739 if (!replace_if_exists &&
3740 vfs_file_exist(conn,destname, NULL)) {
3741 DEBUG(6,("file_exist %s\n", destname));
3746 if (!conn->vfs_ops.rename(dos_to_unix(fname,False),
3747 dos_to_unix(destname,False)))
3749 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3757 return(ERROR(ERRDOS,error));
3759 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3760 unix_ERR_class = ERRDOS;
3761 unix_ERR_code = ERRbadpath;
3763 return(UNIXERROR(ERRDOS,error));
3770 /****************************************************************************
3772 ****************************************************************************/
3774 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3780 pstrcpy(name,smb_buf(inbuf) + 1);
3781 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3783 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3784 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3786 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3788 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3790 outsize = set_message(outbuf,0,0,True);
3795 /*******************************************************************
3796 copy a file as part of a reply_copy
3797 ******************************************************************/
3799 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3800 int count,BOOL target_is_directory, int *err_ret)
3805 files_struct *fsp1,*fsp2;
3810 pstrcpy(dest,dest1);
3811 if (target_is_directory) {
3812 char *p = strrchr(src,'/');
3821 if (!vfs_file_exist(conn,src,&st))
3828 open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3829 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3836 if (!target_is_directory && count)
3841 close_file(fsp1,False);
3844 open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3845 ofun,st.st_mode,0,&Access,&action);
3848 close_file(fsp1,False);
3853 if ((ofun&3) == 1) {
3854 if(conn->vfs_ops.lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3855 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3858 * Stop the copy from occurring.
3866 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0);
3868 close_file(fsp1,False);
3870 * As we are opening fsp1 read-only we only expect
3871 * an error on close on fsp2 if we are out of space.
3872 * Thus we don't look at the error return from the
3875 *err_ret = close_file(fsp2,False);
3877 return(ret == (SMB_OFF_T)st.st_size);
3882 /****************************************************************************
3883 reply to a file copy.
3884 ****************************************************************************/
3885 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3890 pstring mask,newname;
3893 int error = ERRnoaccess;
3897 int tid2 = SVAL(inbuf,smb_vwv0);
3898 int ofun = SVAL(inbuf,smb_vwv1);
3899 int flags = SVAL(inbuf,smb_vwv2);
3900 BOOL target_is_directory=False;
3901 BOOL bad_path1 = False;
3902 BOOL bad_path2 = False;
3905 *directory = *mask = 0;
3907 pstrcpy(name,smb_buf(inbuf));
3908 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3910 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3912 if (tid2 != conn->cnum) {
3913 /* can't currently handle inter share copies XXXX */
3914 DEBUG(3,("Rejecting inter-share copy\n"));
3915 return(ERROR(ERRSRV,ERRinvdevice));
3918 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3919 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3921 rc = unix_convert(name,conn,0,&bad_path1,NULL);
3922 unix_convert(newname,conn,0,&bad_path2,NULL);
3924 target_is_directory = vfs_directory_exist(conn,False,NULL);
3926 if ((flags&1) && target_is_directory) {
3927 return(ERROR(ERRDOS,ERRbadfile));
3930 if ((flags&2) && !target_is_directory) {
3931 return(ERROR(ERRDOS,ERRbadpath));
3934 if ((flags&(1<<5)) && vfs_directory_exist(conn,name,NULL)) {
3935 /* wants a tree copy! XXXX */
3936 DEBUG(3,("Rejecting tree copy\n"));
3937 return(ERROR(ERRSRV,ERRerror));
3940 p = strrchr(name,'/');
3942 pstrcpy(directory,"./");
3946 pstrcpy(directory,name);
3951 * We should only check the mangled cache
3952 * here if unix_convert failed. This means
3953 * that the path in 'mask' doesn't exist
3954 * on the file system and so we need to look
3955 * for a possible mangle. This patch from
3956 * Tine Smukavec <valentin.smukavec@hermes.si>.
3959 if (!rc && is_mangled(mask))
3960 check_mangled_cache( mask );
3962 has_wild = strchr(mask,'*') || strchr(mask,'?');
3965 pstrcat(directory,"/");
3966 pstrcat(directory,mask);
3967 if (resolve_wildcards(directory,newname) &&
3968 copy_file(directory,newname,conn,ofun,
3969 count,target_is_directory,&err)) count++;
3972 return(UNIXERROR(ERRHRD,ERRgeneral));
3974 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3976 void *dirptr = NULL;
3980 if (check_name(directory,conn))
3981 dirptr = OpenDir(conn, directory, True);
3986 if (strequal(mask,"????????.???"))
3989 while ((dname = ReadDirName(dirptr))) {
3991 pstrcpy(fname,dname);
3993 if(!mask_match(fname, mask, case_sensitive, False))
3996 error = ERRnoaccess;
3997 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3998 pstrcpy(destname,newname);
3999 if (resolve_wildcards(fname,destname) &&
4000 copy_file(fname,destname,conn,ofun,
4001 count,target_is_directory,&err)) count++;
4002 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4010 /* Error on close... */
4012 return(UNIXERROR(ERRHRD,ERRgeneral));
4016 return(ERROR(ERRDOS,error));
4019 if((errno == ENOENT) && (bad_path1 || bad_path2))
4021 unix_ERR_class = ERRDOS;
4022 unix_ERR_code = ERRbadpath;
4024 return(UNIXERROR(ERRDOS,error));
4028 outsize = set_message(outbuf,1,0,True);
4029 SSVAL(outbuf,smb_vwv0,count);
4034 /****************************************************************************
4036 ****************************************************************************/
4037 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4045 if (!CAN_SETDIR(snum))
4046 return(ERROR(ERRDOS,ERRnoaccess));
4048 pstrcpy(newdir,smb_buf(inbuf) + 1);
4051 if (strlen(newdir) == 0) {
4054 ok = vfs_directory_exist(conn,newdir,NULL);
4056 string_set(&conn->connectpath,newdir);
4061 return(ERROR(ERRDOS,ERRbadpath));
4063 outsize = set_message(outbuf,0,0,True);
4064 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4066 DEBUG(3,("setdir %s\n", newdir));
4071 /****************************************************************************
4072 Get a lock count, dealing with large count requests.
4073 ****************************************************************************/
4075 SMB_OFF_T get_lock_count( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4077 SMB_OFF_T count = 0;
4081 if(!large_file_format) {
4082 count = (SMB_OFF_T)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4085 #if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
4087 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4088 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4090 #else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
4093 * NT4.x seems to be broken in that it sends large file
4094 * lockingX calls even if the CAP_LARGE_FILES was *not*
4095 * negotiated. For boxes without large file locks truncate the
4096 * lock count by dropping the top 32 bits.
4099 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4100 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4101 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4102 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4103 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4106 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4108 * Before we error out, see if we can sensibly map the top bits
4109 * down to the lower bits - or lose the top bits if they are all 1's.
4110 * It seems that NT has this horrible bug where it will send 64 bit
4111 * lock requests even if told not to. JRA.
4114 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) == (uint32)0xFFFFFFFF)
4115 count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset));
4116 else if (IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) == (uint32)0xFFFFFFFF)
4117 count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4120 DEBUG(0,("get_lock_count: Error : a large file count (%x << 32 | %x) was sent and we don't \
4121 support large counts.\n", (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4122 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4125 return (SMB_OFF_T)-1;
4129 count = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4131 #endif /* LARGE_SMB_OFF_T */
4136 /****************************************************************************
4137 Get a lock offset, dealing with large offset requests.
4138 ****************************************************************************/
4140 SMB_OFF_T get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4142 SMB_OFF_T offset = 0;
4146 if(!large_file_format) {
4147 offset = (SMB_OFF_T)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4150 #if defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
4152 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4153 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4155 #else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
4158 * NT4.x seems to be broken in that it sends large file
4159 * lockingX calls even if the CAP_LARGE_FILES was *not*
4160 * negotiated. For boxes without large file locks mangle the
4161 * lock offset by mapping the top 32 bits onto the lower 32.
4164 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4165 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4166 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4169 if((new_low = map_lock_offset(high, low)) == 0) {
4171 return (SMB_OFF_T)-1;
4174 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4175 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4176 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4177 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4180 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0){
4182 * Before we error out, see if we can sensibly map the top bits
4183 * down to the lower bits - or lose the top bits if they are all 1's.
4184 * It seems that NT has this horrible bug where it will send 64 bit
4185 * lock requests even if told not to. JRA.
4188 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)) == (uint32)0xFFFFFFFF)
4189 offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4190 else if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) == (uint32)0xFFFFFFFF)
4191 offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4194 DEBUG(0,("get_lock_count: Error : a large file offset (%x << 32 | %x) was sent and we don't \
4195 support large offsets.\n", (unsigned int)IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)),
4196 (unsigned int)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)) ));
4199 return (SMB_OFF_T)-1;
4203 offset = (SMB_OFF_T)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4205 #endif /* LARGE_SMB_OFF_T */
4210 /****************************************************************************
4211 reply to a lockingX request
4212 ****************************************************************************/
4214 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4216 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4217 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4219 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4221 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4222 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4223 SMB_OFF_T count = 0, offset = 0;
4224 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4227 uint32 ecode=0, dummy2;
4228 int eclass=0, dummy1;
4229 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
4232 CHECK_FSP(fsp,conn);
4235 data = smb_buf(inbuf);
4237 /* Check if this is an oplock break on a file
4238 we have granted an oplock on.
4240 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4242 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
4246 * Make sure we have granted an exclusive or batch oplock on this file.
4249 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4251 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4252 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4254 /* if this is a pure oplock break request then don't send a reply */
4255 if (num_locks == 0 && num_ulocks == 0)
4258 return ERROR(ERRDOS,ERRlock);
4261 if (remove_oplock(fsp) == False) {
4262 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4266 /* if this is a pure oplock break request then don't send a reply */
4267 if (num_locks == 0 && num_ulocks == 0)
4269 /* Sanity check - ensure a pure oplock break is not a
4271 if(CVAL(inbuf,smb_vwv0) != 0xff)
4272 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4273 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4278 /* Data now points at the beginning of the list
4279 of smb_unlkrng structs */
4280 for(i = 0; i < (int)num_ulocks; i++) {
4281 count = get_lock_count( data, i, large_file_format, &err1);
4282 offset = get_lock_offset( data, i, large_file_format, &err2);
4285 * There is no error code marked "stupid client bug".... :-).
4288 return ERROR(ERRDOS,ERRnoaccess);
4290 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
4291 (double)offset, (double)count, fsp->fsp_name ));
4293 if(!do_unlock(fsp,conn,count,offset, &eclass, &ecode))
4294 return ERROR(eclass,ecode);
4297 /* Setup the timeout in seconds. */
4298 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4300 /* Now do any requested locks */
4301 data += ((large_file_format ? 20 : 10)*num_ulocks);
4303 /* Data now points at the beginning of the list
4304 of smb_lkrng structs */
4306 for(i = 0; i < (int)num_locks; i++) {
4307 count = get_lock_count( data, i, large_file_format, &err1);
4308 offset = get_lock_offset( data, i, large_file_format, &err2);
4311 * There is no error code marked "stupid client bug".... :-).
4314 return ERROR(ERRDOS,ERRnoaccess);
4316 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
4317 (double)offset, (double)count, fsp->fsp_name ));
4319 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4321 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4323 * A blocking lock was requested. Package up
4324 * this smb into a queued request and push it
4325 * onto the blocking lock queue.
4327 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
4334 /* If any of the above locks failed, then we must unlock
4335 all of the previous locks (X/Open spec). */
4336 if(i != num_locks && num_locks != 0) {
4338 * Ensure we don't do a remove on the lock that just failed,
4339 * as under POSIX rules, if we have a lock already there, we
4340 * will delete it (and we shouldn't) .....
4342 for(i--; i >= 0; i--) {
4343 count = get_lock_count( data, i, large_file_format, &err1);
4344 offset = get_lock_offset( data, i, large_file_format, &err2);
4347 * There is no error code marked "stupid client bug".... :-).
4350 return ERROR(ERRDOS,ERRnoaccess);
4352 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
4354 return ERROR(eclass,ecode);
4357 set_message(outbuf,2,0,True);
4359 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4360 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4362 return chain_reply(inbuf,outbuf,length,bufsize);
4366 /****************************************************************************
4367 reply to a SMBreadbmpx (read block multiplex) request
4368 ****************************************************************************/
4369 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4380 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4382 /* this function doesn't seem to work - disable by default */
4384 return(ERROR(ERRSRV,ERRuseSTD));
4386 outsize = set_message(outbuf,8,0,True);
4388 CHECK_FSP(fsp,conn);
4392 startpos = IVAL(inbuf,smb_vwv1);
4393 maxcount = SVAL(inbuf,smb_vwv3);
4395 data = smb_buf(outbuf);
4396 pad = ((long)data)%4;
4397 if (pad) pad = 4 - pad;
4400 max_per_packet = bufsize-(outsize+pad);
4404 if (is_locked(fsp,conn,maxcount,startpos, READ_LOCK))
4405 return(ERROR(ERRDOS,ERRlock));
4409 size_t N = MIN(max_per_packet,tcount-total_read);
4411 nread = read_file(fsp,data,startpos,N);
4413 if (nread <= 0) nread = 0;
4415 if (nread < (ssize_t)N)
4416 tcount = total_read + nread;
4418 set_message(outbuf,8,nread,False);
4419 SIVAL(outbuf,smb_vwv0,startpos);
4420 SSVAL(outbuf,smb_vwv2,tcount);
4421 SSVAL(outbuf,smb_vwv6,nread);
4422 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4424 send_smb(Client,outbuf);
4426 total_read += nread;
4429 while (total_read < (ssize_t)tcount);
4434 /****************************************************************************
4435 reply to a SMBwritebmpx (write block multiplex primary) request
4436 ****************************************************************************/
4438 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4441 ssize_t nwritten = -1;
4448 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4450 CHECK_FSP(fsp,conn);
4454 tcount = SVAL(inbuf,smb_vwv1);
4455 startpos = IVAL(inbuf,smb_vwv3);
4456 write_through = BITSETW(inbuf+smb_vwv7,0);
4457 numtowrite = SVAL(inbuf,smb_vwv10);
4458 smb_doff = SVAL(inbuf,smb_vwv11);
4460 data = smb_base(inbuf) + smb_doff;
4462 /* If this fails we need to send an SMBwriteC response,
4463 not an SMBwritebmpx - set this up now so we don't forget */
4464 CVAL(outbuf,smb_com) = SMBwritec;
4466 if (is_locked(fsp,conn,tcount,startpos,WRITE_LOCK))
4467 return(ERROR(ERRDOS,ERRlock));
4469 nwritten = write_file(fsp,data,startpos,numtowrite);
4471 if(lp_syncalways(SNUM(conn)) || write_through)
4472 conn->vfs_ops.fsync(fsp->fd_ptr->fd);
4474 if(nwritten < (ssize_t)numtowrite)
4475 return(UNIXERROR(ERRHRD,ERRdiskfull));
4477 /* If the maximum to be written to this file
4478 is greater than what we just wrote then set
4479 up a secondary struct to be attached to this
4480 fd, we will use this to cache error messages etc. */
4481 if((ssize_t)tcount > nwritten)
4483 write_bmpx_struct *wbms;
4484 if(fsp->wbmpx_ptr != NULL)
4485 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4487 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4490 DEBUG(0,("Out of memory in reply_readmpx\n"));
4491 return(ERROR(ERRSRV,ERRnoresource));
4493 wbms->wr_mode = write_through;
4494 wbms->wr_discard = False; /* No errors yet */
4495 wbms->wr_total_written = nwritten;
4496 wbms->wr_errclass = 0;
4498 fsp->wbmpx_ptr = wbms;
4501 /* We are returning successfully, set the message type back to
4503 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4505 outsize = set_message(outbuf,1,0,True);
4507 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4509 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4510 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4512 if (write_through && tcount==nwritten) {
4513 /* we need to send both a primary and a secondary response */
4514 smb_setlen(outbuf,outsize - 4);
4515 send_smb(Client,outbuf);
4517 /* now the secondary */
4518 outsize = set_message(outbuf,1,0,True);
4519 CVAL(outbuf,smb_com) = SMBwritec;
4520 SSVAL(outbuf,smb_vwv0,nwritten);
4527 /****************************************************************************
4528 reply to a SMBwritebs (write block multiplex secondary) request
4529 ****************************************************************************/
4530 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4533 ssize_t nwritten = -1;
4540 write_bmpx_struct *wbms;
4541 BOOL send_response = False;
4542 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4544 CHECK_FSP(fsp,conn);
4547 tcount = SVAL(inbuf,smb_vwv1);
4548 startpos = IVAL(inbuf,smb_vwv2);
4549 numtowrite = SVAL(inbuf,smb_vwv6);
4550 smb_doff = SVAL(inbuf,smb_vwv7);
4552 data = smb_base(inbuf) + smb_doff;
4554 /* We need to send an SMBwriteC response, not an SMBwritebs */
4555 CVAL(outbuf,smb_com) = SMBwritec;
4557 /* This fd should have an auxiliary struct attached,
4558 check that it does */
4559 wbms = fsp->wbmpx_ptr;
4560 if(!wbms) return(-1);
4562 /* If write through is set we can return errors, else we must
4564 write_through = wbms->wr_mode;
4566 /* Check for an earlier error */
4567 if(wbms->wr_discard)
4568 return -1; /* Just discard the packet */
4570 nwritten = write_file(fsp,data,startpos,numtowrite);
4572 if(lp_syncalways(SNUM(conn)) || write_through)
4573 conn->vfs_ops.fsync(fsp->fd_ptr->fd);
4575 if (nwritten < (ssize_t)numtowrite)
4579 /* We are returning an error - we can delete the aux struct */
4580 if (wbms) free((char *)wbms);
4581 fsp->wbmpx_ptr = NULL;
4582 return(ERROR(ERRHRD,ERRdiskfull));
4584 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4587 /* Increment the total written, if this matches tcount
4588 we can discard the auxiliary struct (hurrah !) and return a writeC */
4589 wbms->wr_total_written += nwritten;
4590 if(wbms->wr_total_written >= tcount)
4594 outsize = set_message(outbuf,1,0,True);
4595 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4596 send_response = True;
4600 fsp->wbmpx_ptr = NULL;
4610 /****************************************************************************
4611 reply to a SMBsetattrE
4612 ****************************************************************************/
4614 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4616 struct utimbuf unix_times;
4618 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4620 outsize = set_message(outbuf,0,0,True);
4622 CHECK_FSP(fsp,conn);
4625 /* Convert the DOS times into unix times. Ignore create
4626 time as UNIX can't set this.
4628 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4629 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4632 * Patch from Ray Frush <frush@engr.colostate.edu>
4633 * Sometimes times are sent as zero - ignore them.
4636 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4638 /* Ignore request */
4641 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4642 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4646 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4648 /* set modify time = to access time if modify time was 0 */
4649 unix_times.modtime = unix_times.actime;
4652 /* Set the date on this file */
4653 if(file_utime(conn, fsp->fsp_name, &unix_times))
4654 return(ERROR(ERRDOS,ERRnoaccess));
4656 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4657 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4663 /****************************************************************************
4664 reply to a SMBgetattrE
4665 ****************************************************************************/
4667 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4669 SMB_STRUCT_STAT sbuf;
4672 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4674 outsize = set_message(outbuf,11,0,True);
4676 CHECK_FSP(fsp,conn);
4679 /* Do an fstat on this file */
4680 if(fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd, &sbuf))
4681 return(UNIXERROR(ERRDOS,ERRnoaccess));
4683 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4685 /* Convert the times into dos times. Set create
4686 date to be last modify date as UNIX doesn't save
4688 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4689 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4690 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4693 SIVAL(outbuf,smb_vwv6,0);
4694 SIVAL(outbuf,smb_vwv8,0);
4698 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4699 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4701 SSVAL(outbuf,smb_vwv10, mode);
4703 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));