2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
31 extern int DEBUGLEVEL;
34 extern char magic_char;
35 extern BOOL case_sensitive;
36 extern BOOL case_preserve;
37 extern BOOL short_case_preserve;
38 extern userdom_struct current_user_info;
39 extern pstring global_myname;
40 extern fstring global_myworkgroup;
41 extern int global_oplock_break;
42 uint32 global_client_caps = 0;
43 unsigned int smb_echo_count = 0;
45 /****************************************************************************
46 report a possible attack via the password buffer overflow bug
47 ****************************************************************************/
49 static void overflow_attack(int len)
52 dbgtext( "ERROR: Invalid password length %d.\n", len );
53 dbgtext( "Your machine may be under attack by someone " );
54 dbgtext( "attempting to exploit an old bug.\n" );
55 dbgtext( "Attack was from IP = %s.\n", client_addr() );
57 exit_server("possible attack");
61 /****************************************************************************
62 reply to an special message
63 ****************************************************************************/
65 int reply_special(char *inbuf,char *outbuf)
68 int msg_type = CVAL(inbuf,0);
69 int msg_flags = CVAL(inbuf,1);
71 extern fstring remote_machine;
72 extern fstring local_machine;
78 memset(outbuf,'\0',smb_size);
83 case 0x81: /* session request */
84 CVAL(outbuf,0) = 0x82;
86 if (name_len(inbuf+4) > 50 ||
87 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
88 DEBUG(0,("Invalid name length in session request\n"));
91 name_extract(inbuf,4,name1);
92 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
93 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
96 fstrcpy(remote_machine,name2);
97 remote_machine[15] = 0;
98 trim_string(remote_machine," "," ");
99 strlower(remote_machine);
101 fstrcpy(local_machine,name1);
102 len = strlen(local_machine);
104 name_type = local_machine[15];
105 local_machine[15] = 0;
107 trim_string(local_machine," "," ");
108 strlower(local_machine);
110 if (name_type == 'R') {
111 /* We are being asked for a pathworks session ---
113 CVAL(outbuf, 0) = 0x83;
117 /* only add the client's machine name to the list
118 of possibly valid usernames if we are operating
119 in share mode security */
120 if (lp_security() == SEC_SHARE) {
121 add_session_user(remote_machine);
124 reload_services(True);
128 claim_connection(NULL,"",MAXSTATUS,True);
133 case 0x89: /* session keepalive request
134 (some old clients produce this?) */
135 CVAL(outbuf,0) = 0x85;
139 case 0x82: /* positive session response */
140 case 0x83: /* negative session response */
141 case 0x84: /* retarget session response */
142 DEBUG(0,("Unexpected session response\n"));
145 case 0x85: /* session keepalive */
150 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
151 msg_type, msg_flags));
157 /*******************************************************************
158 work out what error to give to a failed connection
159 ********************************************************************/
161 static int connection_error(char *inbuf,char *outbuf,int ecode)
163 if (ecode == ERRnoipc || ecode == ERRnosuchshare)
164 return(ERROR(ERRDOS,ecode));
166 return(ERROR(ERRSRV,ecode));
170 /****************************************************************************
172 ****************************************************************************/
174 int reply_tcon(connection_struct *conn,
175 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
177 BOOL doencrypt = SMBENCRYPT();
183 uint16 vuid = SVAL(inbuf,smb_uid);
188 START_PROFILE(SMBtcon);
190 *service = *user = *password = *dev = 0;
192 p = smb_buf(inbuf)+1;
193 p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE|STR_CONVERT) + 1;
194 p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE|STR_CONVERT) + 1;
195 p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE|STR_CONVERT) + 1;
198 p = strchr(service,'%');
204 p = strrchr(service,'\\');
206 pstrcpy(service, p+1);
210 * Ensure the user and password names are in UNIX codepage format.
213 dos_to_unix(user,True);
215 dos_to_unix(password,True);
218 * Pass the user through the NT -> unix user mapping
222 (void)map_username(user);
225 * Do any UNIX username case mangling.
227 (void)Get_Pwnam( user, True);
229 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
232 END_PROFILE(SMBtcon);
233 return(connection_error(inbuf,outbuf,ecode));
236 outsize = set_message(outbuf,2,0,True);
237 SSVAL(outbuf,smb_vwv0,max_recv);
238 SSVAL(outbuf,smb_vwv1,conn->cnum);
239 SSVAL(outbuf,smb_tid,conn->cnum);
241 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
242 service, user, conn->cnum));
244 END_PROFILE(SMBtcon);
248 /****************************************************************************
249 Reply to a tcon and X.
250 ****************************************************************************/
251 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
258 uint16 vuid = SVAL(inbuf,smb_uid);
259 int passlen = SVAL(inbuf,smb_vwv3);
262 START_PROFILE(SMBtconX);
264 *service = *user = *password = *devicename = 0;
266 /* we might have to close an old one */
267 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
268 close_cnum(conn,vuid);
271 if (passlen > MAX_PASS_LEN) {
272 overflow_attack(passlen);
275 memcpy(password,smb_buf(inbuf),passlen);
277 p = smb_buf(inbuf) + passlen;
278 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE|STR_CONVERT);
281 if (strequal(password," "))
283 passlen = strlen(password);
286 q = strchr(path+2,'\\');
288 END_PROFILE(SMBtconX);
289 return(ERROR(ERRDOS,ERRnosuchshare));
291 fstrcpy(service,q+1);
292 q = strchr(service,'%');
297 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_CONVERT|STR_ASCII);
299 DEBUG(4,("Got device type %s\n",devicename));
302 * Pass the user through the NT -> unix user mapping
306 (void)map_username(user);
309 * Do any UNIX username case mangling.
311 (void)Get_Pwnam(user, True);
313 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
316 END_PROFILE(SMBtconX);
317 return(connection_error(inbuf,outbuf,ecode));
320 if (Protocol < PROTOCOL_NT1) {
321 set_message(outbuf,2,0,True);
323 p += srvstr_push(outbuf, p, devicename, -1,
324 STR_CONVERT|STR_TERMINATE|STR_ASCII);
325 set_message_end(outbuf,p);
327 /* NT sets the fstype of IPC$ to the null string */
328 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
330 set_message(outbuf,3,0,True);
333 p += srvstr_push(outbuf, p, devicename, -1,
334 STR_CONVERT|STR_TERMINATE|STR_ASCII);
335 p += srvstr_push(outbuf, p, fsname, -1,
336 STR_CONVERT|STR_TERMINATE);
338 set_message_end(outbuf,p);
340 /* what does setting this bit do? It is set by NT4 and
341 may affect the ability to autorun mounted cdroms */
342 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
344 init_dfsroot(conn, inbuf, outbuf);
348 DEBUG(3,("tconX service=%s user=%s\n",
351 /* set the incoming and outgoing tid to the just created one */
352 SSVAL(inbuf,smb_tid,conn->cnum);
353 SSVAL(outbuf,smb_tid,conn->cnum);
355 END_PROFILE(SMBtconX);
356 return chain_reply(inbuf,outbuf,length,bufsize);
360 /****************************************************************************
361 reply to an unknown type
362 ****************************************************************************/
363 int reply_unknown(char *inbuf,char *outbuf)
366 type = CVAL(inbuf,smb_com);
368 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
369 smb_fn_name(type), type, type));
371 return(ERROR(ERRSRV,ERRunknownsmb));
375 /****************************************************************************
377 ****************************************************************************/
378 int reply_ioctl(connection_struct *conn,
379 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
381 uint16 device = SVAL(inbuf,smb_vwv1);
382 uint16 function = SVAL(inbuf,smb_vwv2);
383 uint32 ioctl_code = (device << 16) + function;
384 int replysize, outsize;
386 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
387 START_PROFILE(SMBioctl);
389 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
393 case IOCTL_QUERY_JOB_INFO:
397 END_PROFILE(SMBioctl);
398 return(ERROR(ERRSRV,ERRnosupport));
401 outsize = set_message(outbuf,8,replysize+1,True);
402 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
403 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
404 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
405 p = smb_buf(outbuf) + 1; /* Allow for alignment */
409 case IOCTL_QUERY_JOB_INFO:
410 SSVAL(p,0,fsp->print_jobid); /* Job number */
411 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_CONVERT|STR_ASCII);
412 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_CONVERT|STR_ASCII);
416 END_PROFILE(SMBioctl);
420 /****************************************************************************
421 always return an error: it's just a matter of which one...
422 ****************************************************************************/
423 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
424 char *smb_passwd, int smb_passlen,
425 char *smb_nt_passwd, int smb_nt_passlen)
427 /* check if trust account exists */
428 SAM_ACCOUNT *sam_trust_acct = NULL;
432 pdb_init_sam(&sam_trust_acct);
434 if (lp_security() == SEC_USER) {
435 ret = pdb_getsampwnam(sam_trust_acct, user);
437 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
438 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
439 pdb_free_sam(sam_trust_acct);
440 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
444 /* lkclXXXX: workstation entry doesn't exist */
445 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
446 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
447 pdb_free_sam(sam_trust_acct);
448 return(ERROR(0, NT_STATUS_NO_SUCH_USER));
450 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
451 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
452 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
453 pdb_free_sam(sam_trust_acct);
454 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
457 if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) {
458 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
459 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
460 pdb_free_sam(sam_trust_acct);
461 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
464 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
465 pdb_free_sam(sam_trust_acct);
466 if (acct_ctrl & ACB_DOMTRUST) {
467 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
468 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
469 return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
472 if (acct_ctrl & ACB_SVRTRUST) {
473 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
474 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
475 return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
478 if (acct_ctrl & ACB_WSTRUST) {
479 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
480 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
481 return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
485 /* don't know what to do: indicate logon failure */
486 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
487 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
490 /****************************************************************************
491 Create a UNIX user on demand.
492 ****************************************************************************/
494 int smb_create_user(char *unix_user, char *homedir)
499 pstrcpy(add_script, lp_adduser_script());
500 if (! *add_script) return -1;
501 all_string_sub(add_script, "%u", unix_user, sizeof(pstring));
503 all_string_sub(add_script, "%H", homedir, sizeof(pstring));
504 ret = smbrun(add_script,NULL);
505 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
509 /****************************************************************************
510 Delete a UNIX user on demand.
511 ****************************************************************************/
513 static int smb_delete_user(char *unix_user)
518 pstrcpy(del_script, lp_deluser_script());
519 if (! *del_script) return -1;
520 all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
521 ret = smbrun(del_script,NULL);
522 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
526 /****************************************************************************
527 Check user is in correct domain if required
528 ****************************************************************************/
530 static BOOL check_domain_match(char *user, char *domain)
533 * If we aren't serving to trusted domains, we must make sure that
534 * the validation request comes from an account in the same domain
535 * as the Samba server
538 if (!lp_allow_trusted_domains() &&
539 !strequal(lp_workgroup(), domain) ) {
540 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
547 /****************************************************************************
548 Check for a valid username and password in security=server mode.
549 ****************************************************************************/
551 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
552 char *smb_apasswd, int smb_apasslen,
553 char *smb_ntpasswd, int smb_ntpasslen)
557 if(lp_security() != SEC_SERVER)
560 if (!check_domain_match(orig_user, domain))
563 ret = server_validate(orig_user, domain,
564 smb_apasswd, smb_apasslen,
565 smb_ntpasswd, smb_ntpasslen);
567 struct passwd *pwd=NULL;
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() && !(pwd = smb_getpwnam(unix_user,True))) {
578 smb_create_user(unix_user, NULL);
581 if(lp_adduser_script() && pwd) {
585 * Also call smb_create_user if the users home directory
586 * doesn't exist. Used with winbindd to allow the script to
587 * create the home directory for a user mapped with winbindd.
590 if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
591 smb_create_user(unix_user, pwd->pw_dir);
598 /****************************************************************************
599 Check for a valid username and password in security=domain mode.
600 ****************************************************************************/
602 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
603 char *smb_apasswd, int smb_apasslen,
604 char *smb_ntpasswd, int smb_ntpasslen)
607 BOOL user_exists = True;
608 struct passwd *pwd=NULL;
610 if(lp_security() != SEC_DOMAIN)
613 if (!check_domain_match(orig_user, domain))
616 ret = domain_client_validate(orig_user, domain,
617 smb_apasswd, smb_apasslen,
618 smb_ntpasswd, smb_ntpasslen,
623 * User validated ok against Domain controller.
624 * If the admin wants us to try and create a UNIX
625 * user on the fly, do so.
627 if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
628 smb_create_user(unix_user, NULL);
631 if(lp_adduser_script() && pwd) {
635 * Also call smb_create_user if the users home directory
636 * doesn't exist. Used with winbindd to allow the script to
637 * create the home directory for a user mapped with winbindd.
640 if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
641 smb_create_user(unix_user, pwd->pw_dir);
646 * User failed to validate ok against Domain controller.
647 * If the failure was "user doesn't exist" and admin
648 * wants us to try and delete that UNIX user on the fly,
651 if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) {
652 smb_delete_user(unix_user);
659 /****************************************************************************
660 Return a bad password error configured for the correct client type.
661 ****************************************************************************/
663 static int bad_password_error(char *inbuf,char *outbuf)
665 enum remote_arch_types ra_type = get_remote_arch();
667 if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
668 (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
669 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
670 return(ERROR(0,NT_STATUS_LOGON_FAILURE));
673 return(ERROR(ERRSRV,ERRbadpw));
676 /****************************************************************************
677 reply to a session setup command
678 ****************************************************************************/
680 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
686 int smb_apasslen = 0;
688 int smb_ntpasslen = 0;
689 pstring smb_ntpasswd;
690 BOOL valid_nt_password = False;
691 BOOL valid_lm_password = False;
696 fstring native_lanman;
698 static BOOL done_sesssetup = False;
699 BOOL doencrypt = SMBENCRYPT();
700 START_PROFILE(SMBsesssetupX);
705 smb_bufsize = SVAL(inbuf,smb_vwv2);
707 if (Protocol < PROTOCOL_NT1) {
708 smb_apasslen = SVAL(inbuf,smb_vwv7);
709 if (smb_apasslen > MAX_PASS_LEN)
710 overflow_attack(smb_apasslen);
712 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
713 smb_apasswd[smb_apasslen] = 0;
714 srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE|STR_CONVERT);
716 if (!doencrypt && (lp_security() != SEC_SERVER)) {
717 smb_apasslen = strlen(smb_apasswd);
720 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
721 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
722 enum remote_arch_types ra_type = get_remote_arch();
723 char *p = smb_buf(inbuf);
725 if(global_client_caps == 0)
726 global_client_caps = IVAL(inbuf,smb_vwv11);
728 /* client_caps is used as final determination if client is NT or Win95.
729 This is needed to return the correct error codes in some
733 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
734 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
735 set_remote_arch( RA_WIN95);
739 if (passlen1 != 24 && passlen2 != 24)
742 if (passlen1 > MAX_PASS_LEN) {
743 overflow_attack(passlen1);
746 passlen1 = MIN(passlen1, MAX_PASS_LEN);
747 passlen2 = MIN(passlen2, MAX_PASS_LEN);
750 /* both Win95 and WinNT stuff up the password lengths for
751 non-encrypting systems. Uggh.
753 if passlen1==24 its a win95 system, and its setting the
754 password length incorrectly. Luckily it still works with the
755 default code because Win95 will null terminate the password
758 if passlen1>0 and passlen2>0 then maybe its a NT box and its
759 setting passlen2 to some random value which really stuffs
760 things up. we need to fix that one. */
762 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
766 if (lp_restrict_anonymous()) {
767 /* there seems to be no reason behind the differences in MS clients formatting
768 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
769 * in particular seems to have an extra null byte between the username and the
770 * domain, or the password length calculation is wrong, which throws off the
771 * string extraction routines below. This makes the value of domain be the
772 * empty string, which fails the restrict anonymous check further down.
773 * This compensates for that, and allows browsing to work in mixed NT and
774 * win95 environments even when restrict anonymous is true. AAB
776 dump_data(100, p, 0x70);
777 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
778 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
779 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
780 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
781 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
786 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
787 /* Save the lanman2 password and the NT md4 password. */
788 smb_apasslen = passlen1;
789 memcpy(smb_apasswd,p,smb_apasslen);
790 smb_apasswd[smb_apasslen] = 0;
791 smb_ntpasslen = passlen2;
792 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
793 smb_ntpasswd[smb_ntpasslen] = 0;
796 * Ensure the plaintext passwords are in UNIX format.
799 dos_to_unix(smb_apasswd,True);
800 dos_to_unix(smb_ntpasswd,True);
804 /* we use the first password that they gave */
805 smb_apasslen = passlen1;
806 StrnCpy(smb_apasswd,p,smb_apasslen);
808 * Ensure the plaintext password is in UNIX format.
810 dos_to_unix(smb_apasswd,True);
812 /* trim the password */
813 smb_apasslen = strlen(smb_apasswd);
815 /* wfwg sometimes uses a space instead of a null */
816 if (strequal(smb_apasswd," ")) {
822 p += passlen1 + passlen2;
823 p += srvstr_pull(inbuf, user, p, sizeof(user), -1, STR_CONVERT|STR_TERMINATE);
825 * Incoming user and domain are in DOS codepage format. Convert
828 p += srvstr_pull(inbuf, domain, p, sizeof(domain),
829 -1, STR_CONVERT|STR_TERMINATE);
830 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
831 -1, STR_CONVERT|STR_TERMINATE);
832 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
833 -1, STR_CONVERT|STR_TERMINATE);
834 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
835 domain,native_os,native_lanman));
838 DEBUG(3,("sesssetupX:name=[%s]\n",user));
840 /* If name ends in $ then I think it's asking about whether a */
841 /* computer with that name (minus the $) has access. For now */
842 /* say yes to everything ending in $. */
844 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
845 END_PROFILE(SMBsesssetupX);
846 return session_trust_account(conn, inbuf, outbuf, user,
847 smb_apasswd, smb_apasslen,
848 smb_ntpasswd, smb_ntpasslen);
851 if (done_sesssetup && lp_restrict_anonymous()) {
852 /* tests show that even if browsing is done over already validated connections
853 * without a username and password the domain is still provided, which it
854 * wouldn't be if it was a purely anonymous connection. So, in order to
855 * restrict anonymous, we only deny connections that have no session
856 * information. If a domain has been provided, then it's not a purely
857 * anonymous connection. AAB
859 if (!*user && !*smb_apasswd && !*domain) {
860 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
861 END_PROFILE(SMBsesssetupX);
862 return(ERROR(ERRDOS,ERRnoaccess));
866 /* If no username is sent use the guest account */
868 pstrcpy(user,lp_guestaccount(-1));
869 /* If no user and no password then set guest flag. */
870 if( *smb_apasswd == 0)
874 pstrcpy(current_user_info.smb_name,user);
876 reload_services(True);
879 * Save the username before mapping. We will use
880 * the original username sent to us for security=server
881 * and security=domain checking.
884 pstrcpy( orig_user, user);
886 /* if the username exists as a domain/username pair on the unix system then use
888 if (!sys_getpwnam(user)) {
891 slprintf(user2,sizeof(user2)-1,"%s%s%s", dos_to_unix(domain,False),
892 lp_winbind_separator(), user);
894 if (sys_getpwnam(user2)) {
895 DEBUG(3,("Using unix username %s\n", user2));
896 pstrcpy(user, user2);
901 * Pass the user through the NT -> unix user mapping
905 (void)map_username(user);
908 * Do any UNIX username case mangling.
910 smb_getpwnam(user, True);
912 add_session_user(user);
915 * Check if the given username was the guest user with no password.
918 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
922 * Check with orig_user for security=server and
926 if (!guest && !check_server_security(orig_user, domain, user,
927 smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
928 !check_domain_security(orig_user, domain, user, smb_apasswd,
929 smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
930 !check_hosts_equiv(user))
934 * If we get here then the user wasn't guest and the remote
935 * authentication methods failed. Check the authentication
936 * methods on this local server.
938 * If an NT password was supplied try and validate with that
939 * first. This is superior as the passwords are mixed case
940 * 128 length unicode.
945 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
946 DEBUG(2,("NT Password did not match for user '%s'!\n", user));
948 valid_nt_password = True;
952 /* check the LanMan password only if necessary and if allowed
953 by lp_lanman_auth() */
954 if (!valid_nt_password && lp_lanman_auth())
956 DEBUG(2,("Defaulting to Lanman password for %s\n", user));
957 valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen,NULL);
961 /* The true branch will be executed if
962 (1) the NT password failed (or was not tried), and
963 (2) LanMan authentication failed (or was disabled)
965 if (!valid_nt_password && !valid_lm_password)
967 if (lp_security() >= SEC_USER)
969 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
971 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
972 END_PROFILE(SMBsesssetupX);
973 return bad_password_error(inbuf,outbuf);
976 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
978 if (smb_getpwnam(user,True))
980 DEBUG(1,("Rejecting user '%s': bad password\n", user));
981 END_PROFILE(SMBsesssetupX);
982 return bad_password_error(inbuf,outbuf);
987 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
988 * Then always map to guest account - as done below.
992 if (*smb_apasswd || !smb_getpwnam(user,True))
993 pstrcpy(user,lp_guestaccount(-1));
994 DEBUG(3,("Registered username %s for guest access\n",user));
999 if (!smb_getpwnam(user,True)) {
1000 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
1001 pstrcpy(user,lp_guestaccount(-1));
1005 if (!strequal(user,lp_guestaccount(-1)) &&
1006 lp_servicenumber(user) < 0)
1008 add_home_service(user,get_user_home_dir(user));
1012 /* it's ok - setup a reply */
1013 if (Protocol < PROTOCOL_NT1) {
1014 set_message(outbuf,3,0,True);
1017 set_message(outbuf,3,0,True);
1018 p = smb_buf(outbuf);
1019 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE|STR_CONVERT);
1020 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE|STR_CONVERT);
1021 p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE|STR_CONVERT);
1022 set_message_end(outbuf,p);
1023 /* perhaps grab OS version here?? */
1026 /* Set the correct uid in the outgoing and incoming packets
1027 We will use this on future requests to determine which
1028 user we should become.
1031 const struct passwd *pw = smb_getpwnam(user,False);
1033 DEBUG(1,("Username %s is invalid on this system\n",user));
1034 END_PROFILE(SMBsesssetupX);
1035 return bad_password_error(inbuf,outbuf);
1042 SSVAL(outbuf,smb_vwv2,1);
1044 /* register the name and uid as being validated, so further connections
1045 to a uid can get through without a password, on the same VC */
1047 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest);
1049 if (sess_vuid == -1) {
1050 return(ERROR(ERRDOS,ERRnoaccess));
1054 SSVAL(outbuf,smb_uid,sess_vuid);
1055 SSVAL(inbuf,smb_uid,sess_vuid);
1057 if (!done_sesssetup)
1058 max_send = MIN(max_send,smb_bufsize);
1060 DEBUG(6,("Client requested max send size of %d\n", max_send));
1062 done_sesssetup = True;
1064 END_PROFILE(SMBsesssetupX);
1065 return chain_reply(inbuf,outbuf,length,bufsize);
1069 /****************************************************************************
1071 ****************************************************************************/
1072 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1078 BOOL bad_path = False;
1079 SMB_STRUCT_STAT sbuf;
1080 START_PROFILE(SMBchkpth);
1082 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1084 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1086 unix_convert(name,conn,0,&bad_path,&sbuf);
1088 mode = SVAL(inbuf,smb_vwv0);
1090 if (check_name(name,conn)) {
1091 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
1092 ok = S_ISDIR(sbuf.st_mode);
1097 /* We special case this - as when a Windows machine
1098 is parsing a path is steps through the components
1099 one at a time - if a component fails it expects
1100 ERRbadpath, not ERRbadfile.
1104 unix_ERR_class = ERRDOS;
1105 unix_ERR_code = ERRbadpath;
1109 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1110 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1111 (get_remote_arch() == RA_WINNT))
1113 unix_ERR_class = ERRDOS;
1114 unix_ERR_code = ERRbaddirectory;
1118 return(UNIXERROR(ERRDOS,ERRbadpath));
1121 outsize = set_message(outbuf,0,0,True);
1123 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1125 END_PROFILE(SMBchkpth);
1130 /****************************************************************************
1132 ****************************************************************************/
1133 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1137 SMB_STRUCT_STAT sbuf;
1142 BOOL bad_path = False;
1144 START_PROFILE(SMBgetatr);
1146 p = smb_buf(inbuf) + 1;
1147 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1149 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1151 /* if((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && dfs_redirect(fname,conn)) return(dfs_path_error(inbuf,outbuf));
1153 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1154 under WfWg - weird! */
1157 mode = aHIDDEN | aDIR;
1158 if (!CAN_WRITE(conn)) mode |= aRONLY;
1165 unix_convert(fname,conn,0,&bad_path,&sbuf);
1166 if (check_name(fname,conn))
1168 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1170 mode = dos_mode(conn,fname,&sbuf);
1171 size = sbuf.st_size;
1172 mtime = sbuf.st_mtime;
1178 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1184 if((errno == ENOENT) && bad_path)
1186 unix_ERR_class = ERRDOS;
1187 unix_ERR_code = ERRbadpath;
1190 END_PROFILE(SMBgetatr);
1191 return(UNIXERROR(ERRDOS,ERRbadfile));
1194 outsize = set_message(outbuf,10,0,True);
1196 SSVAL(outbuf,smb_vwv0,mode);
1197 if(lp_dos_filetime_resolution(SNUM(conn)) )
1198 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1200 put_dos_date3(outbuf,smb_vwv1,mtime);
1201 SIVAL(outbuf,smb_vwv3,(uint32)size);
1203 if (Protocol >= PROTOCOL_NT1) {
1204 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1207 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1209 END_PROFILE(SMBgetatr);
1214 /****************************************************************************
1216 ****************************************************************************/
1217 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1224 SMB_STRUCT_STAT sbuf;
1225 BOOL bad_path = False;
1228 START_PROFILE(SMBsetatr);
1230 p = smb_buf(inbuf) + 1;
1231 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1232 unix_convert(fname,conn,0,&bad_path,&sbuf);
1234 mode = SVAL(inbuf,smb_vwv0);
1235 mtime = make_unix_date3(inbuf+smb_vwv1);
1237 if (VALID_STAT_OF_DIR(sbuf))
1239 if (check_name(fname,conn))
1240 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1242 ok = set_filetime(conn,fname,mtime);
1246 if((errno == ENOENT) && bad_path)
1248 unix_ERR_class = ERRDOS;
1249 unix_ERR_code = ERRbadpath;
1252 END_PROFILE(SMBsetatr);
1253 return(UNIXERROR(ERRDOS,ERRnoaccess));
1256 outsize = set_message(outbuf,0,0,True);
1258 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1260 END_PROFILE(SMBsetatr);
1265 /****************************************************************************
1267 ****************************************************************************/
1268 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1271 SMB_BIG_UINT dfree,dsize,bsize;
1272 START_PROFILE(SMBdskattr);
1274 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1276 outsize = set_message(outbuf,5,0,True);
1278 SSVAL(outbuf,smb_vwv0,dsize);
1279 SSVAL(outbuf,smb_vwv1,bsize/512);
1280 SSVAL(outbuf,smb_vwv2,512);
1281 SSVAL(outbuf,smb_vwv3,dfree);
1283 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1285 END_PROFILE(SMBdskattr);
1290 /****************************************************************************
1292 Can be called from SMBsearch, SMBffirst or SMBfunique.
1293 ****************************************************************************/
1294 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1305 BOOL finished = False;
1314 BOOL check_descend = False;
1315 BOOL expect_close = False;
1316 BOOL can_open = True;
1317 BOOL bad_path = False;
1318 START_PROFILE(SMBsearch);
1320 *mask = *directory = *fname = 0;
1322 /* If we were called as SMBffirst then we must expect close. */
1323 if(CVAL(inbuf,smb_com) == SMBffirst)
1324 expect_close = True;
1326 outsize = set_message(outbuf,1,3,True);
1327 maxentries = SVAL(inbuf,smb_vwv0);
1328 dirtype = SVAL(inbuf,smb_vwv1);
1329 p = smb_buf(inbuf) + 1;
1330 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1332 status_len = SVAL(p, 0);
1335 /* dirtype &= ~aDIR; */
1337 if (status_len == 0)
1339 SMB_STRUCT_STAT sbuf;
1342 pstrcpy(directory,path);
1344 unix_convert(directory,conn,0,&bad_path,&sbuf);
1347 if (!check_name(directory,conn))
1350 p = strrchr(dir2,'/');
1362 p = strrchr(directory,'/');
1368 if (strlen(directory) == 0)
1369 pstrcpy(directory,"./");
1370 memset((char *)status,'\0',21);
1371 CVAL(status,0) = dirtype;
1375 memcpy(status,p,21);
1376 dirtype = CVAL(status,0) & 0x1F;
1377 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1380 string_set(&conn->dirpath,dptr_path(dptr_num));
1381 fstrcpy(mask, dptr_wcard(dptr_num));
1386 p = smb_buf(outbuf) + 3;
1390 if (status_len == 0)
1392 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1397 if((errno == ENOENT) && bad_path)
1399 unix_ERR_class = ERRDOS;
1400 unix_ERR_code = ERRbadpath;
1402 END_PROFILE(SMBsearch);
1403 return (UNIXERROR(ERRDOS,ERRnofids));
1405 END_PROFILE(SMBsearch);
1406 return(ERROR(ERRDOS,ERRnofids));
1408 dptr_set_wcard(dptr_num, strdup(mask));
1411 DEBUG(4,("dptr_num is %d\n",dptr_num));
1415 if ((dirtype&0x1F) == aVOLID)
1417 memcpy(p,status,21);
1418 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1419 dptr_fill(p+12,dptr_num);
1420 if (dptr_zero(p+12) && (status_len==0))
1424 p += DIR_STRUCT_SIZE;
1428 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1429 conn->dirpath,lp_dontdescend(SNUM(conn))));
1430 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1431 check_descend = True;
1433 for (i=numentries;(i<maxentries) && !finished;i++)
1436 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1439 memcpy(p,status,21);
1440 make_dir_struct(p,mask,fname,size,mode,date);
1441 dptr_fill(p+12,dptr_num);
1444 p += DIR_STRUCT_SIZE;
1453 if (numentries == 0 || !ok)
1455 CVAL(outbuf,smb_rcls) = ERRDOS;
1456 SSVAL(outbuf,smb_err,ERRnofiles);
1457 dptr_close(&dptr_num);
1460 /* If we were called as SMBffirst with smb_search_id == NULL
1461 and no entries were found then return error and close dirptr
1464 if(ok && expect_close && numentries == 0 && status_len == 0)
1466 CVAL(outbuf,smb_rcls) = ERRDOS;
1467 SSVAL(outbuf,smb_err,ERRnofiles);
1468 /* Also close the dptr - we know it's gone */
1469 dptr_close(&dptr_num);
1472 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1473 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1474 dptr_close(&dptr_num);
1476 SSVAL(outbuf,smb_vwv0,numentries);
1477 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1478 CVAL(smb_buf(outbuf),0) = 5;
1479 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1481 if (Protocol >= PROTOCOL_NT1) {
1482 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1485 outsize += DIR_STRUCT_SIZE*numentries;
1486 smb_setlen(outbuf,outsize - 4);
1488 if ((! *directory) && dptr_path(dptr_num))
1489 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1491 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1492 smb_fn_name(CVAL(inbuf,smb_com)),
1493 mask, directory, dirtype, numentries, maxentries ) );
1495 END_PROFILE(SMBsearch);
1500 /****************************************************************************
1501 reply to a fclose (stop directory search)
1502 ****************************************************************************/
1503 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1512 START_PROFILE(SMBfclose);
1514 outsize = set_message(outbuf,1,0,True);
1515 p = smb_buf(inbuf) + 1;
1516 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE|STR_CONVERT);
1518 status_len = SVAL(p,0);
1521 if (status_len == 0) {
1522 END_PROFILE(SMBfclose);
1523 return(ERROR(ERRSRV,ERRsrverror));
1526 memcpy(status,p,21);
1528 if(dptr_fetch(status+12,&dptr_num)) {
1529 /* Close the dptr - we know it's gone */
1530 dptr_close(&dptr_num);
1533 SSVAL(outbuf,smb_vwv0,0);
1535 DEBUG(3,("search close\n"));
1537 END_PROFILE(SMBfclose);
1542 /****************************************************************************
1544 ****************************************************************************/
1546 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1556 SMB_STRUCT_STAT sbuf;
1557 BOOL bad_path = False;
1559 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1560 START_PROFILE(SMBopen);
1562 share_mode = SVAL(inbuf,smb_vwv0);
1564 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1566 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1568 unix_convert(fname,conn,0,&bad_path,&sbuf);
1570 unixmode = unix_mode(conn,aARCH,fname);
1572 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1573 unixmode, oplock_request,&rmode,NULL);
1577 if((errno == ENOENT) && bad_path)
1579 unix_ERR_class = ERRDOS;
1580 unix_ERR_code = ERRbadpath;
1582 END_PROFILE(SMBopen);
1583 return(UNIXERROR(ERRDOS,ERRnoaccess));
1586 size = sbuf.st_size;
1587 fmode = dos_mode(conn,fname,&sbuf);
1588 mtime = sbuf.st_mtime;
1591 DEBUG(3,("attempt to open a directory %s\n",fname));
1592 close_file(fsp,False);
1593 END_PROFILE(SMBopen);
1594 return(ERROR(ERRDOS,ERRnoaccess));
1597 outsize = set_message(outbuf,7,0,True);
1598 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1599 SSVAL(outbuf,smb_vwv1,fmode);
1600 if(lp_dos_filetime_resolution(SNUM(conn)) )
1601 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1603 put_dos_date3(outbuf,smb_vwv2,mtime);
1604 SIVAL(outbuf,smb_vwv4,(uint32)size);
1605 SSVAL(outbuf,smb_vwv6,rmode);
1607 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1608 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1611 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1612 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1613 END_PROFILE(SMBopen);
1618 /****************************************************************************
1619 reply to an open and X
1620 ****************************************************************************/
1621 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1624 int smb_mode = SVAL(inbuf,smb_vwv3);
1625 int smb_attr = SVAL(inbuf,smb_vwv5);
1626 /* Breakout the oplock request bits so we can set the
1627 reply bits separately. */
1628 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1629 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1630 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1632 int open_flags = SVAL(inbuf,smb_vwv2);
1633 int smb_sattr = SVAL(inbuf,smb_vwv4);
1634 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1636 int smb_ofun = SVAL(inbuf,smb_vwv8);
1639 int fmode=0,mtime=0,rmode=0;
1640 SMB_STRUCT_STAT sbuf;
1642 BOOL bad_path = False;
1644 START_PROFILE(SMBopenX);
1646 /* If it's an IPC, pass off the pipe handler. */
1648 if (lp_nt_pipe_support()) {
1649 END_PROFILE(SMBopenX);
1650 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1652 END_PROFILE(SMBopenX);
1653 return (ERROR(ERRSRV,ERRaccess));
1657 /* XXXX we need to handle passed times, sattr and flags */
1658 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1660 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1662 unix_convert(fname,conn,0,&bad_path,&sbuf);
1664 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1666 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1667 oplock_request, &rmode,&smb_action);
1671 if((errno == ENOENT) && bad_path)
1673 unix_ERR_class = ERRDOS;
1674 unix_ERR_code = ERRbadpath;
1676 END_PROFILE(SMBopenX);
1677 return(UNIXERROR(ERRDOS,ERRnoaccess));
1680 size = sbuf.st_size;
1681 fmode = dos_mode(conn,fname,&sbuf);
1682 mtime = sbuf.st_mtime;
1684 close_file(fsp,False);
1685 END_PROFILE(SMBopenX);
1686 return(ERROR(ERRDOS,ERRnoaccess));
1689 /* If the caller set the extended oplock request bit
1690 and we granted one (by whatever means) - set the
1691 correct bit for extended oplock reply.
1694 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1695 smb_action |= EXTENDED_OPLOCK_GRANTED;
1698 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1699 smb_action |= EXTENDED_OPLOCK_GRANTED;
1702 /* If the caller set the core oplock request bit
1703 and we granted one (by whatever means) - set the
1704 correct bit for core oplock reply.
1707 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1708 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1711 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1712 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1715 set_message(outbuf,15,0,True);
1716 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1717 SSVAL(outbuf,smb_vwv3,fmode);
1718 if(lp_dos_filetime_resolution(SNUM(conn)) )
1719 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1721 put_dos_date3(outbuf,smb_vwv4,mtime);
1722 SIVAL(outbuf,smb_vwv6,(uint32)size);
1723 SSVAL(outbuf,smb_vwv8,rmode);
1724 SSVAL(outbuf,smb_vwv11,smb_action);
1726 END_PROFILE(SMBopenX);
1727 return chain_reply(inbuf,outbuf,length,bufsize);
1731 /****************************************************************************
1732 reply to a SMBulogoffX
1733 ****************************************************************************/
1734 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1736 uint16 vuid = SVAL(inbuf,smb_uid);
1737 user_struct *vuser = get_valid_user_struct(vuid);
1738 START_PROFILE(SMBulogoffX);
1741 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1744 /* in user level security we are supposed to close any files
1745 open by this user */
1746 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1747 file_close_user(vuid);
1750 invalidate_vuid(vuid);
1752 set_message(outbuf,2,0,True);
1754 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1756 END_PROFILE(SMBulogoffX);
1757 return chain_reply(inbuf,outbuf,length,bufsize);
1761 /****************************************************************************
1762 reply to a mknew or a create
1763 ****************************************************************************/
1764 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1772 BOOL bad_path = False;
1774 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1775 SMB_STRUCT_STAT sbuf;
1776 START_PROFILE(SMBcreate);
1778 com = SVAL(inbuf,smb_com);
1780 createmode = SVAL(inbuf,smb_vwv0);
1781 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1783 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1785 unix_convert(fname,conn,0,&bad_path,&sbuf);
1787 if (createmode & aVOLID) {
1788 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1791 unixmode = unix_mode(conn,createmode,fname);
1795 /* We should fail if file exists. */
1796 ofun = FILE_CREATE_IF_NOT_EXIST;
1800 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1801 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1804 /* Open file in dos compatibility share mode. */
1805 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1806 ofun, unixmode, oplock_request, NULL, NULL);
1810 if((errno == ENOENT) && bad_path)
1812 unix_ERR_class = ERRDOS;
1813 unix_ERR_code = ERRbadpath;
1815 END_PROFILE(SMBcreate);
1816 return(UNIXERROR(ERRDOS,ERRnoaccess));
1819 outsize = set_message(outbuf,1,0,True);
1820 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1822 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1823 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1826 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1827 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1829 DEBUG( 2, ( "new file %s\n", fname ) );
1830 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1831 fname, fsp->fd, createmode, (int)unixmode ) );
1833 END_PROFILE(SMBcreate);
1838 /****************************************************************************
1839 reply to a create temporary file
1840 ****************************************************************************/
1841 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1848 BOOL bad_path = False;
1850 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1852 SMB_STRUCT_STAT sbuf;
1855 START_PROFILE(SMBctemp);
1857 createmode = SVAL(inbuf,smb_vwv0);
1858 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT);
1859 pstrcat(fname,"/TMXXXXXX");
1861 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1863 unix_convert(fname,conn,0,&bad_path,&sbuf);
1865 unixmode = unix_mode(conn,createmode,fname);
1867 tmpfd = smb_mkstemp(fname);
1869 END_PROFILE(SMBctemp);
1870 return(UNIXERROR(ERRDOS,ERRnoaccess));
1873 vfs_stat(conn,fname2,&sbuf);
1875 /* Open file in dos compatibility share mode. */
1876 /* We should fail if file does not exist. */
1877 fsp = open_file_shared(conn,fname,&sbuf,
1878 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1879 FILE_FAIL_IF_NOT_EXIST,
1880 unixmode, oplock_request, NULL, NULL);
1882 /* close fd from smb_mkstemp() */
1887 if((errno == ENOENT) && bad_path)
1889 unix_ERR_class = ERRDOS;
1890 unix_ERR_code = ERRbadpath;
1892 END_PROFILE(SMBctemp);
1893 return(UNIXERROR(ERRDOS,ERRnoaccess));
1896 outsize = set_message(outbuf,1,0,True);
1897 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1898 CVAL(smb_buf(outbuf),0) = 4;
1899 p = smb_buf(outbuf) + 1;
1900 p += srvstr_push(outbuf, p, fname2, -1, STR_TERMINATE|STR_CONVERT);
1901 set_message_end(outbuf, p);
1903 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1904 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1907 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1908 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1910 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1911 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1912 fname2, fsp->fd, createmode, (int)unixmode ) );
1914 END_PROFILE(SMBctemp);
1919 /*******************************************************************
1920 check if a user is allowed to delete a file
1921 ********************************************************************/
1922 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1924 SMB_STRUCT_STAT sbuf;
1927 if (!CAN_WRITE(conn)) return(False);
1929 if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False);
1930 fmode = dos_mode(conn,fname,&sbuf);
1931 if (fmode & aDIR) return(False);
1932 if (!lp_delete_readonly(SNUM(conn))) {
1933 if (fmode & aRONLY) return(False);
1935 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1937 if (!check_file_sharing(conn,fname,False)) return(False);
1941 /****************************************************************************
1942 The guts of the unlink command, split out so it may be called by the NT SMB
1944 ****************************************************************************/
1946 int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
1947 int dirtype, char *name)
1953 int error = ERRnoaccess;
1956 BOOL bad_path = False;
1958 SMB_STRUCT_STAT sbuf;
1960 *directory = *mask = 0;
1962 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1964 p = strrchr(name,'/');
1966 pstrcpy(directory,"./");
1970 pstrcpy(directory,name);
1975 * We should only check the mangled cache
1976 * here if unix_convert failed. This means
1977 * that the path in 'mask' doesn't exist
1978 * on the file system and so we need to look
1979 * for a possible mangle. This patch from
1980 * Tine Smukavec <valentin.smukavec@hermes.si>.
1983 if (!rc && is_mangled(mask))
1984 check_mangled_cache( mask );
1986 has_wild = ms_has_wild(mask);
1989 pstrcat(directory,"/");
1990 pstrcat(directory,mask);
1991 if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory))
1994 exists = vfs_file_exist(conn,directory,&sbuf);
1996 void *dirptr = NULL;
1999 if (check_name(directory,conn))
2000 dirptr = OpenDir(conn, directory, True);
2002 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2003 the pattern matches against the long name, otherwise the short name
2004 We don't implement this yet XXXX
2011 if (strequal(mask,"????????.???"))
2014 while ((dname = ReadDirName(dirptr)))
2017 pstrcpy(fname,dname);
2019 if(!mask_match(fname, mask, case_sensitive)) continue;
2021 error = ERRnoaccess;
2022 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2023 if (!can_delete(fname,conn,dirtype)) continue;
2024 if (!vfs_unlink(conn,fname)) count++;
2025 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2033 return(ERROR(ERRDOS,error));
2035 if((errno == ENOENT) && bad_path) {
2036 unix_ERR_class = ERRDOS;
2037 unix_ERR_code = ERRbadpath;
2039 return(UNIXERROR(ERRDOS,error));
2046 /****************************************************************************
2048 ****************************************************************************/
2050 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2055 START_PROFILE(SMBunlink);
2057 dirtype = SVAL(inbuf,smb_vwv0);
2059 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
2061 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
2063 DEBUG(3,("reply_unlink : %s\n",name));
2065 outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
2069 * Win2k needs a changenotify request response before it will
2070 * update after a rename..
2073 process_pending_change_notify_queue((time_t)0);
2075 outsize = set_message(outbuf,0,0,True);
2078 END_PROFILE(SMBunlink);
2083 /****************************************************************************
2084 reply to a readbraw (core+ protocol)
2085 ****************************************************************************/
2087 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2089 size_t maxcount,mincount;
2092 char *header = outbuf;
2095 START_PROFILE(SMBreadbraw);
2098 * Special check if an oplock break has been issued
2099 * and the readraw request croses on the wire, we must
2100 * return a zero length response here.
2103 if(global_oplock_break)
2105 _smb_setlen(header,0);
2106 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2107 DEBUG(5,("readbraw - oplock break finished\n"));
2108 END_PROFILE(SMBreadbraw);
2112 fsp = file_fsp(inbuf,smb_vwv0);
2114 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2116 * fsp could be NULL here so use the value from the packet. JRA.
2118 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2119 _smb_setlen(header,0);
2120 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2121 END_PROFILE(SMBreadbraw);
2125 CHECK_FSP(fsp,conn);
2127 flush_write_cache(fsp, READRAW_FLUSH);
2129 startpos = IVAL(inbuf,smb_vwv1);
2130 if(CVAL(inbuf,smb_wct) == 10) {
2132 * This is a large offset (64 bit) read.
2134 #ifdef LARGE_SMB_OFF_T
2136 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2138 #else /* !LARGE_SMB_OFF_T */
2141 * Ensure we haven't been sent a >32 bit offset.
2144 if(IVAL(inbuf,smb_vwv8) != 0) {
2145 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2146 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2147 _smb_setlen(header,0);
2148 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2149 END_PROFILE(SMBreadbraw);
2153 #endif /* LARGE_SMB_OFF_T */
2156 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2157 (double)startpos ));
2158 _smb_setlen(header,0);
2159 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2160 END_PROFILE(SMBreadbraw);
2164 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2165 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2167 /* ensure we don't overrun the packet size */
2168 maxcount = MIN(65535,maxcount);
2169 maxcount = MAX(mincount,maxcount);
2171 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK))
2173 SMB_OFF_T size = fsp->size;
2174 SMB_OFF_T sizeneeded = startpos + maxcount;
2176 if (size < sizeneeded)
2179 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2181 if (!fsp->can_write)
2185 nread = MIN(maxcount,(size - startpos));
2188 if (nread < mincount)
2191 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2192 fsp->fnum, (double)startpos,
2193 (int)maxcount, (int)mincount, (int)nread ) );
2197 BOOL seek_fail = False;
2199 _smb_setlen(header,nread);
2201 if ((nread-predict) > 0) {
2202 if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
2203 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2210 ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
2211 (SMB_OFF_T)(nread-predict),header,4+predict,
2216 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2217 fsp->fsp_name,startpos,nread,ret));
2219 #else /* UNSAFE_READRAW */
2220 ret = read_file(fsp,header+4,startpos,nread);
2221 if (ret < mincount) ret = 0;
2223 _smb_setlen(header,ret);
2224 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2225 #endif /* UNSAFE_READRAW */
2227 DEBUG(5,("readbraw finished\n"));
2228 END_PROFILE(SMBreadbraw);
2233 /****************************************************************************
2234 reply to a lockread (core+ protocol)
2235 ****************************************************************************/
2236 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2245 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2246 START_PROFILE(SMBlockread);
2248 CHECK_FSP(fsp,conn);
2252 release_level_2_oplocks_on_change(fsp);
2254 numtoread = SVAL(inbuf,smb_vwv1);
2255 startpos = IVAL(inbuf,smb_vwv2);
2257 outsize = set_message(outbuf,5,3,True);
2258 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2259 data = smb_buf(outbuf) + 3;
2262 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2263 * protocol request that predates the read/write lock concept.
2264 * Thus instead of asking for a read lock here we need to ask
2265 * for a write lock. JRA.
2268 if(!do_lock( fsp, conn, (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2269 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2271 * A blocking lock was requested. Package up
2272 * this smb into a queued request and push it
2273 * onto the blocking lock queue.
2275 if(push_blocking_lock_request(inbuf, length, -1, 0))
2276 END_PROFILE(SMBlockread);
2279 END_PROFILE(SMBlockread);
2280 return (ERROR(eclass,ecode));
2283 nread = read_file(fsp,data,startpos,numtoread);
2286 END_PROFILE(SMBlockread);
2287 return(UNIXERROR(ERRDOS,ERRnoaccess));
2291 SSVAL(outbuf,smb_vwv0,nread);
2292 SSVAL(outbuf,smb_vwv5,nread+3);
2293 SSVAL(smb_buf(outbuf),1,nread);
2295 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2296 fsp->fnum, (int)numtoread, (int)nread ) );
2298 END_PROFILE(SMBlockread);
2303 /****************************************************************************
2305 ****************************************************************************/
2307 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2314 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2315 START_PROFILE(SMBread);
2317 CHECK_FSP(fsp,conn);
2321 numtoread = SVAL(inbuf,smb_vwv1);
2322 startpos = IVAL(inbuf,smb_vwv2);
2324 outsize = set_message(outbuf,5,3,True);
2325 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2326 data = smb_buf(outbuf) + 3;
2328 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2329 END_PROFILE(SMBread);
2330 return(ERROR(ERRDOS,ERRlock));
2334 nread = read_file(fsp,data,startpos,numtoread);
2337 END_PROFILE(SMBread);
2338 return(UNIXERROR(ERRDOS,ERRnoaccess));
2342 SSVAL(outbuf,smb_vwv0,nread);
2343 SSVAL(outbuf,smb_vwv5,nread+3);
2344 CVAL(smb_buf(outbuf),0) = 1;
2345 SSVAL(smb_buf(outbuf),1,nread);
2347 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2348 fsp->fnum, (int)numtoread, (int)nread ) );
2350 END_PROFILE(SMBread);
2355 /****************************************************************************
2356 reply to a read and X
2357 ****************************************************************************/
2358 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2360 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2361 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2362 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2363 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2366 START_PROFILE(SMBreadX);
2368 /* If it's an IPC, pass off the pipe handler. */
2370 END_PROFILE(SMBreadX);
2371 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2374 CHECK_FSP(fsp,conn);
2378 set_message(outbuf,12,0,True);
2379 data = smb_buf(outbuf);
2381 if(CVAL(inbuf,smb_wct) == 12) {
2382 #ifdef LARGE_SMB_OFF_T
2384 * This is a large offset (64 bit) read.
2386 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2388 #else /* !LARGE_SMB_OFF_T */
2391 * Ensure we haven't been sent a >32 bit offset.
2394 if(IVAL(inbuf,smb_vwv10) != 0) {
2395 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2396 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2397 END_PROFILE(SMBreadX);
2398 return(ERROR(ERRDOS,ERRbadaccess));
2401 #endif /* LARGE_SMB_OFF_T */
2405 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2406 END_PROFILE(SMBreadX);
2407 return(ERROR(ERRDOS,ERRlock));
2409 nread = read_file(fsp,data,startpos,smb_maxcnt);
2412 END_PROFILE(SMBreadX);
2413 return(UNIXERROR(ERRDOS,ERRnoaccess));
2416 SSVAL(outbuf,smb_vwv5,nread);
2417 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2418 SSVAL(smb_buf(outbuf),-2,nread);
2420 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2421 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2423 END_PROFILE(SMBreadX);
2424 return chain_reply(inbuf,outbuf,length,bufsize);
2427 /****************************************************************************
2428 reply to a writebraw (core+ or LANMAN1.0 protocol)
2429 ****************************************************************************/
2431 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2434 ssize_t total_written=0;
2435 size_t numtowrite=0;
2440 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2442 START_PROFILE(SMBwritebraw);
2444 CHECK_FSP(fsp,conn);
2448 tcount = IVAL(inbuf,smb_vwv1);
2449 startpos = IVAL(inbuf,smb_vwv3);
2450 write_through = BITSETW(inbuf+smb_vwv7,0);
2452 /* We have to deal with slightly different formats depending
2453 on whether we are using the core+ or lanman1.0 protocol */
2454 if(Protocol <= PROTOCOL_COREPLUS) {
2455 numtowrite = SVAL(smb_buf(inbuf),-2);
2456 data = smb_buf(inbuf);
2458 numtowrite = SVAL(inbuf,smb_vwv10);
2459 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2462 /* force the error type */
2463 CVAL(inbuf,smb_com) = SMBwritec;
2464 CVAL(outbuf,smb_com) = SMBwritec;
2466 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2467 END_PROFILE(SMBwritebraw);
2468 return(ERROR(ERRDOS,ERRlock));
2472 nwritten = write_file(fsp,data,startpos,numtowrite);
2474 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2475 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2477 if (nwritten < numtowrite) {
2478 END_PROFILE(SMBwritebraw);
2479 return(UNIXERROR(ERRHRD,ERRdiskfull));
2482 total_written = nwritten;
2484 /* Return a message to the redirector to tell it
2485 to send more bytes */
2486 CVAL(outbuf,smb_com) = SMBwritebraw;
2487 SSVALS(outbuf,smb_vwv0,-1);
2488 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2489 send_smb(smbd_server_fd(),outbuf);
2491 /* Now read the raw data into the buffer and write it */
2492 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2493 exit_server("secondary writebraw failed");
2496 /* Even though this is not an smb message, smb_len
2497 returns the generic length of an smb message */
2498 numtowrite = smb_len(inbuf);
2500 if (tcount > nwritten+numtowrite) {
2501 DEBUG(3,("Client overestimated the write %d %d %d\n",
2502 (int)tcount,(int)nwritten,(int)numtowrite));
2505 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2506 (SMB_OFF_T)numtowrite,NULL,0,
2508 total_written += nwritten;
2510 /* Set up outbuf to return the correct return */
2511 outsize = set_message(outbuf,1,0,True);
2512 CVAL(outbuf,smb_com) = SMBwritec;
2513 SSVAL(outbuf,smb_vwv0,total_written);
2515 if (nwritten < (ssize_t)numtowrite) {
2516 CVAL(outbuf,smb_rcls) = ERRHRD;
2517 SSVAL(outbuf,smb_err,ERRdiskfull);
2520 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2521 lp_strict_sync(SNUM(conn)))
2522 sync_file(conn,fsp);
2524 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2525 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2527 /* we won't return a status if write through is not selected - this
2528 follows what WfWg does */
2529 END_PROFILE(SMBwritebraw);
2530 if (!write_through && total_written==tcount) {
2537 /****************************************************************************
2538 reply to a writeunlock (core+)
2539 ****************************************************************************/
2541 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2543 ssize_t nwritten = -1;
2549 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2551 START_PROFILE(SMBwriteunlock);
2553 CHECK_FSP(fsp,conn);
2557 numtowrite = SVAL(inbuf,smb_vwv1);
2558 startpos = IVAL(inbuf,smb_vwv2);
2559 data = smb_buf(inbuf) + 3;
2561 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2562 END_PROFILE(SMBwriteunlock);
2563 return(ERROR(ERRDOS,ERRlock));
2566 /* The special X/Open SMB protocol handling of
2567 zero length writes is *NOT* done for
2572 nwritten = write_file(fsp,data,startpos,numtowrite);
2574 if (lp_syncalways(SNUM(conn)))
2575 sync_file(conn,fsp);
2577 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2578 END_PROFILE(SMBwriteunlock);
2579 return(UNIXERROR(ERRDOS,ERRnoaccess));
2582 if(!do_unlock(fsp, conn, (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) {
2583 END_PROFILE(SMBwriteunlock);
2584 return(ERROR(eclass,ecode));
2587 outsize = set_message(outbuf,1,0,True);
2589 SSVAL(outbuf,smb_vwv0,nwritten);
2591 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2592 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2594 END_PROFILE(SMBwriteunlock);
2598 /****************************************************************************
2600 ****************************************************************************/
2601 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2604 ssize_t nwritten = -1;
2607 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2609 START_PROFILE(SMBwrite);
2611 /* If it's an IPC, pass off the pipe handler. */
2613 END_PROFILE(SMBwrite);
2614 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2617 CHECK_FSP(fsp,conn);
2621 numtowrite = SVAL(inbuf,smb_vwv1);
2622 startpos = IVAL(inbuf,smb_vwv2);
2623 data = smb_buf(inbuf) + 3;
2625 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2626 END_PROFILE(SMBwrite);
2627 return(ERROR(ERRDOS,ERRlock));
2630 /* X/Open SMB protocol says that if smb_vwv1 is
2631 zero then the file size should be extended or
2632 truncated to the size given in smb_vwv[2-3] */
2633 if(numtowrite == 0) {
2634 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2636 nwritten = write_file(fsp,data,startpos,numtowrite);
2638 if (lp_syncalways(SNUM(conn)))
2639 sync_file(conn,fsp);
2641 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2642 END_PROFILE(SMBwrite);
2643 return(UNIXERROR(ERRDOS,ERRnoaccess));
2646 outsize = set_message(outbuf,1,0,True);
2648 SSVAL(outbuf,smb_vwv0,nwritten);
2650 if (nwritten < (ssize_t)numtowrite) {
2651 CVAL(outbuf,smb_rcls) = ERRHRD;
2652 SSVAL(outbuf,smb_err,ERRdiskfull);
2655 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2656 fsp->fnum, (int)numtowrite, (int)nwritten));
2658 END_PROFILE(SMBwrite);
2663 /****************************************************************************
2664 reply to a write and X
2665 ****************************************************************************/
2666 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2668 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2669 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2670 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2671 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2672 ssize_t nwritten = -1;
2673 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2675 START_PROFILE(SMBwriteX);
2677 /* If it's an IPC, pass off the pipe handler. */
2679 END_PROFILE(SMBwriteX);
2680 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2683 CHECK_FSP(fsp,conn);
2687 if(smb_doff > smb_len(inbuf)) {
2688 END_PROFILE(SMBwriteX);
2689 return(ERROR(ERRDOS,ERRbadmem));
2692 data = smb_base(inbuf) + smb_doff;
2694 if(CVAL(inbuf,smb_wct) == 14) {
2695 #ifdef LARGE_SMB_OFF_T
2697 * This is a large offset (64 bit) write.
2699 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2701 #else /* !LARGE_SMB_OFF_T */
2704 * Ensure we haven't been sent a >32 bit offset.
2707 if(IVAL(inbuf,smb_vwv12) != 0) {
2708 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2709 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2710 END_PROFILE(SMBwriteX);
2711 return(ERROR(ERRDOS,ERRbadaccess));
2714 #endif /* LARGE_SMB_OFF_T */
2717 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2718 END_PROFILE(SMBwriteX);
2719 return(ERROR(ERRDOS,ERRlock));
2722 /* X/Open SMB protocol says that, unlike SMBwrite
2723 if the length is zero then NO truncation is
2724 done, just a write of zero. To truncate a file,
2729 nwritten = write_file(fsp,data,startpos,numtowrite);
2731 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2732 END_PROFILE(SMBwriteX);
2733 return(UNIXERROR(ERRDOS,ERRnoaccess));
2736 set_message(outbuf,6,0,True);
2738 SSVAL(outbuf,smb_vwv2,nwritten);
2740 if (nwritten < (ssize_t)numtowrite) {
2741 CVAL(outbuf,smb_rcls) = ERRHRD;
2742 SSVAL(outbuf,smb_err,ERRdiskfull);
2745 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2746 fsp->fnum, (int)numtowrite, (int)nwritten));
2748 if (lp_syncalways(SNUM(conn)) || write_through)
2749 sync_file(conn,fsp);
2751 END_PROFILE(SMBwriteX);
2752 return chain_reply(inbuf,outbuf,length,bufsize);
2756 /****************************************************************************
2758 ****************************************************************************/
2760 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2766 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2767 START_PROFILE(SMBlseek);
2769 CHECK_FSP(fsp,conn);
2772 flush_write_cache(fsp, SEEK_FLUSH);
2774 mode = SVAL(inbuf,smb_vwv1) & 3;
2775 startpos = IVALS(inbuf,smb_vwv2);
2778 case 0: umode = SEEK_SET; break;
2779 case 1: umode = SEEK_CUR; break;
2780 case 2: umode = SEEK_END; break;
2782 umode = SEEK_SET; break;
2785 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2787 * Check for the special case where a seek before the start
2788 * of the file sets the offset to zero. Added in the CIFS spec,
2792 if(errno == EINVAL) {
2793 SMB_OFF_T current_pos = startpos;
2795 if(umode == SEEK_CUR) {
2797 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2798 END_PROFILE(SMBlseek);
2799 return(UNIXERROR(ERRDOS,ERRnoaccess));
2802 current_pos += startpos;
2804 } else if (umode == SEEK_END) {
2806 SMB_STRUCT_STAT sbuf;
2808 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2809 END_PROFILE(SMBlseek);
2810 return(UNIXERROR(ERRDOS,ERRnoaccess));
2813 current_pos += sbuf.st_size;
2817 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2821 END_PROFILE(SMBlseek);
2822 return(UNIXERROR(ERRDOS,ERRnoaccess));
2828 outsize = set_message(outbuf,2,0,True);
2829 SIVAL(outbuf,smb_vwv0,res);
2831 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2832 fsp->fnum, (double)startpos, (double)res, mode));
2834 END_PROFILE(SMBlseek);
2838 /****************************************************************************
2840 ****************************************************************************/
2842 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2844 int outsize = set_message(outbuf,0,0,True);
2845 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2846 START_PROFILE(SMBflush);
2849 CHECK_FSP(fsp,conn);
2854 file_sync_all(conn);
2856 sync_file(conn,fsp);
2859 DEBUG(3,("flush\n"));
2860 END_PROFILE(SMBflush);
2865 /****************************************************************************
2867 ****************************************************************************/
2868 int reply_exit(connection_struct *conn,
2869 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2872 START_PROFILE(SMBexit);
2873 outsize = set_message(outbuf,0,0,True);
2875 DEBUG(3,("exit\n"));
2877 END_PROFILE(SMBexit);
2882 /****************************************************************************
2883 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2884 ****************************************************************************/
2885 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2890 int32 eclass = 0, err = 0;
2891 files_struct *fsp = NULL;
2892 START_PROFILE(SMBclose);
2894 outsize = set_message(outbuf,0,0,True);
2896 /* If it's an IPC, pass off to the pipe handler. */
2898 END_PROFILE(SMBclose);
2899 return reply_pipe_close(conn, inbuf,outbuf);
2902 fsp = file_fsp(inbuf,smb_vwv0);
2905 * We can only use CHECK_FSP if we know it's not a directory.
2908 if(!fsp || (fsp->conn != conn)) {
2909 END_PROFILE(SMBclose);
2910 return(ERROR(ERRDOS,ERRbadfid));
2913 if(HAS_CACHED_ERROR(fsp)) {
2914 eclass = fsp->wbmpx_ptr->wr_errclass;
2915 err = fsp->wbmpx_ptr->wr_error;
2918 if(fsp->is_directory || fsp->stat_open) {
2920 * Special case - close NT SMB directory or stat file
2923 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2924 close_file(fsp,True);
2927 * Close ordinary file.
2932 * If there was a modify time outstanding,
2933 * try and set it here.
2935 if(fsp->pending_modtime)
2936 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2939 * Now take care of any time sent in the close.
2941 mtime = make_unix_date3(inbuf+smb_vwv1);
2943 /* try and set the date */
2944 set_filetime(conn, fsp->fsp_name,mtime);
2946 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2948 conn->num_files_open));
2951 * close_file() returns the unix errno if an error
2952 * was detected on close - normally this is due to
2953 * a disk full error. If not then it was probably an I/O error.
2956 if((close_err = close_file(fsp,True)) != 0) {
2958 END_PROFILE(SMBclose);
2959 return (UNIXERROR(ERRHRD,ERRgeneral));
2963 /* We have a cached error */
2965 END_PROFILE(SMBclose);
2966 return(ERROR(eclass,err));
2969 END_PROFILE(SMBclose);
2974 /****************************************************************************
2975 reply to a writeclose (Core+ protocol)
2976 ****************************************************************************/
2978 int reply_writeclose(connection_struct *conn,
2979 char *inbuf,char *outbuf, int size, int dum_buffsize)
2982 ssize_t nwritten = -1;
2988 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2989 START_PROFILE(SMBwriteclose);
2991 CHECK_FSP(fsp,conn);
2995 numtowrite = SVAL(inbuf,smb_vwv1);
2996 startpos = IVAL(inbuf,smb_vwv2);
2997 mtime = make_unix_date3(inbuf+smb_vwv4);
2998 data = smb_buf(inbuf) + 1;
3000 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3001 END_PROFILE(SMBwriteclose);
3002 return(ERROR(ERRDOS,ERRlock));
3005 nwritten = write_file(fsp,data,startpos,numtowrite);
3007 set_filetime(conn, fsp->fsp_name,mtime);
3009 close_err = close_file(fsp,True);
3011 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3012 fsp->fnum, (int)numtowrite, (int)nwritten,
3013 conn->num_files_open));
3015 if (nwritten <= 0) {
3016 END_PROFILE(SMBwriteclose);
3017 return(UNIXERROR(ERRDOS,ERRnoaccess));
3020 if(close_err != 0) {
3022 END_PROFILE(SMBwriteclose);
3023 return(UNIXERROR(ERRHRD,ERRgeneral));
3026 outsize = set_message(outbuf,1,0,True);
3028 SSVAL(outbuf,smb_vwv0,nwritten);
3029 END_PROFILE(SMBwriteclose);
3034 /****************************************************************************
3036 ****************************************************************************/
3037 int reply_lock(connection_struct *conn,
3038 char *inbuf,char *outbuf, int length, int dum_buffsize)
3040 int outsize = set_message(outbuf,0,0,True);
3041 SMB_BIG_UINT count,offset;
3044 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3045 START_PROFILE(SMBlock);
3047 CHECK_FSP(fsp,conn);
3050 release_level_2_oplocks_on_change(fsp);
3052 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3053 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3055 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3056 fsp->fd, fsp->fnum, (double)offset, (double)count));
3058 if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) {
3059 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
3061 * A blocking lock was requested. Package up
3062 * this smb into a queued request and push it
3063 * onto the blocking lock queue.
3065 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
3066 END_PROFILE(SMBlock);
3070 END_PROFILE(SMBlock);
3071 return (ERROR(eclass,ecode));
3074 END_PROFILE(SMBlock);
3079 /****************************************************************************
3081 ****************************************************************************/
3082 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3084 int outsize = set_message(outbuf,0,0,True);
3085 SMB_BIG_UINT count,offset;
3088 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3089 START_PROFILE(SMBunlock);
3091 CHECK_FSP(fsp,conn);
3094 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3095 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3097 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode)) {
3098 END_PROFILE(SMBunlock);
3099 return (ERROR(eclass,ecode));
3102 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3103 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3105 END_PROFILE(SMBunlock);
3110 /****************************************************************************
3112 ****************************************************************************/
3113 int reply_tdis(connection_struct *conn,
3114 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3116 int outsize = set_message(outbuf,0,0,True);
3118 START_PROFILE(SMBtdis);
3120 vuid = SVAL(inbuf,smb_uid);
3123 DEBUG(4,("Invalid connection in tdis\n"));
3124 END_PROFILE(SMBtdis);
3125 return(ERROR(ERRSRV,ERRinvnid));
3130 close_cnum(conn,vuid);
3132 END_PROFILE(SMBtdis);
3138 /****************************************************************************
3140 ****************************************************************************/
3141 int reply_echo(connection_struct *conn,
3142 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3144 int smb_reverb = SVAL(inbuf,smb_vwv0);
3146 unsigned int data_len = smb_buflen(inbuf);
3147 int outsize = set_message(outbuf,1,data_len,True);
3148 START_PROFILE(SMBecho);
3150 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3152 /* copy any incoming data back out */
3154 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3156 if (smb_reverb > 100) {
3157 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3161 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3162 SSVAL(outbuf,smb_vwv0,seq_num);
3164 smb_setlen(outbuf,outsize - 4);
3166 send_smb(smbd_server_fd(),outbuf);
3169 DEBUG(3,("echo %d times\n", smb_reverb));
3173 END_PROFILE(SMBecho);
3178 /****************************************************************************
3179 reply to a printopen
3180 ****************************************************************************/
3181 int reply_printopen(connection_struct *conn,
3182 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3186 START_PROFILE(SMBsplopen);
3188 if (!CAN_PRINT(conn)) {
3189 END_PROFILE(SMBsplopen);
3190 return(ERROR(ERRDOS,ERRnoaccess));
3193 /* Open for exclusive use, write only. */
3194 fsp = print_fsp_open(conn);
3197 END_PROFILE(SMBsplopen);
3198 return(UNIXERROR(ERRDOS,ERRnoaccess));
3201 outsize = set_message(outbuf,1,0,True);
3202 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3204 DEBUG(3,("openprint fd=%d fnum=%d\n",
3205 fsp->fd, fsp->fnum));
3207 END_PROFILE(SMBsplopen);
3212 /****************************************************************************
3213 reply to a printclose
3214 ****************************************************************************/
3215 int reply_printclose(connection_struct *conn,
3216 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3218 int outsize = set_message(outbuf,0,0,True);
3219 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3221 START_PROFILE(SMBsplclose);
3223 CHECK_FSP(fsp,conn);
3226 if (!CAN_PRINT(conn)) {
3227 END_PROFILE(SMBsplclose);
3228 return(ERROR(ERRDOS,ERRnoaccess));
3231 DEBUG(3,("printclose fd=%d fnum=%d\n",
3232 fsp->fd,fsp->fnum));
3234 close_err = close_file(fsp,True);
3236 if(close_err != 0) {
3238 END_PROFILE(SMBsplclose);
3239 return(UNIXERROR(ERRHRD,ERRgeneral));
3242 END_PROFILE(SMBsplclose);
3247 /****************************************************************************
3248 reply to a printqueue
3249 ****************************************************************************/
3250 int reply_printqueue(connection_struct *conn,
3251 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3253 int outsize = set_message(outbuf,2,3,True);
3254 int max_count = SVAL(inbuf,smb_vwv0);
3255 int start_index = SVAL(inbuf,smb_vwv1);
3256 START_PROFILE(SMBsplretq);
3258 /* we used to allow the client to get the cnum wrong, but that
3259 is really quite gross and only worked when there was only
3260 one printer - I think we should now only accept it if they
3261 get it right (tridge) */
3262 if (!CAN_PRINT(conn)) {
3263 END_PROFILE(SMBsplretq);
3264 return(ERROR(ERRDOS,ERRnoaccess));
3267 SSVAL(outbuf,smb_vwv0,0);
3268 SSVAL(outbuf,smb_vwv1,0);
3269 CVAL(smb_buf(outbuf),0) = 1;
3270 SSVAL(smb_buf(outbuf),1,0);
3272 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3273 start_index, max_count));
3276 print_queue_struct *queue = NULL;
3277 char *p = smb_buf(outbuf) + 3;
3278 int count = print_queue_status(SNUM(conn), &queue,NULL);
3279 int num_to_get = ABS(max_count);
3280 int first = (max_count>0?start_index:start_index+max_count+1);
3286 num_to_get = MIN(num_to_get,count-first);
3289 for (i=first;i<first+num_to_get;i++) {
3290 put_dos_date2(p,0,queue[i].time);
3291 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3292 SSVAL(p,5, queue[i].job);
3293 SIVAL(p,7,queue[i].size);
3295 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_CONVERT|STR_ASCII);
3300 outsize = set_message(outbuf,2,28*count+3,False);
3301 SSVAL(outbuf,smb_vwv0,count);
3302 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3303 CVAL(smb_buf(outbuf),0) = 1;
3304 SSVAL(smb_buf(outbuf),1,28*count);
3307 if (queue) free(queue);
3309 DEBUG(3,("%d entries returned in queue\n",count));
3312 END_PROFILE(SMBsplretq);
3317 /****************************************************************************
3318 reply to a printwrite
3319 ****************************************************************************/
3320 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3323 int outsize = set_message(outbuf,0,0,True);
3325 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3326 START_PROFILE(SMBsplwr);
3328 if (!CAN_PRINT(conn)) {
3329 END_PROFILE(SMBsplwr);
3330 return(ERROR(ERRDOS,ERRnoaccess));
3333 CHECK_FSP(fsp,conn);
3337 numtowrite = SVAL(smb_buf(inbuf),1);
3338 data = smb_buf(inbuf) + 3;
3340 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3341 END_PROFILE(SMBsplwr);
3342 return(UNIXERROR(ERRDOS,ERRnoaccess));
3345 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3347 END_PROFILE(SMBsplwr);
3352 /****************************************************************************
3353 The guts of the mkdir command, split out so it may be called by the NT SMB
3355 ****************************************************************************/
3356 int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
3358 BOOL bad_path = False;
3359 SMB_STRUCT_STAT sbuf;
3362 unix_convert(directory,conn,0,&bad_path,&sbuf);
3364 if (check_name(directory, conn))
3365 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3369 if((errno == ENOENT) && bad_path)
3371 unix_ERR_class = ERRDOS;
3372 unix_ERR_code = ERRbadpath;
3374 return(UNIXERROR(ERRDOS,ERRnoaccess));
3380 /****************************************************************************
3382 ****************************************************************************/
3383 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3387 START_PROFILE(SMBmkdir);
3389 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3391 outsize=mkdir_internal(conn, inbuf, outbuf, directory);
3393 outsize = set_message(outbuf,0,0,True);
3395 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3397 END_PROFILE(SMBmkdir);
3401 /****************************************************************************
3402 Static function used by reply_rmdir to delete an entire directory
3404 ****************************************************************************/
3406 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3410 void *dirptr = OpenDir(NULL, directory, False);
3415 while((dname = ReadDirName(dirptr)))
3420 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3423 /* Construct the full name. */
3424 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3430 pstrcpy(fullname, directory);
3431 pstrcat(fullname, "/");
3432 pstrcat(fullname, dname);
3434 if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname,False), &st) != 0)
3440 if(st.st_mode & S_IFDIR)
3442 if(recursive_rmdir(conn, fullname)!=0)
3447 if(vfs_rmdir(conn,fullname) != 0)
3453 else if(vfs_unlink(conn,fullname) != 0)
3463 /****************************************************************************
3464 The internals of the rmdir code - called elsewhere.
3465 ****************************************************************************/
3467 BOOL rmdir_internals(connection_struct *conn, char *directory)
3471 ok = (vfs_rmdir(conn,directory) == 0);
3472 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3475 * Check to see if the only thing in this directory are
3476 * vetoed files/directories. If so then delete them and
3477 * retry. If we fail to delete any of them (and we *don't*
3478 * do a recursive delete) then fail the rmdir.
3480 BOOL all_veto_files = True;
3482 void *dirptr = OpenDir(conn, directory, False);
3486 int dirpos = TellDir(dirptr);
3487 while ((dname = ReadDirName(dirptr)))
3489 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3491 if(!IS_VETO_PATH(conn, dname))
3493 all_veto_files = False;
3499 SeekDir(dirptr,dirpos);
3500 while ((dname = ReadDirName(dirptr)))
3505 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3508 /* Construct the full name. */
3509 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3514 pstrcpy(fullname, directory);
3515 pstrcat(fullname, "/");
3516 pstrcat(fullname, dname);
3518 if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname, False), &st) != 0)
3520 if(st.st_mode & S_IFDIR)
3522 if(lp_recursive_veto_delete(SNUM(conn)))
3524 if(recursive_rmdir(conn, fullname) != 0)
3527 if(vfs_rmdir(conn,fullname) != 0)
3530 else if(vfs_unlink(conn,fullname) != 0)
3534 /* Retry the rmdir */
3535 ok = (vfs_rmdir(conn,directory) == 0);
3545 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3546 directory,strerror(errno)));
3551 /****************************************************************************
3553 ****************************************************************************/
3555 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3560 BOOL bad_path = False;
3561 SMB_STRUCT_STAT sbuf;
3562 START_PROFILE(SMBrmdir);
3564 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3566 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3568 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3570 if (check_name(directory,conn))
3572 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3573 ok = rmdir_internals(conn, directory);
3578 if((errno == ENOENT) && bad_path)
3580 unix_ERR_class = ERRDOS;
3581 unix_ERR_code = ERRbadpath;
3583 END_PROFILE(SMBrmdir);
3584 return(UNIXERROR(ERRDOS,ERRbadpath));
3587 outsize = set_message(outbuf,0,0,True);
3589 DEBUG( 3, ( "rmdir %s\n", directory ) );
3591 END_PROFILE(SMBrmdir);
3596 /*******************************************************************
3597 resolve wildcards in a filename rename
3598 ********************************************************************/
3599 static BOOL resolve_wildcards(char *name1,char *name2)
3601 fstring root1,root2;
3605 name1 = strrchr(name1,'/');
3606 name2 = strrchr(name2,'/');
3608 if (!name1 || !name2) return(False);
3610 fstrcpy(root1,name1);
3611 fstrcpy(root2,name2);
3612 p = strrchr(root1,'.');
3619 p = strrchr(root2,'.');
3651 pstrcpy(name2,root2);
3654 pstrcat(name2,ext2);
3660 /*******************************************************************
3661 check if a user is allowed to rename a file
3662 ********************************************************************/
3663 static BOOL can_rename(char *fname,connection_struct *conn)
3665 SMB_STRUCT_STAT sbuf;
3667 if (!CAN_WRITE(conn)) return(False);
3669 if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False);
3670 if (!check_file_sharing(conn,fname,True)) return(False);
3674 /****************************************************************************
3675 The guts of the rename command, split out so it may be called by the NT SMB
3677 ****************************************************************************/
3678 int rename_internals(connection_struct *conn,
3679 char *inbuf, char *outbuf, char *name,
3680 char *newname, BOOL replace_if_exists)
3684 pstring newname_last_component;
3687 BOOL bad_path1 = False;
3688 BOOL bad_path2 = False;
3690 int error = ERRnoaccess;
3693 SMB_STRUCT_STAT sbuf1, sbuf2;
3696 *directory = *mask = 0;
3698 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3699 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3702 * Split the old name into directory and last component
3703 * strings. Note that unix_convert may have stripped off a
3704 * leading ./ from both name and newname if the rename is
3705 * at the root of the share. We need to make sure either both
3706 * name and newname contain a / character or neither of them do
3707 * as this is checked in resolve_wildcards().
3710 p = strrchr(name,'/');
3712 pstrcpy(directory,".");
3716 pstrcpy(directory,name);
3718 *p = '/'; /* Replace needed for exceptional test below. */
3722 * We should only check the mangled cache
3723 * here if unix_convert failed. This means
3724 * that the path in 'mask' doesn't exist
3725 * on the file system and so we need to look
3726 * for a possible mangle. This patch from
3727 * Tine Smukavec <valentin.smukavec@hermes.si>.
3730 if (!rc && is_mangled(mask))
3731 check_mangled_cache( mask );
3733 has_wild = ms_has_wild(mask);
3737 * No wildcards - just process the one file.
3739 BOOL is_short_name = is_8_3(name, True);
3741 /* Add a terminating '/' to the directory name. */
3742 pstrcat(directory,"/");
3743 pstrcat(directory,mask);
3745 /* Ensure newname contains a '/' also */
3746 if(strrchr(newname,'/') == 0) {
3749 pstrcpy(tmpstr, "./");
3750 pstrcat(tmpstr, newname);
3751 pstrcpy(newname, tmpstr);
3754 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",
3755 case_sensitive, case_preserve, short_case_preserve, directory,
3756 newname, newname_last_component, is_short_name));
3759 * Check for special case with case preserving and not
3760 * case sensitive, if directory and newname are identical,
3761 * and the old last component differs from the original
3762 * last component only by case, then we should allow
3763 * the rename (user is trying to change the case of the
3766 if((case_sensitive == False) &&
3767 (((case_preserve == True) &&
3768 (is_short_name == False)) ||
3769 ((short_case_preserve == True) &&
3770 (is_short_name == True))) &&
3771 strcsequal(directory, newname)) {
3772 pstring newname_modified_last_component;
3775 * Get the last component of the modified name.
3776 * Note that we guarantee that newname contains a '/'
3779 p = strrchr(newname,'/');
3780 pstrcpy(newname_modified_last_component,p+1);
3782 if(strcsequal(newname_modified_last_component,
3783 newname_last_component) == False) {
3785 * Replace the modified last component with
3788 pstrcpy(p+1, newname_last_component);
3792 pstrcpy(zdirectory, dos_to_unix(directory, False));
3793 if(replace_if_exists) {
3795 * NT SMB specific flag - rename can overwrite
3796 * file with the same name so don't check for
3800 if(resolve_wildcards(directory,newname) &&
3801 can_rename(directory,conn) &&
3802 !conn->vfs_ops.rename(conn,zdirectory,
3803 dos_to_unix(newname,False)))
3806 if (resolve_wildcards(directory,newname) &&
3807 can_rename(directory,conn) &&
3808 !vfs_file_exist(conn,newname,NULL) &&
3809 !conn->vfs_ops.rename(conn,zdirectory,
3810 dos_to_unix(newname,False)))
3814 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3815 directory,newname));
3817 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3818 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3824 * Wildcards - process each file that matches.
3826 void *dirptr = NULL;
3830 if (check_name(directory,conn))
3831 dirptr = OpenDir(conn, directory, True);
3836 if (strequal(mask,"????????.???"))
3839 while ((dname = ReadDirName(dirptr))) {
3842 pstrcpy(fname,dname);
3844 if(!mask_match(fname, mask, case_sensitive))
3847 error = ERRnoaccess;
3848 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3849 if (!can_rename(fname,conn)) {
3850 DEBUG(6,("rename %s refused\n", fname));
3853 pstrcpy(destname,newname);
3855 if (!resolve_wildcards(fname,destname)) {
3856 DEBUG(6,("resolve_wildcards %s %s failed\n",
3861 if (!replace_if_exists &&
3862 vfs_file_exist(conn,destname, NULL)) {
3863 DEBUG(6,("file_exist %s\n", destname));
3868 if (!conn->vfs_ops.rename(conn,dos_to_unix(fname,False),
3869 dos_to_unix(destname,False)))
3871 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3879 return(ERROR(ERRDOS,error));
3881 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3882 unix_ERR_class = ERRDOS;
3883 unix_ERR_code = ERRbadpath;
3885 return(UNIXERROR(ERRDOS,error));
3892 /****************************************************************************
3894 ****************************************************************************/
3896 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3903 START_PROFILE(SMBmv);
3905 p = smb_buf(inbuf) + 1;
3906 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3908 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3910 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3911 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3913 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3915 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3919 * Win2k needs a changenotify request response before it will
3920 * update after a rename..
3923 process_pending_change_notify_queue((time_t)0);
3925 outsize = set_message(outbuf,0,0,True);
3932 /*******************************************************************
3933 copy a file as part of a reply_copy
3934 ******************************************************************/
3936 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3937 int count,BOOL target_is_directory, int *err_ret)
3940 SMB_STRUCT_STAT src_sbuf, sbuf2;
3942 files_struct *fsp1,*fsp2;
3947 pstrcpy(dest,dest1);
3948 if (target_is_directory) {
3949 char *p = strrchr(src,'/');
3958 if (!vfs_file_exist(conn,src,&src_sbuf))
3961 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3962 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3968 if (!target_is_directory && count)
3969 ofun = FILE_EXISTS_OPEN;
3971 vfs_stat(conn,dest,&sbuf2);
3972 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3973 ofun,src_sbuf.st_mode,0,&Access,&action);
3976 close_file(fsp1,False);
3980 if ((ofun&3) == 1) {
3981 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3982 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3985 * Stop the copy from occurring.
3988 src_sbuf.st_size = 0;
3992 if (src_sbuf.st_size)
3993 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
3995 close_file(fsp1,False);
3997 * As we are opening fsp1 read-only we only expect
3998 * an error on close on fsp2 if we are out of space.
3999 * Thus we don't look at the error return from the
4002 *err_ret = close_file(fsp2,False);
4004 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4009 /****************************************************************************
4010 reply to a file copy.
4011 ****************************************************************************/
4012 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4017 pstring mask,newname;
4020 int error = ERRnoaccess;
4024 int tid2 = SVAL(inbuf,smb_vwv0);
4025 int ofun = SVAL(inbuf,smb_vwv1);
4026 int flags = SVAL(inbuf,smb_vwv2);
4027 BOOL target_is_directory=False;
4028 BOOL bad_path1 = False;
4029 BOOL bad_path2 = False;
4031 SMB_STRUCT_STAT sbuf1, sbuf2;
4032 START_PROFILE(SMBcopy);
4034 *directory = *mask = 0;
4037 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
4038 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
4040 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4042 if (tid2 != conn->cnum) {
4043 /* can't currently handle inter share copies XXXX */
4044 DEBUG(3,("Rejecting inter-share copy\n"));
4045 END_PROFILE(SMBcopy);
4046 return(ERROR(ERRSRV,ERRinvdevice));
4049 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4050 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4052 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4053 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4055 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4057 if ((flags&1) && target_is_directory) {
4058 END_PROFILE(SMBcopy);
4059 return(ERROR(ERRDOS,ERRbadfile));
4062 if ((flags&2) && !target_is_directory) {
4063 END_PROFILE(SMBcopy);
4064 return(ERROR(ERRDOS,ERRbadpath));
4067 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4068 /* wants a tree copy! XXXX */
4069 DEBUG(3,("Rejecting tree copy\n"));
4070 END_PROFILE(SMBcopy);
4071 return(ERROR(ERRSRV,ERRerror));
4074 p = strrchr(name,'/');
4076 pstrcpy(directory,"./");
4080 pstrcpy(directory,name);
4085 * We should only check the mangled cache
4086 * here if unix_convert failed. This means
4087 * that the path in 'mask' doesn't exist
4088 * on the file system and so we need to look
4089 * for a possible mangle. This patch from
4090 * Tine Smukavec <valentin.smukavec@hermes.si>.
4093 if (!rc && is_mangled(mask))
4094 check_mangled_cache( mask );
4096 has_wild = ms_has_wild(mask);
4099 pstrcat(directory,"/");
4100 pstrcat(directory,mask);
4101 if (resolve_wildcards(directory,newname) &&
4102 copy_file(directory,newname,conn,ofun,
4103 count,target_is_directory,&err)) count++;
4106 END_PROFILE(SMBcopy);
4107 return(UNIXERROR(ERRHRD,ERRgeneral));
4109 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4111 void *dirptr = NULL;
4115 if (check_name(directory,conn))
4116 dirptr = OpenDir(conn, directory, True);
4121 if (strequal(mask,"????????.???"))
4124 while ((dname = ReadDirName(dirptr))) {
4126 pstrcpy(fname,dname);
4128 if(!mask_match(fname, mask, case_sensitive))
4131 error = ERRnoaccess;
4132 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4133 pstrcpy(destname,newname);
4134 if (resolve_wildcards(fname,destname) &&
4135 copy_file(fname,destname,conn,ofun,
4136 count,target_is_directory,&err)) count++;
4137 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4145 /* Error on close... */
4147 END_PROFILE(SMBcopy);
4148 return(UNIXERROR(ERRHRD,ERRgeneral));
4152 END_PROFILE(SMBcopy);
4153 return(ERROR(ERRDOS,error));
4156 if((errno == ENOENT) && (bad_path1 || bad_path2))
4158 unix_ERR_class = ERRDOS;
4159 unix_ERR_code = ERRbadpath;
4161 END_PROFILE(SMBcopy);
4162 return(UNIXERROR(ERRDOS,error));
4166 outsize = set_message(outbuf,1,0,True);
4167 SSVAL(outbuf,smb_vwv0,count);
4169 END_PROFILE(SMBcopy);
4173 /****************************************************************************
4175 ****************************************************************************/
4176 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4182 START_PROFILE(pathworks_setdir);
4185 if (!CAN_SETDIR(snum)) {
4186 END_PROFILE(pathworks_setdir);
4187 return(ERROR(ERRDOS,ERRnoaccess));
4190 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE|STR_CONVERT);
4192 if (strlen(newdir) == 0) {
4195 ok = vfs_directory_exist(conn,newdir,NULL);
4197 string_set(&conn->connectpath,newdir);
4202 END_PROFILE(pathworks_setdir);
4203 return(ERROR(ERRDOS,ERRbadpath));
4206 outsize = set_message(outbuf,0,0,True);
4207 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4209 DEBUG(3,("setdir %s\n", newdir));
4211 END_PROFILE(pathworks_setdir);
4215 /****************************************************************************
4216 Get a lock count, dealing with large count requests.
4217 ****************************************************************************/
4219 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4221 SMB_BIG_UINT count = 0;
4223 if(!large_file_format) {
4224 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4227 #if defined(HAVE_LONGLONG)
4228 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4229 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4230 #else /* HAVE_LONGLONG */
4233 * NT4.x seems to be broken in that it sends large file (64 bit)
4234 * lockingX calls even if the CAP_LARGE_FILES was *not*
4235 * negotiated. For boxes without large unsigned ints truncate the
4236 * lock count by dropping the top 32 bits.
4239 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4240 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4241 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4242 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4243 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4246 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4247 #endif /* HAVE_LONGLONG */
4253 /****************************************************************************
4254 Get a lock offset, dealing with large offset requests.
4255 ****************************************************************************/
4257 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4259 SMB_BIG_UINT offset = 0;
4263 if(!large_file_format) {
4264 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4267 #if defined(HAVE_LONGLONG)
4268 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4269 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4270 #else /* HAVE_LONGLONG */
4273 * NT4.x seems to be broken in that it sends large file (64 bit)
4274 * lockingX calls even if the CAP_LARGE_FILES was *not*
4275 * negotiated. For boxes without large unsigned ints mangle the
4276 * lock offset by mapping the top 32 bits onto the lower 32.
4279 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4280 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4281 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4284 if((new_low = map_lock_offset(high, low)) == 0) {
4286 return (SMB_BIG_UINT)-1;
4289 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4290 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4291 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4292 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4295 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4296 #endif /* HAVE_LONGLONG */
4302 /****************************************************************************
4303 reply to a lockingX request
4304 ****************************************************************************/
4306 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4308 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4309 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4310 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4311 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4312 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4313 SMB_BIG_UINT count = 0, offset = 0;
4314 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4317 uint32 ecode=0, dummy2;
4318 int eclass=0, dummy1;
4319 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4321 START_PROFILE(SMBlockingX);
4323 CHECK_FSP(fsp,conn);
4326 data = smb_buf(inbuf);
4328 /* Check if this is an oplock break on a file
4329 we have granted an oplock on.
4331 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4333 /* Client can insist on breaking to none. */
4334 BOOL break_to_none = (oplocklevel == 0);
4336 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4337 fsp->fnum, (unsigned int)oplocklevel ));
4340 * Make sure we have granted an exclusive or batch oplock on this file.
4343 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4345 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4346 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4348 /* if this is a pure oplock break request then don't send a reply */
4349 if (num_locks == 0 && num_ulocks == 0) {
4350 END_PROFILE(SMBlockingX);
4353 END_PROFILE(SMBlockingX);
4354 return ERROR(ERRDOS,ERRlock);
4358 if (remove_oplock(fsp, break_to_none) == False) {
4359 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4363 /* if this is a pure oplock break request then don't send a reply */
4364 if (num_locks == 0 && num_ulocks == 0)
4366 /* Sanity check - ensure a pure oplock break is not a
4368 if(CVAL(inbuf,smb_vwv0) != 0xff)
4369 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4370 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4371 END_PROFILE(SMBlockingX);
4377 * We do this check *after* we have checked this is not a oplock break
4378 * response message. JRA.
4381 release_level_2_oplocks_on_change(fsp);
4383 /* Data now points at the beginning of the list
4384 of smb_unlkrng structs */
4385 for(i = 0; i < (int)num_ulocks; i++) {
4386 count = get_lock_count( data, i, large_file_format);
4387 offset = get_lock_offset( data, i, large_file_format, &err);
4390 * There is no error code marked "stupid client bug".... :-).
4393 END_PROFILE(SMBlockingX);
4394 return ERROR(ERRDOS,ERRnoaccess);
4397 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
4398 (double)offset, (double)count, fsp->fsp_name ));
4400 if(!do_unlock(fsp,conn,count,offset, &eclass, &ecode)) {
4401 END_PROFILE(SMBlockingX);
4402 return ERROR(eclass,ecode);
4406 /* Setup the timeout in seconds. */
4407 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4409 /* Now do any requested locks */
4410 data += ((large_file_format ? 20 : 10)*num_ulocks);
4412 /* Data now points at the beginning of the list
4413 of smb_lkrng structs */
4415 for(i = 0; i < (int)num_locks; i++) {
4416 count = get_lock_count( data, i, large_file_format);
4417 offset = get_lock_offset( data, i, large_file_format, &err);
4420 * There is no error code marked "stupid client bug".... :-).
4423 END_PROFILE(SMBlockingX);
4424 return ERROR(ERRDOS,ERRnoaccess);
4427 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
4428 (double)offset, (double)count, fsp->fsp_name ));
4430 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4432 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4434 * A blocking lock was requested. Package up
4435 * this smb into a queued request and push it
4436 * onto the blocking lock queue.
4438 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4439 END_PROFILE(SMBlockingX);
4447 /* If any of the above locks failed, then we must unlock
4448 all of the previous locks (X/Open spec). */
4449 if(i != num_locks && num_locks != 0) {
4451 * Ensure we don't do a remove on the lock that just failed,
4452 * as under POSIX rules, if we have a lock already there, we
4453 * will delete it (and we shouldn't) .....
4455 for(i--; i >= 0; i--) {
4456 count = get_lock_count( data, i, large_file_format);
4457 offset = get_lock_offset( data, i, large_file_format, &err);
4460 * There is no error code marked "stupid client bug".... :-).
4463 END_PROFILE(SMBlockingX);
4464 return ERROR(ERRDOS,ERRnoaccess);
4467 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
4469 END_PROFILE(SMBlockingX);
4470 return ERROR(eclass,ecode);
4473 set_message(outbuf,2,0,True);
4475 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4476 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4478 END_PROFILE(SMBlockingX);
4479 return chain_reply(inbuf,outbuf,length,bufsize);
4483 /****************************************************************************
4484 reply to a SMBreadbmpx (read block multiplex) request
4485 ****************************************************************************/
4486 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4497 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4498 START_PROFILE(SMBreadBmpx);
4500 /* this function doesn't seem to work - disable by default */
4501 if (!lp_readbmpx()) {
4502 END_PROFILE(SMBreadBmpx);
4503 return(ERROR(ERRSRV,ERRuseSTD));
4506 outsize = set_message(outbuf,8,0,True);
4508 CHECK_FSP(fsp,conn);
4512 startpos = IVAL(inbuf,smb_vwv1);
4513 maxcount = SVAL(inbuf,smb_vwv3);
4515 data = smb_buf(outbuf);
4516 pad = ((long)data)%4;
4517 if (pad) pad = 4 - pad;
4520 max_per_packet = bufsize-(outsize+pad);
4524 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
4525 END_PROFILE(SMBreadBmpx);
4526 return(ERROR(ERRDOS,ERRlock));
4531 size_t N = MIN(max_per_packet,tcount-total_read);
4533 nread = read_file(fsp,data,startpos,N);
4535 if (nread <= 0) nread = 0;
4537 if (nread < (ssize_t)N)
4538 tcount = total_read + nread;
4540 set_message(outbuf,8,nread,False);
4541 SIVAL(outbuf,smb_vwv0,startpos);
4542 SSVAL(outbuf,smb_vwv2,tcount);
4543 SSVAL(outbuf,smb_vwv6,nread);
4544 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4546 send_smb(smbd_server_fd(),outbuf);
4548 total_read += nread;
4551 while (total_read < (ssize_t)tcount);
4553 END_PROFILE(SMBreadBmpx);
4557 /****************************************************************************
4558 reply to a SMBwritebmpx (write block multiplex primary) request
4559 ****************************************************************************/
4561 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4564 ssize_t nwritten = -1;
4571 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4572 START_PROFILE(SMBwriteBmpx);
4574 CHECK_FSP(fsp,conn);
4578 tcount = SVAL(inbuf,smb_vwv1);
4579 startpos = IVAL(inbuf,smb_vwv3);
4580 write_through = BITSETW(inbuf+smb_vwv7,0);
4581 numtowrite = SVAL(inbuf,smb_vwv10);
4582 smb_doff = SVAL(inbuf,smb_vwv11);
4584 data = smb_base(inbuf) + smb_doff;
4586 /* If this fails we need to send an SMBwriteC response,
4587 not an SMBwritebmpx - set this up now so we don't forget */
4588 CVAL(outbuf,smb_com) = SMBwritec;
4590 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
4591 END_PROFILE(SMBwriteBmpx);
4592 return(ERROR(ERRDOS,ERRlock));
4595 nwritten = write_file(fsp,data,startpos,numtowrite);
4597 if(lp_syncalways(SNUM(conn)) || write_through)
4598 sync_file(conn,fsp);
4600 if(nwritten < (ssize_t)numtowrite) {
4601 END_PROFILE(SMBwriteBmpx);
4602 return(UNIXERROR(ERRHRD,ERRdiskfull));
4605 /* If the maximum to be written to this file
4606 is greater than what we just wrote then set
4607 up a secondary struct to be attached to this
4608 fd, we will use this to cache error messages etc. */
4609 if((ssize_t)tcount > nwritten)
4611 write_bmpx_struct *wbms;
4612 if(fsp->wbmpx_ptr != NULL)
4613 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4615 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4618 DEBUG(0,("Out of memory in reply_readmpx\n"));
4619 END_PROFILE(SMBwriteBmpx);
4620 return(ERROR(ERRSRV,ERRnoresource));
4622 wbms->wr_mode = write_through;
4623 wbms->wr_discard = False; /* No errors yet */
4624 wbms->wr_total_written = nwritten;
4625 wbms->wr_errclass = 0;
4627 fsp->wbmpx_ptr = wbms;
4630 /* We are returning successfully, set the message type back to
4632 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4634 outsize = set_message(outbuf,1,0,True);
4636 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4638 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4639 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4641 if (write_through && tcount==nwritten) {
4642 /* we need to send both a primary and a secondary response */
4643 smb_setlen(outbuf,outsize - 4);
4644 send_smb(smbd_server_fd(),outbuf);
4646 /* now the secondary */
4647 outsize = set_message(outbuf,1,0,True);
4648 CVAL(outbuf,smb_com) = SMBwritec;
4649 SSVAL(outbuf,smb_vwv0,nwritten);
4652 END_PROFILE(SMBwriteBmpx);
4657 /****************************************************************************
4658 reply to a SMBwritebs (write block multiplex secondary) request
4659 ****************************************************************************/
4660 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4663 ssize_t nwritten = -1;
4670 write_bmpx_struct *wbms;
4671 BOOL send_response = False;
4672 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4673 START_PROFILE(SMBwriteBs);
4675 CHECK_FSP(fsp,conn);
4678 tcount = SVAL(inbuf,smb_vwv1);
4679 startpos = IVAL(inbuf,smb_vwv2);
4680 numtowrite = SVAL(inbuf,smb_vwv6);
4681 smb_doff = SVAL(inbuf,smb_vwv7);
4683 data = smb_base(inbuf) + smb_doff;
4685 /* We need to send an SMBwriteC response, not an SMBwritebs */
4686 CVAL(outbuf,smb_com) = SMBwritec;
4688 /* This fd should have an auxiliary struct attached,
4689 check that it does */
4690 wbms = fsp->wbmpx_ptr;
4692 END_PROFILE(SMBwriteBs);
4696 /* If write through is set we can return errors, else we must
4698 write_through = wbms->wr_mode;
4700 /* Check for an earlier error */
4701 if(wbms->wr_discard) {
4702 END_PROFILE(SMBwriteBs);
4703 return -1; /* Just discard the packet */
4706 nwritten = write_file(fsp,data,startpos,numtowrite);
4708 if(lp_syncalways(SNUM(conn)) || write_through)
4709 sync_file(conn,fsp);
4711 if (nwritten < (ssize_t)numtowrite)
4715 /* We are returning an error - we can delete the aux struct */
4716 if (wbms) free((char *)wbms);
4717 fsp->wbmpx_ptr = NULL;
4718 END_PROFILE(SMBwriteBs);
4719 return(ERROR(ERRHRD,ERRdiskfull));
4721 END_PROFILE(SMBwriteBs);
4722 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4725 /* Increment the total written, if this matches tcount
4726 we can discard the auxiliary struct (hurrah !) and return a writeC */
4727 wbms->wr_total_written += nwritten;
4728 if(wbms->wr_total_written >= tcount)
4732 outsize = set_message(outbuf,1,0,True);
4733 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4734 send_response = True;
4738 fsp->wbmpx_ptr = NULL;
4742 END_PROFILE(SMBwriteBs);
4746 END_PROFILE(SMBwriteBs);
4751 /****************************************************************************
4752 reply to a SMBsetattrE
4753 ****************************************************************************/
4755 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4757 struct utimbuf unix_times;
4759 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4760 START_PROFILE(SMBsetattrE);
4762 outsize = set_message(outbuf,0,0,True);
4764 CHECK_FSP(fsp,conn);
4767 /* Convert the DOS times into unix times. Ignore create
4768 time as UNIX can't set this.
4770 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4771 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4774 * Patch from Ray Frush <frush@engr.colostate.edu>
4775 * Sometimes times are sent as zero - ignore them.
4778 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4780 /* Ignore request */
4783 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4784 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4786 END_PROFILE(SMBsetattrE);
4789 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4791 /* set modify time = to access time if modify time was 0 */
4792 unix_times.modtime = unix_times.actime;
4795 /* Set the date on this file */
4796 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4797 END_PROFILE(SMBsetattrE);
4798 return(ERROR(ERRDOS,ERRnoaccess));
4801 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4802 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4804 END_PROFILE(SMBsetattrE);
4809 /****************************************************************************
4810 reply to a SMBgetattrE
4811 ****************************************************************************/
4813 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4815 SMB_STRUCT_STAT sbuf;
4818 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4819 START_PROFILE(SMBgetattrE);
4821 outsize = set_message(outbuf,11,0,True);
4823 CHECK_FSP(fsp,conn);
4826 /* Do an fstat on this file */
4827 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4828 END_PROFILE(SMBgetattrE);
4829 return(UNIXERROR(ERRDOS,ERRnoaccess));
4832 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4834 /* Convert the times into dos times. Set create
4835 date to be last modify date as UNIX doesn't save
4837 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4838 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4839 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4842 SIVAL(outbuf,smb_vwv6,0);
4843 SIVAL(outbuf,smb_vwv8,0);
4847 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4848 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4850 SSVAL(outbuf,smb_vwv10, mode);
4852 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4854 END_PROFILE(SMBgetattrE);