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;
431 if (lp_security() == SEC_USER) {
432 sam_trust_acct = pdb_getsampwnam(user);
434 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
435 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
436 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
439 if (sam_trust_acct == NULL) {
440 /* lkclXXXX: workstation entry doesn't exist */
441 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
442 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
443 return(ERROR(0, NT_STATUS_NO_SUCH_USER));
445 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
446 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
447 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
448 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
451 if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) {
452 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
453 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
454 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
457 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
458 if (acct_ctrl & ACB_DOMTRUST) {
459 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
460 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
461 return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
464 if (acct_ctrl & ACB_SVRTRUST) {
465 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
466 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
467 return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
470 if (acct_ctrl & ACB_WSTRUST) {
471 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
472 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
473 return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
477 /* don't know what to do: indicate logon failure */
478 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
479 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
482 /****************************************************************************
483 Create a UNIX user on demand.
484 ****************************************************************************/
486 int smb_create_user(char *unix_user, char *homedir)
491 pstrcpy(add_script, lp_adduser_script());
492 if (! *add_script) return -1;
493 all_string_sub(add_script, "%u", unix_user, sizeof(pstring));
495 all_string_sub(add_script, "%H", homedir, sizeof(pstring));
496 ret = smbrun(add_script,NULL,False);
497 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
501 /****************************************************************************
502 Delete a UNIX user on demand.
503 ****************************************************************************/
505 static int smb_delete_user(char *unix_user)
510 pstrcpy(del_script, lp_deluser_script());
511 if (! *del_script) return -1;
512 all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
513 ret = smbrun(del_script,NULL,False);
514 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
518 /****************************************************************************
519 Check user is in correct domain if required
520 ****************************************************************************/
522 static BOOL check_domain_match(char *user, char *domain)
525 * If we aren't serving to trusted domains, we must make sure that
526 * the validation request comes from an account in the same domain
527 * as the Samba server
530 if (!lp_allow_trusted_domains() &&
531 !strequal(lp_workgroup(), domain) ) {
532 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
539 /****************************************************************************
540 Check for a valid username and password in security=server mode.
541 ****************************************************************************/
543 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
544 char *smb_apasswd, int smb_apasslen,
545 char *smb_ntpasswd, int smb_ntpasslen)
549 if(lp_security() != SEC_SERVER)
552 if (!check_domain_match(orig_user, domain))
555 ret = server_validate(orig_user, domain,
556 smb_apasswd, smb_apasslen,
557 smb_ntpasswd, smb_ntpasslen);
562 * User validated ok against Domain controller.
563 * If the admin wants us to try and create a UNIX
564 * user on the fly, do so.
565 * Note that we can never delete users when in server
566 * level security as we never know if it was a failure
567 * due to a bad password, or the user really doesn't exist.
569 if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
570 smb_create_user(unix_user, NULL);
573 if(lp_adduser_script() && pwd) {
577 * Also call smb_create_user if the users home directory
578 * doesn't exist. Used with winbindd to allow the script to
579 * create the home directory for a user mapped with winbindd.
582 if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
583 smb_create_user(unix_user, pwd->pw_dir);
590 /****************************************************************************
591 Check for a valid username and password in security=domain mode.
592 ****************************************************************************/
594 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
595 char *smb_apasswd, int smb_apasslen,
596 char *smb_ntpasswd, int smb_ntpasslen)
599 BOOL user_exists = True;
602 if(lp_security() != SEC_DOMAIN)
605 if (!check_domain_match(orig_user, domain))
608 ret = domain_client_validate(orig_user, domain,
609 smb_apasswd, smb_apasslen,
610 smb_ntpasswd, smb_ntpasslen,
615 * User validated ok against Domain controller.
616 * If the admin wants us to try and create a UNIX
617 * user on the fly, do so.
619 if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
620 smb_create_user(unix_user, NULL);
623 if(lp_adduser_script() && pwd) {
627 * Also call smb_create_user if the users home directory
628 * doesn't exist. Used with winbindd to allow the script to
629 * create the home directory for a user mapped with winbindd.
632 if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
633 smb_create_user(unix_user, pwd->pw_dir);
638 * User failed to validate ok against Domain controller.
639 * If the failure was "user doesn't exist" and admin
640 * wants us to try and delete that UNIX user on the fly,
643 if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) {
644 smb_delete_user(unix_user);
651 /****************************************************************************
652 Return a bad password error configured for the correct client type.
653 ****************************************************************************/
655 static int bad_password_error(char *inbuf,char *outbuf)
657 enum remote_arch_types ra_type = get_remote_arch();
659 if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
660 (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
661 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
662 return(ERROR(0,NT_STATUS_LOGON_FAILURE));
665 return(ERROR(ERRSRV,ERRbadpw));
668 /****************************************************************************
669 reply to a session setup command
670 ****************************************************************************/
672 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
678 int smb_apasslen = 0;
680 int smb_ntpasslen = 0;
681 pstring smb_ntpasswd;
682 BOOL valid_nt_password = False;
683 BOOL valid_lm_password = False;
688 fstring native_lanman;
690 static BOOL done_sesssetup = False;
691 BOOL doencrypt = SMBENCRYPT();
692 START_PROFILE(SMBsesssetupX);
697 smb_bufsize = SVAL(inbuf,smb_vwv2);
699 if (Protocol < PROTOCOL_NT1) {
700 smb_apasslen = SVAL(inbuf,smb_vwv7);
701 if (smb_apasslen > MAX_PASS_LEN)
702 overflow_attack(smb_apasslen);
704 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
705 smb_apasswd[smb_apasslen] = 0;
706 srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE|STR_CONVERT);
708 if (!doencrypt && (lp_security() != SEC_SERVER)) {
709 smb_apasslen = strlen(smb_apasswd);
712 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
713 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
714 enum remote_arch_types ra_type = get_remote_arch();
715 char *p = smb_buf(inbuf);
717 if(global_client_caps == 0)
718 global_client_caps = IVAL(inbuf,smb_vwv11);
720 /* client_caps is used as final determination if client is NT or Win95.
721 This is needed to return the correct error codes in some
725 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
726 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
727 set_remote_arch( RA_WIN95);
731 if (passlen1 != 24 && passlen2 != 24)
734 if (passlen1 > MAX_PASS_LEN) {
735 overflow_attack(passlen1);
738 passlen1 = MIN(passlen1, MAX_PASS_LEN);
739 passlen2 = MIN(passlen2, MAX_PASS_LEN);
742 /* both Win95 and WinNT stuff up the password lengths for
743 non-encrypting systems. Uggh.
745 if passlen1==24 its a win95 system, and its setting the
746 password length incorrectly. Luckily it still works with the
747 default code because Win95 will null terminate the password
750 if passlen1>0 and passlen2>0 then maybe its a NT box and its
751 setting passlen2 to some random value which really stuffs
752 things up. we need to fix that one. */
754 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
758 if (lp_restrict_anonymous()) {
759 /* there seems to be no reason behind the differences in MS clients formatting
760 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
761 * in particular seems to have an extra null byte between the username and the
762 * domain, or the password length calculation is wrong, which throws off the
763 * string extraction routines below. This makes the value of domain be the
764 * empty string, which fails the restrict anonymous check further down.
765 * This compensates for that, and allows browsing to work in mixed NT and
766 * win95 environments even when restrict anonymous is true. AAB
768 dump_data(100, p, 0x70);
769 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
770 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
771 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
772 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
773 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
778 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
779 /* Save the lanman2 password and the NT md4 password. */
780 smb_apasslen = passlen1;
781 memcpy(smb_apasswd,p,smb_apasslen);
782 smb_apasswd[smb_apasslen] = 0;
783 smb_ntpasslen = passlen2;
784 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
785 smb_ntpasswd[smb_ntpasslen] = 0;
788 * Ensure the plaintext passwords are in UNIX format.
791 dos_to_unix(smb_apasswd,True);
792 dos_to_unix(smb_ntpasswd,True);
796 /* we use the first password that they gave */
797 smb_apasslen = passlen1;
798 StrnCpy(smb_apasswd,p,smb_apasslen);
800 * Ensure the plaintext password is in UNIX format.
802 dos_to_unix(smb_apasswd,True);
804 /* trim the password */
805 smb_apasslen = strlen(smb_apasswd);
807 /* wfwg sometimes uses a space instead of a null */
808 if (strequal(smb_apasswd," ")) {
814 p += passlen1 + passlen2;
815 p += srvstr_pull(inbuf, user, p, sizeof(user), -1, STR_CONVERT|STR_TERMINATE);
817 * Incoming user and domain are in DOS codepage format. Convert
820 p += srvstr_pull(inbuf, domain, p, sizeof(domain),
821 -1, STR_CONVERT|STR_TERMINATE);
822 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
823 -1, STR_CONVERT|STR_TERMINATE);
824 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
825 -1, STR_CONVERT|STR_TERMINATE);
826 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
827 domain,native_os,native_lanman));
830 DEBUG(3,("sesssetupX:name=[%s]\n",user));
832 /* If name ends in $ then I think it's asking about whether a */
833 /* computer with that name (minus the $) has access. For now */
834 /* say yes to everything ending in $. */
836 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
837 END_PROFILE(SMBsesssetupX);
838 return session_trust_account(conn, inbuf, outbuf, user,
839 smb_apasswd, smb_apasslen,
840 smb_ntpasswd, smb_ntpasslen);
843 if (done_sesssetup && lp_restrict_anonymous()) {
844 /* tests show that even if browsing is done over already validated connections
845 * without a username and password the domain is still provided, which it
846 * wouldn't be if it was a purely anonymous connection. So, in order to
847 * restrict anonymous, we only deny connections that have no session
848 * information. If a domain has been provided, then it's not a purely
849 * anonymous connection. AAB
851 if (!*user && !*smb_apasswd && !*domain) {
852 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
853 END_PROFILE(SMBsesssetupX);
854 return(ERROR(ERRDOS,ERRnoaccess));
858 /* If no username is sent use the guest account */
860 pstrcpy(user,lp_guestaccount(-1));
861 /* If no user and no password then set guest flag. */
862 if( *smb_apasswd == 0)
866 pstrcpy(current_user_info.smb_name,user);
868 reload_services(True);
871 * Save the username before mapping. We will use
872 * the original username sent to us for security=server
873 * and security=domain checking.
876 pstrcpy( orig_user, user);
878 /* if the username exists as a domain/username pair on the unix system then use
880 if (!sys_getpwnam(user)) {
883 slprintf(user2,sizeof(user2),"%s%s%s", dos_to_unix(domain,False),
884 lp_winbind_separator(), user);
886 if (sys_getpwnam(user2)) {
887 DEBUG(3,("Using unix username %s\n", user2));
888 pstrcpy(user, user2);
893 * Pass the user through the NT -> unix user mapping
897 (void)map_username(user);
900 * Do any UNIX username case mangling.
902 smb_getpwnam(user, True);
904 add_session_user(user);
907 * Check if the given username was the guest user with no password.
910 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
914 * Check with orig_user for security=server and
918 if (!guest && !check_server_security(orig_user, domain, user,
919 smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
920 !check_domain_security(orig_user, domain, user, smb_apasswd,
921 smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
922 !check_hosts_equiv(user))
926 * If we get here then the user wasn't guest and the remote
927 * authentication methods failed. Check the authentication
928 * methods on this local server.
930 * If an NT password was supplied try and validate with that
931 * first. This is superior as the passwords are mixed case
932 * 128 length unicode.
937 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
938 DEBUG(2,("NT Password did not match for user '%s'!\n", user));
940 valid_nt_password = True;
944 /* check the LanMan password only if necessary and if allowed
945 by lp_lanman_auth() */
946 if (!valid_nt_password && lp_lanman_auth())
948 DEBUG(2,("Defaulting to Lanman password for %s\n", user));
949 valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen,NULL);
953 /* The true branch will be executed if
954 (1) the NT password failed (or was not tried), and
955 (2) LanMan authentication failed (or was disabled)
957 if (!valid_nt_password && !valid_lm_password)
959 if (lp_security() >= SEC_USER)
961 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
963 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
964 END_PROFILE(SMBsesssetupX);
965 return bad_password_error(inbuf,outbuf);
968 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
970 if (smb_getpwnam(user,True))
972 DEBUG(1,("Rejecting user '%s': bad password\n", user));
973 END_PROFILE(SMBsesssetupX);
974 return bad_password_error(inbuf,outbuf);
979 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
980 * Then always map to guest account - as done below.
984 if (*smb_apasswd || !smb_getpwnam(user,True))
985 pstrcpy(user,lp_guestaccount(-1));
986 DEBUG(3,("Registered username %s for guest access\n",user));
991 if (!smb_getpwnam(user,True)) {
992 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
993 pstrcpy(user,lp_guestaccount(-1));
997 if (!strequal(user,lp_guestaccount(-1)) &&
998 lp_servicenumber(user) < 0)
1000 add_home_service(user,get_user_home_dir(user));
1004 /* it's ok - setup a reply */
1005 if (Protocol < PROTOCOL_NT1) {
1006 set_message(outbuf,3,0,True);
1009 set_message(outbuf,3,0,True);
1010 p = smb_buf(outbuf);
1011 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE|STR_CONVERT);
1012 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE|STR_CONVERT);
1013 p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE|STR_CONVERT);
1014 set_message_end(outbuf,p);
1015 /* perhaps grab OS version here?? */
1018 /* Set the correct uid in the outgoing and incoming packets
1019 We will use this on future requests to determine which
1020 user we should become.
1023 const struct passwd *pw = smb_getpwnam(user,False);
1025 DEBUG(1,("Username %s is invalid on this system\n",user));
1026 END_PROFILE(SMBsesssetupX);
1027 return bad_password_error(inbuf,outbuf);
1034 SSVAL(outbuf,smb_vwv2,1);
1036 /* register the name and uid as being validated, so further connections
1037 to a uid can get through without a password, on the same VC */
1039 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest);
1041 SSVAL(outbuf,smb_uid,sess_vuid);
1042 SSVAL(inbuf,smb_uid,sess_vuid);
1044 if (!done_sesssetup)
1045 max_send = MIN(max_send,smb_bufsize);
1047 DEBUG(6,("Client requested max send size of %d\n", max_send));
1049 done_sesssetup = True;
1051 END_PROFILE(SMBsesssetupX);
1052 return chain_reply(inbuf,outbuf,length,bufsize);
1056 /****************************************************************************
1058 ****************************************************************************/
1059 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1065 BOOL bad_path = False;
1066 SMB_STRUCT_STAT sbuf;
1067 START_PROFILE(SMBchkpth);
1069 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1071 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1073 unix_convert(name,conn,0,&bad_path,&sbuf);
1075 mode = SVAL(inbuf,smb_vwv0);
1077 if (check_name(name,conn)) {
1078 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
1079 ok = S_ISDIR(sbuf.st_mode);
1084 /* We special case this - as when a Windows machine
1085 is parsing a path is steps through the components
1086 one at a time - if a component fails it expects
1087 ERRbadpath, not ERRbadfile.
1091 unix_ERR_class = ERRDOS;
1092 unix_ERR_code = ERRbadpath;
1096 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1097 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1098 (get_remote_arch() == RA_WINNT))
1100 unix_ERR_class = ERRDOS;
1101 unix_ERR_code = ERRbaddirectory;
1105 return(UNIXERROR(ERRDOS,ERRbadpath));
1108 outsize = set_message(outbuf,0,0,True);
1110 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1112 END_PROFILE(SMBchkpth);
1117 /****************************************************************************
1119 ****************************************************************************/
1120 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1124 SMB_STRUCT_STAT sbuf;
1129 BOOL bad_path = False;
1131 START_PROFILE(SMBgetatr);
1133 p = smb_buf(inbuf) + 1;
1134 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1136 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1138 /* if((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && dfs_redirect(fname,conn)) return(dfs_path_error(inbuf,outbuf));
1140 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1141 under WfWg - weird! */
1144 mode = aHIDDEN | aDIR;
1145 if (!CAN_WRITE(conn)) mode |= aRONLY;
1152 unix_convert(fname,conn,0,&bad_path,&sbuf);
1153 if (check_name(fname,conn))
1155 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1157 mode = dos_mode(conn,fname,&sbuf);
1158 size = sbuf.st_size;
1159 mtime = sbuf.st_mtime;
1165 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1171 if((errno == ENOENT) && bad_path)
1173 unix_ERR_class = ERRDOS;
1174 unix_ERR_code = ERRbadpath;
1177 END_PROFILE(SMBgetatr);
1178 return(UNIXERROR(ERRDOS,ERRbadfile));
1181 outsize = set_message(outbuf,10,0,True);
1183 SSVAL(outbuf,smb_vwv0,mode);
1184 if(lp_dos_filetime_resolution(SNUM(conn)) )
1185 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1187 put_dos_date3(outbuf,smb_vwv1,mtime);
1188 SIVAL(outbuf,smb_vwv3,(uint32)size);
1190 if (Protocol >= PROTOCOL_NT1) {
1191 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1194 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1196 END_PROFILE(SMBgetatr);
1201 /****************************************************************************
1203 ****************************************************************************/
1204 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1211 SMB_STRUCT_STAT sbuf;
1212 BOOL bad_path = False;
1215 START_PROFILE(SMBsetatr);
1217 p = smb_buf(inbuf) + 1;
1218 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1219 unix_convert(fname,conn,0,&bad_path,&sbuf);
1221 mode = SVAL(inbuf,smb_vwv0);
1222 mtime = make_unix_date3(inbuf+smb_vwv1);
1224 if (VALID_STAT_OF_DIR(sbuf))
1226 if (check_name(fname,conn))
1227 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1229 ok = set_filetime(conn,fname,mtime);
1233 if((errno == ENOENT) && bad_path)
1235 unix_ERR_class = ERRDOS;
1236 unix_ERR_code = ERRbadpath;
1239 END_PROFILE(SMBsetatr);
1240 return(UNIXERROR(ERRDOS,ERRnoaccess));
1243 outsize = set_message(outbuf,0,0,True);
1245 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1247 END_PROFILE(SMBsetatr);
1252 /****************************************************************************
1254 ****************************************************************************/
1255 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1258 SMB_BIG_UINT dfree,dsize,bsize;
1259 START_PROFILE(SMBdskattr);
1261 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1263 outsize = set_message(outbuf,5,0,True);
1265 SSVAL(outbuf,smb_vwv0,dsize);
1266 SSVAL(outbuf,smb_vwv1,bsize/512);
1267 SSVAL(outbuf,smb_vwv2,512);
1268 SSVAL(outbuf,smb_vwv3,dfree);
1270 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1272 END_PROFILE(SMBdskattr);
1277 /****************************************************************************
1279 Can be called from SMBsearch, SMBffirst or SMBfunique.
1280 ****************************************************************************/
1281 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1292 BOOL finished = False;
1301 BOOL check_descend = False;
1302 BOOL expect_close = False;
1303 BOOL can_open = True;
1304 BOOL bad_path = False;
1305 START_PROFILE(SMBsearch);
1307 *mask = *directory = *fname = 0;
1309 /* If we were called as SMBffirst then we must expect close. */
1310 if(CVAL(inbuf,smb_com) == SMBffirst)
1311 expect_close = True;
1313 outsize = set_message(outbuf,1,3,True);
1314 maxentries = SVAL(inbuf,smb_vwv0);
1315 dirtype = SVAL(inbuf,smb_vwv1);
1316 p = smb_buf(inbuf) + 1;
1317 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1319 status_len = SVAL(p, 0);
1322 /* dirtype &= ~aDIR; */
1324 if (status_len == 0)
1326 SMB_STRUCT_STAT sbuf;
1329 pstrcpy(directory,path);
1331 unix_convert(directory,conn,0,&bad_path,&sbuf);
1334 if (!check_name(directory,conn))
1337 p = strrchr(dir2,'/');
1349 p = strrchr(directory,'/');
1355 if (strlen(directory) == 0)
1356 pstrcpy(directory,"./");
1357 memset((char *)status,'\0',21);
1358 CVAL(status,0) = dirtype;
1362 memcpy(status,p,21);
1363 dirtype = CVAL(status,0) & 0x1F;
1364 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1367 string_set(&conn->dirpath,dptr_path(dptr_num));
1368 fstrcpy(mask, dptr_wcard(dptr_num));
1373 p = smb_buf(outbuf) + 3;
1377 if (status_len == 0)
1379 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1384 if((errno == ENOENT) && bad_path)
1386 unix_ERR_class = ERRDOS;
1387 unix_ERR_code = ERRbadpath;
1389 END_PROFILE(SMBsearch);
1390 return (UNIXERROR(ERRDOS,ERRnofids));
1392 END_PROFILE(SMBsearch);
1393 return(ERROR(ERRDOS,ERRnofids));
1395 dptr_set_wcard(dptr_num, strdup(mask));
1398 DEBUG(4,("dptr_num is %d\n",dptr_num));
1402 if ((dirtype&0x1F) == aVOLID)
1404 memcpy(p,status,21);
1405 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1406 dptr_fill(p+12,dptr_num);
1407 if (dptr_zero(p+12) && (status_len==0))
1411 p += DIR_STRUCT_SIZE;
1415 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1416 conn->dirpath,lp_dontdescend(SNUM(conn))));
1417 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1418 check_descend = True;
1420 for (i=numentries;(i<maxentries) && !finished;i++)
1423 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1426 memcpy(p,status,21);
1427 make_dir_struct(p,mask,fname,size,mode,date);
1428 dptr_fill(p+12,dptr_num);
1431 p += DIR_STRUCT_SIZE;
1440 if (numentries == 0 || !ok)
1442 CVAL(outbuf,smb_rcls) = ERRDOS;
1443 SSVAL(outbuf,smb_err,ERRnofiles);
1444 dptr_close(&dptr_num);
1447 /* If we were called as SMBffirst with smb_search_id == NULL
1448 and no entries were found then return error and close dirptr
1451 if(ok && expect_close && numentries == 0 && status_len == 0)
1453 CVAL(outbuf,smb_rcls) = ERRDOS;
1454 SSVAL(outbuf,smb_err,ERRnofiles);
1455 /* Also close the dptr - we know it's gone */
1456 dptr_close(&dptr_num);
1459 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1460 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1461 dptr_close(&dptr_num);
1463 SSVAL(outbuf,smb_vwv0,numentries);
1464 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1465 CVAL(smb_buf(outbuf),0) = 5;
1466 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1468 if (Protocol >= PROTOCOL_NT1) {
1469 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1472 outsize += DIR_STRUCT_SIZE*numentries;
1473 smb_setlen(outbuf,outsize - 4);
1475 if ((! *directory) && dptr_path(dptr_num))
1476 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1478 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1479 smb_fn_name(CVAL(inbuf,smb_com)),
1480 mask, directory, dirtype, numentries, maxentries ) );
1482 END_PROFILE(SMBsearch);
1487 /****************************************************************************
1488 reply to a fclose (stop directory search)
1489 ****************************************************************************/
1490 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1499 START_PROFILE(SMBfclose);
1501 outsize = set_message(outbuf,1,0,True);
1502 p = smb_buf(inbuf) + 1;
1503 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE|STR_CONVERT);
1505 status_len = SVAL(p,0);
1508 if (status_len == 0) {
1509 END_PROFILE(SMBfclose);
1510 return(ERROR(ERRSRV,ERRsrverror));
1513 memcpy(status,p,21);
1515 if(dptr_fetch(status+12,&dptr_num)) {
1516 /* Close the dptr - we know it's gone */
1517 dptr_close(&dptr_num);
1520 SSVAL(outbuf,smb_vwv0,0);
1522 DEBUG(3,("search close\n"));
1524 END_PROFILE(SMBfclose);
1529 /****************************************************************************
1531 ****************************************************************************/
1533 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1543 SMB_STRUCT_STAT sbuf;
1544 BOOL bad_path = False;
1546 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1547 START_PROFILE(SMBopen);
1549 share_mode = SVAL(inbuf,smb_vwv0);
1551 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1553 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1555 unix_convert(fname,conn,0,&bad_path,&sbuf);
1557 unixmode = unix_mode(conn,aARCH,fname);
1559 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1560 unixmode, oplock_request,&rmode,NULL);
1564 if((errno == ENOENT) && bad_path)
1566 unix_ERR_class = ERRDOS;
1567 unix_ERR_code = ERRbadpath;
1569 END_PROFILE(SMBopen);
1570 return(UNIXERROR(ERRDOS,ERRnoaccess));
1573 size = sbuf.st_size;
1574 fmode = dos_mode(conn,fname,&sbuf);
1575 mtime = sbuf.st_mtime;
1578 DEBUG(3,("attempt to open a directory %s\n",fname));
1579 close_file(fsp,False);
1580 END_PROFILE(SMBopen);
1581 return(ERROR(ERRDOS,ERRnoaccess));
1584 outsize = set_message(outbuf,7,0,True);
1585 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1586 SSVAL(outbuf,smb_vwv1,fmode);
1587 if(lp_dos_filetime_resolution(SNUM(conn)) )
1588 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1590 put_dos_date3(outbuf,smb_vwv2,mtime);
1591 SIVAL(outbuf,smb_vwv4,(uint32)size);
1592 SSVAL(outbuf,smb_vwv6,rmode);
1594 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1595 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1598 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1599 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1600 END_PROFILE(SMBopen);
1605 /****************************************************************************
1606 reply to an open and X
1607 ****************************************************************************/
1608 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1611 int smb_mode = SVAL(inbuf,smb_vwv3);
1612 int smb_attr = SVAL(inbuf,smb_vwv5);
1613 /* Breakout the oplock request bits so we can set the
1614 reply bits separately. */
1615 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1616 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1617 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1619 int open_flags = SVAL(inbuf,smb_vwv2);
1620 int smb_sattr = SVAL(inbuf,smb_vwv4);
1621 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1623 int smb_ofun = SVAL(inbuf,smb_vwv8);
1626 int fmode=0,mtime=0,rmode=0;
1627 SMB_STRUCT_STAT sbuf;
1629 BOOL bad_path = False;
1631 START_PROFILE(SMBopenX);
1633 /* If it's an IPC, pass off the pipe handler. */
1635 if (lp_nt_pipe_support()) {
1636 END_PROFILE(SMBopenX);
1637 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1639 END_PROFILE(SMBopenX);
1640 return (ERROR(ERRSRV,ERRaccess));
1644 /* XXXX we need to handle passed times, sattr and flags */
1645 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1647 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1649 unix_convert(fname,conn,0,&bad_path,&sbuf);
1651 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1653 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1654 oplock_request, &rmode,&smb_action);
1658 if((errno == ENOENT) && bad_path)
1660 unix_ERR_class = ERRDOS;
1661 unix_ERR_code = ERRbadpath;
1663 END_PROFILE(SMBopenX);
1664 return(UNIXERROR(ERRDOS,ERRnoaccess));
1667 size = sbuf.st_size;
1668 fmode = dos_mode(conn,fname,&sbuf);
1669 mtime = sbuf.st_mtime;
1671 close_file(fsp,False);
1672 END_PROFILE(SMBopenX);
1673 return(ERROR(ERRDOS,ERRnoaccess));
1676 /* If the caller set the extended oplock request bit
1677 and we granted one (by whatever means) - set the
1678 correct bit for extended oplock reply.
1681 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1682 smb_action |= EXTENDED_OPLOCK_GRANTED;
1685 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1686 smb_action |= EXTENDED_OPLOCK_GRANTED;
1689 /* If the caller set the core oplock request bit
1690 and we granted one (by whatever means) - set the
1691 correct bit for core oplock reply.
1694 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1695 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1698 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1699 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1702 set_message(outbuf,15,0,True);
1703 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1704 SSVAL(outbuf,smb_vwv3,fmode);
1705 if(lp_dos_filetime_resolution(SNUM(conn)) )
1706 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1708 put_dos_date3(outbuf,smb_vwv4,mtime);
1709 SIVAL(outbuf,smb_vwv6,(uint32)size);
1710 SSVAL(outbuf,smb_vwv8,rmode);
1711 SSVAL(outbuf,smb_vwv11,smb_action);
1713 END_PROFILE(SMBopenX);
1714 return chain_reply(inbuf,outbuf,length,bufsize);
1718 /****************************************************************************
1719 reply to a SMBulogoffX
1720 ****************************************************************************/
1721 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1723 uint16 vuid = SVAL(inbuf,smb_uid);
1724 user_struct *vuser = get_valid_user_struct(vuid);
1725 START_PROFILE(SMBulogoffX);
1728 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1731 /* in user level security we are supposed to close any files
1732 open by this user */
1733 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1734 file_close_user(vuid);
1737 invalidate_vuid(vuid);
1739 set_message(outbuf,2,0,True);
1741 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1743 END_PROFILE(SMBulogoffX);
1744 return chain_reply(inbuf,outbuf,length,bufsize);
1748 /****************************************************************************
1749 reply to a mknew or a create
1750 ****************************************************************************/
1751 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1759 BOOL bad_path = False;
1761 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1762 SMB_STRUCT_STAT sbuf;
1763 START_PROFILE(SMBcreate);
1765 com = SVAL(inbuf,smb_com);
1767 createmode = SVAL(inbuf,smb_vwv0);
1768 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1770 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1772 unix_convert(fname,conn,0,&bad_path,&sbuf);
1774 if (createmode & aVOLID) {
1775 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1778 unixmode = unix_mode(conn,createmode,fname);
1782 /* We should fail if file exists. */
1783 ofun = FILE_CREATE_IF_NOT_EXIST;
1787 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1788 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1791 /* Open file in dos compatibility share mode. */
1792 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1793 ofun, unixmode, oplock_request, NULL, NULL);
1797 if((errno == ENOENT) && bad_path)
1799 unix_ERR_class = ERRDOS;
1800 unix_ERR_code = ERRbadpath;
1802 END_PROFILE(SMBcreate);
1803 return(UNIXERROR(ERRDOS,ERRnoaccess));
1806 outsize = set_message(outbuf,1,0,True);
1807 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1809 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1810 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1813 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1814 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1816 DEBUG( 2, ( "new file %s\n", fname ) );
1817 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1818 fname, fsp->fd, createmode, (int)unixmode ) );
1820 END_PROFILE(SMBcreate);
1825 /****************************************************************************
1826 reply to a create temporary file
1827 ****************************************************************************/
1828 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1835 BOOL bad_path = False;
1837 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1838 SMB_STRUCT_STAT sbuf;
1841 START_PROFILE(SMBctemp);
1843 createmode = SVAL(inbuf,smb_vwv0);
1844 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE|STR_CONVERT);
1845 pstrcat(fname,"/TMXXXXXX");
1847 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1849 unix_convert(fname,conn,0,&bad_path,&sbuf);
1851 unixmode = unix_mode(conn,createmode,fname);
1853 pstrcpy(fname2,(char *)smbd_mktemp(fname));
1854 /* This file should not exist. */
1856 vfs_stat(conn,fname2,&sbuf);
1858 /* Open file in dos compatibility share mode. */
1859 /* We should fail if file exists. */
1860 fsp = open_file_shared(conn,fname2,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1861 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1865 if((errno == ENOENT) && bad_path)
1867 unix_ERR_class = ERRDOS;
1868 unix_ERR_code = ERRbadpath;
1870 END_PROFILE(SMBctemp);
1871 return(UNIXERROR(ERRDOS,ERRnoaccess));
1874 outsize = set_message(outbuf,1,0,True);
1875 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1876 CVAL(smb_buf(outbuf),0) = 4;
1877 p = smb_buf(outbuf) + 1;
1878 p += srvstr_push(outbuf, p, fname2, -1, STR_TERMINATE|STR_CONVERT);
1879 set_message_end(outbuf, p);
1881 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1882 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1885 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1886 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1888 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1889 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1890 fname2, fsp->fd, createmode, (int)unixmode ) );
1892 END_PROFILE(SMBctemp);
1897 /*******************************************************************
1898 check if a user is allowed to delete a file
1899 ********************************************************************/
1900 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1902 SMB_STRUCT_STAT sbuf;
1905 if (!CAN_WRITE(conn)) return(False);
1907 if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False);
1908 fmode = dos_mode(conn,fname,&sbuf);
1909 if (fmode & aDIR) return(False);
1910 if (!lp_delete_readonly(SNUM(conn))) {
1911 if (fmode & aRONLY) return(False);
1913 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1915 if (!check_file_sharing(conn,fname,False)) return(False);
1919 /****************************************************************************
1920 The guts of the unlink command, split out so it may be called by the NT SMB
1922 ****************************************************************************/
1924 int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
1925 int dirtype, char *name)
1931 int error = ERRnoaccess;
1934 BOOL bad_path = False;
1936 SMB_STRUCT_STAT sbuf;
1938 *directory = *mask = 0;
1940 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1942 p = strrchr(name,'/');
1944 pstrcpy(directory,"./");
1948 pstrcpy(directory,name);
1953 * We should only check the mangled cache
1954 * here if unix_convert failed. This means
1955 * that the path in 'mask' doesn't exist
1956 * on the file system and so we need to look
1957 * for a possible mangle. This patch from
1958 * Tine Smukavec <valentin.smukavec@hermes.si>.
1961 if (!rc && is_mangled(mask))
1962 check_mangled_cache( mask );
1964 has_wild = ms_has_wild(mask);
1967 pstrcat(directory,"/");
1968 pstrcat(directory,mask);
1969 if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory))
1972 exists = vfs_file_exist(conn,directory,&sbuf);
1974 void *dirptr = NULL;
1977 if (check_name(directory,conn))
1978 dirptr = OpenDir(conn, directory, True);
1980 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1981 the pattern matches against the long name, otherwise the short name
1982 We don't implement this yet XXXX
1989 if (strequal(mask,"????????.???"))
1992 while ((dname = ReadDirName(dirptr)))
1995 pstrcpy(fname,dname);
1997 if(!mask_match(fname, mask, case_sensitive)) continue;
1999 error = ERRnoaccess;
2000 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2001 if (!can_delete(fname,conn,dirtype)) continue;
2002 if (!vfs_unlink(conn,fname)) count++;
2003 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2011 return(ERROR(ERRDOS,error));
2013 if((errno == ENOENT) && bad_path) {
2014 unix_ERR_class = ERRDOS;
2015 unix_ERR_code = ERRbadpath;
2017 return(UNIXERROR(ERRDOS,error));
2024 /****************************************************************************
2026 ****************************************************************************/
2028 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2033 START_PROFILE(SMBunlink);
2035 dirtype = SVAL(inbuf,smb_vwv0);
2037 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
2039 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
2041 DEBUG(3,("reply_unlink : %s\n",name));
2043 outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
2047 * Win2k needs a changenotify request response before it will
2048 * update after a rename..
2051 process_pending_change_notify_queue((time_t)0);
2053 outsize = set_message(outbuf,0,0,True);
2056 END_PROFILE(SMBunlink);
2061 /****************************************************************************
2062 reply to a readbraw (core+ protocol)
2063 ****************************************************************************/
2065 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2067 size_t maxcount,mincount;
2070 char *header = outbuf;
2073 START_PROFILE(SMBreadbraw);
2076 * Special check if an oplock break has been issued
2077 * and the readraw request croses on the wire, we must
2078 * return a zero length response here.
2081 if(global_oplock_break)
2083 _smb_setlen(header,0);
2084 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2085 DEBUG(5,("readbraw - oplock break finished\n"));
2086 END_PROFILE(SMBreadbraw);
2090 fsp = file_fsp(inbuf,smb_vwv0);
2092 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2094 * fsp could be NULL here so use the value from the packet. JRA.
2096 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2097 _smb_setlen(header,0);
2098 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2099 END_PROFILE(SMBreadbraw);
2103 CHECK_FSP(fsp,conn);
2105 flush_write_cache(fsp, READRAW_FLUSH);
2107 startpos = IVAL(inbuf,smb_vwv1);
2108 if(CVAL(inbuf,smb_wct) == 10) {
2110 * This is a large offset (64 bit) read.
2112 #ifdef LARGE_SMB_OFF_T
2114 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2116 #else /* !LARGE_SMB_OFF_T */
2119 * Ensure we haven't been sent a >32 bit offset.
2122 if(IVAL(inbuf,smb_vwv8) != 0) {
2123 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2124 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2125 _smb_setlen(header,0);
2126 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2127 END_PROFILE(SMBreadbraw);
2131 #endif /* LARGE_SMB_OFF_T */
2134 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2135 (double)startpos ));
2136 _smb_setlen(header,0);
2137 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2138 END_PROFILE(SMBreadbraw);
2142 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2143 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2145 /* ensure we don't overrun the packet size */
2146 maxcount = MIN(65535,maxcount);
2147 maxcount = MAX(mincount,maxcount);
2149 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK))
2151 SMB_OFF_T size = fsp->size;
2152 SMB_OFF_T sizeneeded = startpos + maxcount;
2154 if (size < sizeneeded)
2157 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2159 if (!fsp->can_write)
2163 nread = MIN(maxcount,(size - startpos));
2166 if (nread < mincount)
2169 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2170 fsp->fnum, (double)startpos,
2171 (int)maxcount, (int)mincount, (int)nread ) );
2175 BOOL seek_fail = False;
2177 _smb_setlen(header,nread);
2179 if ((nread-predict) > 0) {
2180 if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
2181 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2188 ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
2189 (SMB_OFF_T)(nread-predict),header,4+predict,
2194 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2195 fsp->fsp_name,startpos,nread,ret));
2197 #else /* UNSAFE_READRAW */
2198 ret = read_file(fsp,header+4,startpos,nread);
2199 if (ret < mincount) ret = 0;
2201 _smb_setlen(header,ret);
2202 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2203 #endif /* UNSAFE_READRAW */
2205 DEBUG(5,("readbraw finished\n"));
2206 END_PROFILE(SMBreadbraw);
2211 /****************************************************************************
2212 reply to a lockread (core+ protocol)
2213 ****************************************************************************/
2214 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2223 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2224 START_PROFILE(SMBlockread);
2226 CHECK_FSP(fsp,conn);
2230 release_level_2_oplocks_on_change(fsp);
2232 numtoread = SVAL(inbuf,smb_vwv1);
2233 startpos = IVAL(inbuf,smb_vwv2);
2235 outsize = set_message(outbuf,5,3,True);
2236 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2237 data = smb_buf(outbuf) + 3;
2240 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2241 * protocol request that predates the read/write lock concept.
2242 * Thus instead of asking for a read lock here we need to ask
2243 * for a write lock. JRA.
2246 if(!do_lock( fsp, conn, (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2247 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2249 * A blocking lock was requested. Package up
2250 * this smb into a queued request and push it
2251 * onto the blocking lock queue.
2253 if(push_blocking_lock_request(inbuf, length, -1, 0))
2254 END_PROFILE(SMBlockread);
2257 END_PROFILE(SMBlockread);
2258 return (ERROR(eclass,ecode));
2261 nread = read_file(fsp,data,startpos,numtoread);
2264 END_PROFILE(SMBlockread);
2265 return(UNIXERROR(ERRDOS,ERRnoaccess));
2269 SSVAL(outbuf,smb_vwv0,nread);
2270 SSVAL(outbuf,smb_vwv5,nread+3);
2271 SSVAL(smb_buf(outbuf),1,nread);
2273 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2274 fsp->fnum, (int)numtoread, (int)nread ) );
2276 END_PROFILE(SMBlockread);
2281 /****************************************************************************
2283 ****************************************************************************/
2285 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2292 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2293 START_PROFILE(SMBread);
2295 CHECK_FSP(fsp,conn);
2299 numtoread = SVAL(inbuf,smb_vwv1);
2300 startpos = IVAL(inbuf,smb_vwv2);
2302 outsize = set_message(outbuf,5,3,True);
2303 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2304 data = smb_buf(outbuf) + 3;
2306 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2307 END_PROFILE(SMBread);
2308 return(ERROR(ERRDOS,ERRlock));
2312 nread = read_file(fsp,data,startpos,numtoread);
2315 END_PROFILE(SMBread);
2316 return(UNIXERROR(ERRDOS,ERRnoaccess));
2320 SSVAL(outbuf,smb_vwv0,nread);
2321 SSVAL(outbuf,smb_vwv5,nread+3);
2322 CVAL(smb_buf(outbuf),0) = 1;
2323 SSVAL(smb_buf(outbuf),1,nread);
2325 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2326 fsp->fnum, (int)numtoread, (int)nread ) );
2328 END_PROFILE(SMBread);
2333 /****************************************************************************
2334 reply to a read and X
2335 ****************************************************************************/
2336 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2338 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2339 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2340 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2341 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2344 START_PROFILE(SMBreadX);
2346 /* If it's an IPC, pass off the pipe handler. */
2348 END_PROFILE(SMBreadX);
2349 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2352 CHECK_FSP(fsp,conn);
2356 set_message(outbuf,12,0,True);
2357 data = smb_buf(outbuf);
2359 if(CVAL(inbuf,smb_wct) == 12) {
2360 #ifdef LARGE_SMB_OFF_T
2362 * This is a large offset (64 bit) read.
2364 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2366 #else /* !LARGE_SMB_OFF_T */
2369 * Ensure we haven't been sent a >32 bit offset.
2372 if(IVAL(inbuf,smb_vwv10) != 0) {
2373 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2374 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2375 END_PROFILE(SMBreadX);
2376 return(ERROR(ERRDOS,ERRbadaccess));
2379 #endif /* LARGE_SMB_OFF_T */
2383 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2384 END_PROFILE(SMBreadX);
2385 return(ERROR(ERRDOS,ERRlock));
2387 nread = read_file(fsp,data,startpos,smb_maxcnt);
2390 END_PROFILE(SMBreadX);
2391 return(UNIXERROR(ERRDOS,ERRnoaccess));
2394 SSVAL(outbuf,smb_vwv5,nread);
2395 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2396 SSVAL(smb_buf(outbuf),-2,nread);
2398 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2399 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2401 END_PROFILE(SMBreadX);
2402 return chain_reply(inbuf,outbuf,length,bufsize);
2405 /****************************************************************************
2406 reply to a writebraw (core+ or LANMAN1.0 protocol)
2407 ****************************************************************************/
2409 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2412 ssize_t total_written=0;
2413 size_t numtowrite=0;
2418 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2420 START_PROFILE(SMBwritebraw);
2422 CHECK_FSP(fsp,conn);
2426 tcount = IVAL(inbuf,smb_vwv1);
2427 startpos = IVAL(inbuf,smb_vwv3);
2428 write_through = BITSETW(inbuf+smb_vwv7,0);
2430 /* We have to deal with slightly different formats depending
2431 on whether we are using the core+ or lanman1.0 protocol */
2432 if(Protocol <= PROTOCOL_COREPLUS) {
2433 numtowrite = SVAL(smb_buf(inbuf),-2);
2434 data = smb_buf(inbuf);
2436 numtowrite = SVAL(inbuf,smb_vwv10);
2437 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2440 /* force the error type */
2441 CVAL(inbuf,smb_com) = SMBwritec;
2442 CVAL(outbuf,smb_com) = SMBwritec;
2444 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2445 END_PROFILE(SMBwritebraw);
2446 return(ERROR(ERRDOS,ERRlock));
2450 nwritten = write_file(fsp,data,startpos,numtowrite);
2452 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2453 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2455 if (nwritten < numtowrite) {
2456 END_PROFILE(SMBwritebraw);
2457 return(UNIXERROR(ERRHRD,ERRdiskfull));
2460 total_written = nwritten;
2462 /* Return a message to the redirector to tell it
2463 to send more bytes */
2464 CVAL(outbuf,smb_com) = SMBwritebraw;
2465 SSVALS(outbuf,smb_vwv0,-1);
2466 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2467 send_smb(smbd_server_fd(),outbuf);
2469 /* Now read the raw data into the buffer and write it */
2470 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2471 exit_server("secondary writebraw failed");
2474 /* Even though this is not an smb message, smb_len
2475 returns the generic length of an smb message */
2476 numtowrite = smb_len(inbuf);
2478 if (tcount > nwritten+numtowrite) {
2479 DEBUG(3,("Client overestimated the write %d %d %d\n",
2480 (int)tcount,(int)nwritten,(int)numtowrite));
2483 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2484 (SMB_OFF_T)numtowrite,NULL,0,
2486 total_written += nwritten;
2488 /* Set up outbuf to return the correct return */
2489 outsize = set_message(outbuf,1,0,True);
2490 CVAL(outbuf,smb_com) = SMBwritec;
2491 SSVAL(outbuf,smb_vwv0,total_written);
2493 if (nwritten < (ssize_t)numtowrite) {
2494 CVAL(outbuf,smb_rcls) = ERRHRD;
2495 SSVAL(outbuf,smb_err,ERRdiskfull);
2498 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2499 lp_strict_sync(SNUM(conn)))
2500 sync_file(conn,fsp);
2502 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2503 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2505 /* we won't return a status if write through is not selected - this
2506 follows what WfWg does */
2507 END_PROFILE(SMBwritebraw);
2508 if (!write_through && total_written==tcount) {
2515 /****************************************************************************
2516 reply to a writeunlock (core+)
2517 ****************************************************************************/
2519 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2521 ssize_t nwritten = -1;
2527 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2529 START_PROFILE(SMBwriteunlock);
2531 CHECK_FSP(fsp,conn);
2535 numtowrite = SVAL(inbuf,smb_vwv1);
2536 startpos = IVAL(inbuf,smb_vwv2);
2537 data = smb_buf(inbuf) + 3;
2539 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2540 END_PROFILE(SMBwriteunlock);
2541 return(ERROR(ERRDOS,ERRlock));
2544 /* The special X/Open SMB protocol handling of
2545 zero length writes is *NOT* done for
2550 nwritten = write_file(fsp,data,startpos,numtowrite);
2552 if (lp_syncalways(SNUM(conn)))
2553 sync_file(conn,fsp);
2555 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2556 END_PROFILE(SMBwriteunlock);
2557 return(UNIXERROR(ERRDOS,ERRnoaccess));
2560 if(!do_unlock(fsp, conn, (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) {
2561 END_PROFILE(SMBwriteunlock);
2562 return(ERROR(eclass,ecode));
2565 outsize = set_message(outbuf,1,0,True);
2567 SSVAL(outbuf,smb_vwv0,nwritten);
2569 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2570 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2572 END_PROFILE(SMBwriteunlock);
2576 /****************************************************************************
2578 ****************************************************************************/
2579 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2582 ssize_t nwritten = -1;
2585 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2587 START_PROFILE(SMBwrite);
2589 /* If it's an IPC, pass off the pipe handler. */
2591 END_PROFILE(SMBwrite);
2592 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2595 CHECK_FSP(fsp,conn);
2599 numtowrite = SVAL(inbuf,smb_vwv1);
2600 startpos = IVAL(inbuf,smb_vwv2);
2601 data = smb_buf(inbuf) + 3;
2603 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2604 END_PROFILE(SMBwrite);
2605 return(ERROR(ERRDOS,ERRlock));
2608 /* X/Open SMB protocol says that if smb_vwv1 is
2609 zero then the file size should be extended or
2610 truncated to the size given in smb_vwv[2-3] */
2611 if(numtowrite == 0) {
2612 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2614 nwritten = write_file(fsp,data,startpos,numtowrite);
2616 if (lp_syncalways(SNUM(conn)))
2617 sync_file(conn,fsp);
2619 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2620 END_PROFILE(SMBwrite);
2621 return(UNIXERROR(ERRDOS,ERRnoaccess));
2624 outsize = set_message(outbuf,1,0,True);
2626 SSVAL(outbuf,smb_vwv0,nwritten);
2628 if (nwritten < (ssize_t)numtowrite) {
2629 CVAL(outbuf,smb_rcls) = ERRHRD;
2630 SSVAL(outbuf,smb_err,ERRdiskfull);
2633 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2634 fsp->fnum, (int)numtowrite, (int)nwritten));
2636 END_PROFILE(SMBwrite);
2641 /****************************************************************************
2642 reply to a write and X
2643 ****************************************************************************/
2644 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2646 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2647 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2648 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2649 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2650 ssize_t nwritten = -1;
2651 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2653 START_PROFILE(SMBwriteX);
2655 /* If it's an IPC, pass off the pipe handler. */
2657 END_PROFILE(SMBwriteX);
2658 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2661 CHECK_FSP(fsp,conn);
2665 if(smb_doff > smb_len(inbuf)) {
2666 END_PROFILE(SMBwriteX);
2667 return(ERROR(ERRDOS,ERRbadmem));
2670 data = smb_base(inbuf) + smb_doff;
2672 if(CVAL(inbuf,smb_wct) == 14) {
2673 #ifdef LARGE_SMB_OFF_T
2675 * This is a large offset (64 bit) write.
2677 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2679 #else /* !LARGE_SMB_OFF_T */
2682 * Ensure we haven't been sent a >32 bit offset.
2685 if(IVAL(inbuf,smb_vwv12) != 0) {
2686 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2687 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2688 END_PROFILE(SMBwriteX);
2689 return(ERROR(ERRDOS,ERRbadaccess));
2692 #endif /* LARGE_SMB_OFF_T */
2695 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2696 END_PROFILE(SMBwriteX);
2697 return(ERROR(ERRDOS,ERRlock));
2700 /* X/Open SMB protocol says that, unlike SMBwrite
2701 if the length is zero then NO truncation is
2702 done, just a write of zero. To truncate a file,
2707 nwritten = write_file(fsp,data,startpos,numtowrite);
2709 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2710 END_PROFILE(SMBwriteX);
2711 return(UNIXERROR(ERRDOS,ERRnoaccess));
2714 set_message(outbuf,6,0,True);
2716 SSVAL(outbuf,smb_vwv2,nwritten);
2718 if (nwritten < (ssize_t)numtowrite) {
2719 CVAL(outbuf,smb_rcls) = ERRHRD;
2720 SSVAL(outbuf,smb_err,ERRdiskfull);
2723 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2724 fsp->fnum, (int)numtowrite, (int)nwritten));
2726 if (lp_syncalways(SNUM(conn)) || write_through)
2727 sync_file(conn,fsp);
2729 END_PROFILE(SMBwriteX);
2730 return chain_reply(inbuf,outbuf,length,bufsize);
2734 /****************************************************************************
2736 ****************************************************************************/
2738 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2744 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2745 START_PROFILE(SMBlseek);
2747 CHECK_FSP(fsp,conn);
2750 flush_write_cache(fsp, SEEK_FLUSH);
2752 mode = SVAL(inbuf,smb_vwv1) & 3;
2753 startpos = IVALS(inbuf,smb_vwv2);
2756 case 0: umode = SEEK_SET; break;
2757 case 1: umode = SEEK_CUR; break;
2758 case 2: umode = SEEK_END; break;
2760 umode = SEEK_SET; break;
2763 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2765 * Check for the special case where a seek before the start
2766 * of the file sets the offset to zero. Added in the CIFS spec,
2770 if(errno == EINVAL) {
2771 SMB_OFF_T current_pos = startpos;
2773 if(umode == SEEK_CUR) {
2775 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2776 END_PROFILE(SMBlseek);
2777 return(UNIXERROR(ERRDOS,ERRnoaccess));
2780 current_pos += startpos;
2782 } else if (umode == SEEK_END) {
2784 SMB_STRUCT_STAT sbuf;
2786 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2787 END_PROFILE(SMBlseek);
2788 return(UNIXERROR(ERRDOS,ERRnoaccess));
2791 current_pos += sbuf.st_size;
2795 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2799 END_PROFILE(SMBlseek);
2800 return(UNIXERROR(ERRDOS,ERRnoaccess));
2806 outsize = set_message(outbuf,2,0,True);
2807 SIVAL(outbuf,smb_vwv0,res);
2809 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2810 fsp->fnum, (double)startpos, (double)res, mode));
2812 END_PROFILE(SMBlseek);
2816 /****************************************************************************
2818 ****************************************************************************/
2820 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2822 int outsize = set_message(outbuf,0,0,True);
2823 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2824 START_PROFILE(SMBflush);
2827 CHECK_FSP(fsp,conn);
2832 file_sync_all(conn);
2834 sync_file(conn,fsp);
2837 DEBUG(3,("flush\n"));
2838 END_PROFILE(SMBflush);
2843 /****************************************************************************
2845 ****************************************************************************/
2846 int reply_exit(connection_struct *conn,
2847 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2850 START_PROFILE(SMBexit);
2851 outsize = set_message(outbuf,0,0,True);
2853 DEBUG(3,("exit\n"));
2855 END_PROFILE(SMBexit);
2860 /****************************************************************************
2861 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2862 ****************************************************************************/
2863 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2868 int32 eclass = 0, err = 0;
2869 files_struct *fsp = NULL;
2870 START_PROFILE(SMBclose);
2872 outsize = set_message(outbuf,0,0,True);
2874 /* If it's an IPC, pass off to the pipe handler. */
2876 END_PROFILE(SMBclose);
2877 return reply_pipe_close(conn, inbuf,outbuf);
2880 fsp = file_fsp(inbuf,smb_vwv0);
2883 * We can only use CHECK_FSP if we know it's not a directory.
2886 if(!fsp || (fsp->conn != conn)) {
2887 END_PROFILE(SMBclose);
2888 return(ERROR(ERRDOS,ERRbadfid));
2891 if(HAS_CACHED_ERROR(fsp)) {
2892 eclass = fsp->wbmpx_ptr->wr_errclass;
2893 err = fsp->wbmpx_ptr->wr_error;
2896 if(fsp->is_directory || fsp->stat_open) {
2898 * Special case - close NT SMB directory or stat file
2901 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2902 close_file(fsp,True);
2905 * Close ordinary file.
2910 * If there was a modify time outstanding,
2911 * try and set it here.
2913 if(fsp->pending_modtime)
2914 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2917 * Now take care of any time sent in the close.
2919 mtime = make_unix_date3(inbuf+smb_vwv1);
2921 /* try and set the date */
2922 set_filetime(conn, fsp->fsp_name,mtime);
2924 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2926 conn->num_files_open));
2929 * close_file() returns the unix errno if an error
2930 * was detected on close - normally this is due to
2931 * a disk full error. If not then it was probably an I/O error.
2934 if((close_err = close_file(fsp,True)) != 0) {
2936 END_PROFILE(SMBclose);
2937 return (UNIXERROR(ERRHRD,ERRgeneral));
2941 /* We have a cached error */
2943 END_PROFILE(SMBclose);
2944 return(ERROR(eclass,err));
2947 END_PROFILE(SMBclose);
2952 /****************************************************************************
2953 reply to a writeclose (Core+ protocol)
2954 ****************************************************************************/
2956 int reply_writeclose(connection_struct *conn,
2957 char *inbuf,char *outbuf, int size, int dum_buffsize)
2960 ssize_t nwritten = -1;
2966 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2967 START_PROFILE(SMBwriteclose);
2969 CHECK_FSP(fsp,conn);
2973 numtowrite = SVAL(inbuf,smb_vwv1);
2974 startpos = IVAL(inbuf,smb_vwv2);
2975 mtime = make_unix_date3(inbuf+smb_vwv4);
2976 data = smb_buf(inbuf) + 1;
2978 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2979 END_PROFILE(SMBwriteclose);
2980 return(ERROR(ERRDOS,ERRlock));
2983 nwritten = write_file(fsp,data,startpos,numtowrite);
2985 set_filetime(conn, fsp->fsp_name,mtime);
2987 close_err = close_file(fsp,True);
2989 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2990 fsp->fnum, (int)numtowrite, (int)nwritten,
2991 conn->num_files_open));
2993 if (nwritten <= 0) {
2994 END_PROFILE(SMBwriteclose);
2995 return(UNIXERROR(ERRDOS,ERRnoaccess));
2998 if(close_err != 0) {
3000 END_PROFILE(SMBwriteclose);
3001 return(UNIXERROR(ERRHRD,ERRgeneral));
3004 outsize = set_message(outbuf,1,0,True);
3006 SSVAL(outbuf,smb_vwv0,nwritten);
3007 END_PROFILE(SMBwriteclose);
3012 /****************************************************************************
3014 ****************************************************************************/
3015 int reply_lock(connection_struct *conn,
3016 char *inbuf,char *outbuf, int length, int dum_buffsize)
3018 int outsize = set_message(outbuf,0,0,True);
3019 SMB_BIG_UINT count,offset;
3022 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3023 START_PROFILE(SMBlock);
3025 CHECK_FSP(fsp,conn);
3028 release_level_2_oplocks_on_change(fsp);
3030 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3031 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3033 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3034 fsp->fd, fsp->fnum, (double)offset, (double)count));
3036 if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) {
3037 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
3039 * A blocking lock was requested. Package up
3040 * this smb into a queued request and push it
3041 * onto the blocking lock queue.
3043 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
3044 END_PROFILE(SMBlock);
3048 END_PROFILE(SMBlock);
3049 return (ERROR(eclass,ecode));
3052 END_PROFILE(SMBlock);
3057 /****************************************************************************
3059 ****************************************************************************/
3060 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3062 int outsize = set_message(outbuf,0,0,True);
3063 SMB_BIG_UINT count,offset;
3066 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3067 START_PROFILE(SMBunlock);
3069 CHECK_FSP(fsp,conn);
3072 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3073 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3075 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode)) {
3076 END_PROFILE(SMBunlock);
3077 return (ERROR(eclass,ecode));
3080 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3081 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3083 END_PROFILE(SMBunlock);
3088 /****************************************************************************
3090 ****************************************************************************/
3091 int reply_tdis(connection_struct *conn,
3092 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3094 int outsize = set_message(outbuf,0,0,True);
3096 START_PROFILE(SMBtdis);
3098 vuid = SVAL(inbuf,smb_uid);
3101 DEBUG(4,("Invalid connection in tdis\n"));
3102 END_PROFILE(SMBtdis);
3103 return(ERROR(ERRSRV,ERRinvnid));
3108 close_cnum(conn,vuid);
3110 END_PROFILE(SMBtdis);
3116 /****************************************************************************
3118 ****************************************************************************/
3119 int reply_echo(connection_struct *conn,
3120 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3122 int smb_reverb = SVAL(inbuf,smb_vwv0);
3124 unsigned int data_len = smb_buflen(inbuf);
3125 int outsize = set_message(outbuf,1,data_len,True);
3126 START_PROFILE(SMBecho);
3128 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3130 /* copy any incoming data back out */
3132 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3134 if (smb_reverb > 100) {
3135 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3139 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3140 SSVAL(outbuf,smb_vwv0,seq_num);
3142 smb_setlen(outbuf,outsize - 4);
3144 send_smb(smbd_server_fd(),outbuf);
3147 DEBUG(3,("echo %d times\n", smb_reverb));
3151 END_PROFILE(SMBecho);
3156 /****************************************************************************
3157 reply to a printopen
3158 ****************************************************************************/
3159 int reply_printopen(connection_struct *conn,
3160 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3164 START_PROFILE(SMBsplopen);
3166 if (!CAN_PRINT(conn)) {
3167 END_PROFILE(SMBsplopen);
3168 return(ERROR(ERRDOS,ERRnoaccess));
3171 /* Open for exclusive use, write only. */
3172 fsp = print_fsp_open(conn,"dos.prn");
3175 END_PROFILE(SMBsplopen);
3176 return(UNIXERROR(ERRDOS,ERRnoaccess));
3179 outsize = set_message(outbuf,1,0,True);
3180 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3182 DEBUG(3,("openprint fd=%d fnum=%d\n",
3183 fsp->fd, fsp->fnum));
3185 END_PROFILE(SMBsplopen);
3190 /****************************************************************************
3191 reply to a printclose
3192 ****************************************************************************/
3193 int reply_printclose(connection_struct *conn,
3194 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3196 int outsize = set_message(outbuf,0,0,True);
3197 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3199 START_PROFILE(SMBsplclose);
3201 CHECK_FSP(fsp,conn);
3204 if (!CAN_PRINT(conn)) {
3205 END_PROFILE(SMBsplclose);
3206 return(ERROR(ERRDOS,ERRnoaccess));
3209 DEBUG(3,("printclose fd=%d fnum=%d\n",
3210 fsp->fd,fsp->fnum));
3212 close_err = close_file(fsp,True);
3214 if(close_err != 0) {
3216 END_PROFILE(SMBsplclose);
3217 return(UNIXERROR(ERRHRD,ERRgeneral));
3220 END_PROFILE(SMBsplclose);
3225 /****************************************************************************
3226 reply to a printqueue
3227 ****************************************************************************/
3228 int reply_printqueue(connection_struct *conn,
3229 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3231 int outsize = set_message(outbuf,2,3,True);
3232 int max_count = SVAL(inbuf,smb_vwv0);
3233 int start_index = SVAL(inbuf,smb_vwv1);
3234 START_PROFILE(SMBsplretq);
3236 /* we used to allow the client to get the cnum wrong, but that
3237 is really quite gross and only worked when there was only
3238 one printer - I think we should now only accept it if they
3239 get it right (tridge) */
3240 if (!CAN_PRINT(conn)) {
3241 END_PROFILE(SMBsplretq);
3242 return(ERROR(ERRDOS,ERRnoaccess));
3245 SSVAL(outbuf,smb_vwv0,0);
3246 SSVAL(outbuf,smb_vwv1,0);
3247 CVAL(smb_buf(outbuf),0) = 1;
3248 SSVAL(smb_buf(outbuf),1,0);
3250 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3251 start_index, max_count));
3254 print_queue_struct *queue = NULL;
3255 char *p = smb_buf(outbuf) + 3;
3256 int count = print_queue_status(SNUM(conn), &queue,NULL);
3257 int num_to_get = ABS(max_count);
3258 int first = (max_count>0?start_index:start_index+max_count+1);
3264 num_to_get = MIN(num_to_get,count-first);
3267 for (i=first;i<first+num_to_get;i++) {
3268 put_dos_date2(p,0,queue[i].time);
3269 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3270 SSVAL(p,5, queue[i].job);
3271 SIVAL(p,7,queue[i].size);
3273 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_CONVERT|STR_ASCII);
3278 outsize = set_message(outbuf,2,28*count+3,False);
3279 SSVAL(outbuf,smb_vwv0,count);
3280 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3281 CVAL(smb_buf(outbuf),0) = 1;
3282 SSVAL(smb_buf(outbuf),1,28*count);
3285 if (queue) free(queue);
3287 DEBUG(3,("%d entries returned in queue\n",count));
3290 END_PROFILE(SMBsplretq);
3295 /****************************************************************************
3296 reply to a printwrite
3297 ****************************************************************************/
3298 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3301 int outsize = set_message(outbuf,0,0,True);
3303 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3304 START_PROFILE(SMBsplwr);
3306 if (!CAN_PRINT(conn)) {
3307 END_PROFILE(SMBsplwr);
3308 return(ERROR(ERRDOS,ERRnoaccess));
3311 CHECK_FSP(fsp,conn);
3315 numtowrite = SVAL(smb_buf(inbuf),1);
3316 data = smb_buf(inbuf) + 3;
3318 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3319 END_PROFILE(SMBsplwr);
3320 return(UNIXERROR(ERRDOS,ERRnoaccess));
3323 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3325 END_PROFILE(SMBsplwr);
3330 /****************************************************************************
3331 The guts of the mkdir command, split out so it may be called by the NT SMB
3333 ****************************************************************************/
3334 int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
3336 BOOL bad_path = False;
3337 SMB_STRUCT_STAT sbuf;
3340 unix_convert(directory,conn,0,&bad_path,&sbuf);
3342 if (check_name(directory, conn))
3343 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3347 if((errno == ENOENT) && bad_path)
3349 unix_ERR_class = ERRDOS;
3350 unix_ERR_code = ERRbadpath;
3352 return(UNIXERROR(ERRDOS,ERRnoaccess));
3358 /****************************************************************************
3360 ****************************************************************************/
3361 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3365 START_PROFILE(SMBmkdir);
3367 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3369 outsize=mkdir_internal(conn, inbuf, outbuf, directory);
3371 outsize = set_message(outbuf,0,0,True);
3373 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3375 END_PROFILE(SMBmkdir);
3379 /****************************************************************************
3380 Static function used by reply_rmdir to delete an entire directory
3382 ****************************************************************************/
3384 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3388 void *dirptr = OpenDir(NULL, directory, False);
3393 while((dname = ReadDirName(dirptr)))
3398 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3401 /* Construct the full name. */
3402 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3408 pstrcpy(fullname, directory);
3409 pstrcat(fullname, "/");
3410 pstrcat(fullname, dname);
3412 if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname,False), &st) != 0)
3418 if(st.st_mode & S_IFDIR)
3420 if(recursive_rmdir(conn, fullname)!=0)
3425 if(vfs_rmdir(conn,fullname) != 0)
3431 else if(vfs_unlink(conn,fullname) != 0)
3441 /****************************************************************************
3442 The internals of the rmdir code - called elsewhere.
3443 ****************************************************************************/
3445 BOOL rmdir_internals(connection_struct *conn, char *directory)
3449 ok = (vfs_rmdir(conn,directory) == 0);
3450 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3453 * Check to see if the only thing in this directory are
3454 * vetoed files/directories. If so then delete them and
3455 * retry. If we fail to delete any of them (and we *don't*
3456 * do a recursive delete) then fail the rmdir.
3458 BOOL all_veto_files = True;
3460 void *dirptr = OpenDir(conn, directory, False);
3464 int dirpos = TellDir(dirptr);
3465 while ((dname = ReadDirName(dirptr)))
3467 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3469 if(!IS_VETO_PATH(conn, dname))
3471 all_veto_files = False;
3477 SeekDir(dirptr,dirpos);
3478 while ((dname = ReadDirName(dirptr)))
3483 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3486 /* Construct the full name. */
3487 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3492 pstrcpy(fullname, directory);
3493 pstrcat(fullname, "/");
3494 pstrcat(fullname, dname);
3496 if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname, False), &st) != 0)
3498 if(st.st_mode & S_IFDIR)
3500 if(lp_recursive_veto_delete(SNUM(conn)))
3502 if(recursive_rmdir(conn, fullname) != 0)
3505 if(vfs_rmdir(conn,fullname) != 0)
3508 else if(vfs_unlink(conn,fullname) != 0)
3512 /* Retry the rmdir */
3513 ok = (vfs_rmdir(conn,directory) == 0);
3523 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3524 directory,strerror(errno)));
3529 /****************************************************************************
3531 ****************************************************************************/
3533 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3538 BOOL bad_path = False;
3539 SMB_STRUCT_STAT sbuf;
3540 START_PROFILE(SMBrmdir);
3542 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3544 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3546 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3548 if (check_name(directory,conn))
3550 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3551 ok = rmdir_internals(conn, directory);
3556 if((errno == ENOENT) && bad_path)
3558 unix_ERR_class = ERRDOS;
3559 unix_ERR_code = ERRbadpath;
3561 END_PROFILE(SMBrmdir);
3562 return(UNIXERROR(ERRDOS,ERRbadpath));
3565 outsize = set_message(outbuf,0,0,True);
3567 DEBUG( 3, ( "rmdir %s\n", directory ) );
3569 END_PROFILE(SMBrmdir);
3574 /*******************************************************************
3575 resolve wildcards in a filename rename
3576 ********************************************************************/
3577 static BOOL resolve_wildcards(char *name1,char *name2)
3579 fstring root1,root2;
3583 name1 = strrchr(name1,'/');
3584 name2 = strrchr(name2,'/');
3586 if (!name1 || !name2) return(False);
3588 fstrcpy(root1,name1);
3589 fstrcpy(root2,name2);
3590 p = strrchr(root1,'.');
3597 p = strrchr(root2,'.');
3629 pstrcpy(name2,root2);
3632 pstrcat(name2,ext2);
3638 /*******************************************************************
3639 check if a user is allowed to rename a file
3640 ********************************************************************/
3641 static BOOL can_rename(char *fname,connection_struct *conn)
3643 SMB_STRUCT_STAT sbuf;
3645 if (!CAN_WRITE(conn)) return(False);
3647 if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False);
3648 if (!check_file_sharing(conn,fname,True)) return(False);
3652 /****************************************************************************
3653 The guts of the rename command, split out so it may be called by the NT SMB
3655 ****************************************************************************/
3656 int rename_internals(connection_struct *conn,
3657 char *inbuf, char *outbuf, char *name,
3658 char *newname, BOOL replace_if_exists)
3662 pstring newname_last_component;
3665 BOOL bad_path1 = False;
3666 BOOL bad_path2 = False;
3668 int error = ERRnoaccess;
3671 SMB_STRUCT_STAT sbuf1, sbuf2;
3674 *directory = *mask = 0;
3676 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3677 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3680 * Split the old name into directory and last component
3681 * strings. Note that unix_convert may have stripped off a
3682 * leading ./ from both name and newname if the rename is
3683 * at the root of the share. We need to make sure either both
3684 * name and newname contain a / character or neither of them do
3685 * as this is checked in resolve_wildcards().
3688 p = strrchr(name,'/');
3690 pstrcpy(directory,".");
3694 pstrcpy(directory,name);
3696 *p = '/'; /* Replace needed for exceptional test below. */
3700 * We should only check the mangled cache
3701 * here if unix_convert failed. This means
3702 * that the path in 'mask' doesn't exist
3703 * on the file system and so we need to look
3704 * for a possible mangle. This patch from
3705 * Tine Smukavec <valentin.smukavec@hermes.si>.
3708 if (!rc && is_mangled(mask))
3709 check_mangled_cache( mask );
3711 has_wild = ms_has_wild(mask);
3715 * No wildcards - just process the one file.
3717 BOOL is_short_name = is_8_3(name, True);
3719 /* Add a terminating '/' to the directory name. */
3720 pstrcat(directory,"/");
3721 pstrcat(directory,mask);
3723 /* Ensure newname contains a '/' also */
3724 if(strrchr(newname,'/') == 0) {
3727 pstrcpy(tmpstr, "./");
3728 pstrcat(tmpstr, newname);
3729 pstrcpy(newname, tmpstr);
3732 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",
3733 case_sensitive, case_preserve, short_case_preserve, directory,
3734 newname, newname_last_component, is_short_name));
3737 * Check for special case with case preserving and not
3738 * case sensitive, if directory and newname are identical,
3739 * and the old last component differs from the original
3740 * last component only by case, then we should allow
3741 * the rename (user is trying to change the case of the
3744 if((case_sensitive == False) &&
3745 (((case_preserve == True) &&
3746 (is_short_name == False)) ||
3747 ((short_case_preserve == True) &&
3748 (is_short_name == True))) &&
3749 strcsequal(directory, newname)) {
3750 pstring newname_modified_last_component;
3753 * Get the last component of the modified name.
3754 * Note that we guarantee that newname contains a '/'
3757 p = strrchr(newname,'/');
3758 pstrcpy(newname_modified_last_component,p+1);
3760 if(strcsequal(newname_modified_last_component,
3761 newname_last_component) == False) {
3763 * Replace the modified last component with
3766 pstrcpy(p+1, newname_last_component);
3770 pstrcpy(zdirectory, dos_to_unix(directory, False));
3771 if(replace_if_exists) {
3773 * NT SMB specific flag - rename can overwrite
3774 * file with the same name so don't check for
3778 if(resolve_wildcards(directory,newname) &&
3779 can_rename(directory,conn) &&
3780 !conn->vfs_ops.rename(conn,zdirectory,
3781 dos_to_unix(newname,False)))
3784 if (resolve_wildcards(directory,newname) &&
3785 can_rename(directory,conn) &&
3786 !vfs_file_exist(conn,newname,NULL) &&
3787 !conn->vfs_ops.rename(conn,zdirectory,
3788 dos_to_unix(newname,False)))
3792 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3793 directory,newname));
3795 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3796 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3802 * Wildcards - process each file that matches.
3804 void *dirptr = NULL;
3808 if (check_name(directory,conn))
3809 dirptr = OpenDir(conn, directory, True);
3814 if (strequal(mask,"????????.???"))
3817 while ((dname = ReadDirName(dirptr))) {
3820 pstrcpy(fname,dname);
3822 if(!mask_match(fname, mask, case_sensitive))
3825 error = ERRnoaccess;
3826 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3827 if (!can_rename(fname,conn)) {
3828 DEBUG(6,("rename %s refused\n", fname));
3831 pstrcpy(destname,newname);
3833 if (!resolve_wildcards(fname,destname)) {
3834 DEBUG(6,("resolve_wildcards %s %s failed\n",
3839 if (!replace_if_exists &&
3840 vfs_file_exist(conn,destname, NULL)) {
3841 DEBUG(6,("file_exist %s\n", destname));
3846 if (!conn->vfs_ops.rename(conn,dos_to_unix(fname,False),
3847 dos_to_unix(destname,False)))
3849 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3857 return(ERROR(ERRDOS,error));
3859 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3860 unix_ERR_class = ERRDOS;
3861 unix_ERR_code = ERRbadpath;
3863 return(UNIXERROR(ERRDOS,error));
3870 /****************************************************************************
3872 ****************************************************************************/
3874 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3881 START_PROFILE(SMBmv);
3883 p = smb_buf(inbuf) + 1;
3884 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3886 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3888 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3889 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3891 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3893 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3897 * Win2k needs a changenotify request response before it will
3898 * update after a rename..
3901 process_pending_change_notify_queue((time_t)0);
3903 outsize = set_message(outbuf,0,0,True);
3910 /*******************************************************************
3911 copy a file as part of a reply_copy
3912 ******************************************************************/
3914 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3915 int count,BOOL target_is_directory, int *err_ret)
3918 SMB_STRUCT_STAT src_sbuf, sbuf2;
3920 files_struct *fsp1,*fsp2;
3925 pstrcpy(dest,dest1);
3926 if (target_is_directory) {
3927 char *p = strrchr(src,'/');
3936 if (!vfs_file_exist(conn,src,&src_sbuf))
3939 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3940 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3946 if (!target_is_directory && count)
3947 ofun = FILE_EXISTS_OPEN;
3949 vfs_stat(conn,dest,&sbuf2);
3950 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3951 ofun,src_sbuf.st_mode,0,&Access,&action);
3954 close_file(fsp1,False);
3958 if ((ofun&3) == 1) {
3959 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3960 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3963 * Stop the copy from occurring.
3966 src_sbuf.st_size = 0;
3970 if (src_sbuf.st_size)
3971 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
3973 close_file(fsp1,False);
3975 * As we are opening fsp1 read-only we only expect
3976 * an error on close on fsp2 if we are out of space.
3977 * Thus we don't look at the error return from the
3980 *err_ret = close_file(fsp2,False);
3982 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3987 /****************************************************************************
3988 reply to a file copy.
3989 ****************************************************************************/
3990 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3995 pstring mask,newname;
3998 int error = ERRnoaccess;
4002 int tid2 = SVAL(inbuf,smb_vwv0);
4003 int ofun = SVAL(inbuf,smb_vwv1);
4004 int flags = SVAL(inbuf,smb_vwv2);
4005 BOOL target_is_directory=False;
4006 BOOL bad_path1 = False;
4007 BOOL bad_path2 = False;
4009 SMB_STRUCT_STAT sbuf1, sbuf2;
4010 START_PROFILE(SMBcopy);
4012 *directory = *mask = 0;
4015 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
4016 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
4018 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4020 if (tid2 != conn->cnum) {
4021 /* can't currently handle inter share copies XXXX */
4022 DEBUG(3,("Rejecting inter-share copy\n"));
4023 END_PROFILE(SMBcopy);
4024 return(ERROR(ERRSRV,ERRinvdevice));
4027 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4028 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4030 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4031 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4033 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4035 if ((flags&1) && target_is_directory) {
4036 END_PROFILE(SMBcopy);
4037 return(ERROR(ERRDOS,ERRbadfile));
4040 if ((flags&2) && !target_is_directory) {
4041 END_PROFILE(SMBcopy);
4042 return(ERROR(ERRDOS,ERRbadpath));
4045 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4046 /* wants a tree copy! XXXX */
4047 DEBUG(3,("Rejecting tree copy\n"));
4048 END_PROFILE(SMBcopy);
4049 return(ERROR(ERRSRV,ERRerror));
4052 p = strrchr(name,'/');
4054 pstrcpy(directory,"./");
4058 pstrcpy(directory,name);
4063 * We should only check the mangled cache
4064 * here if unix_convert failed. This means
4065 * that the path in 'mask' doesn't exist
4066 * on the file system and so we need to look
4067 * for a possible mangle. This patch from
4068 * Tine Smukavec <valentin.smukavec@hermes.si>.
4071 if (!rc && is_mangled(mask))
4072 check_mangled_cache( mask );
4074 has_wild = ms_has_wild(mask);
4077 pstrcat(directory,"/");
4078 pstrcat(directory,mask);
4079 if (resolve_wildcards(directory,newname) &&
4080 copy_file(directory,newname,conn,ofun,
4081 count,target_is_directory,&err)) count++;
4084 END_PROFILE(SMBcopy);
4085 return(UNIXERROR(ERRHRD,ERRgeneral));
4087 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4089 void *dirptr = NULL;
4093 if (check_name(directory,conn))
4094 dirptr = OpenDir(conn, directory, True);
4099 if (strequal(mask,"????????.???"))
4102 while ((dname = ReadDirName(dirptr))) {
4104 pstrcpy(fname,dname);
4106 if(!mask_match(fname, mask, case_sensitive))
4109 error = ERRnoaccess;
4110 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4111 pstrcpy(destname,newname);
4112 if (resolve_wildcards(fname,destname) &&
4113 copy_file(fname,destname,conn,ofun,
4114 count,target_is_directory,&err)) count++;
4115 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4123 /* Error on close... */
4125 END_PROFILE(SMBcopy);
4126 return(UNIXERROR(ERRHRD,ERRgeneral));
4130 END_PROFILE(SMBcopy);
4131 return(ERROR(ERRDOS,error));
4134 if((errno == ENOENT) && (bad_path1 || bad_path2))
4136 unix_ERR_class = ERRDOS;
4137 unix_ERR_code = ERRbadpath;
4139 END_PROFILE(SMBcopy);
4140 return(UNIXERROR(ERRDOS,error));
4144 outsize = set_message(outbuf,1,0,True);
4145 SSVAL(outbuf,smb_vwv0,count);
4147 END_PROFILE(SMBcopy);
4151 /****************************************************************************
4153 ****************************************************************************/
4154 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4160 START_PROFILE(pathworks_setdir);
4163 if (!CAN_SETDIR(snum)) {
4164 END_PROFILE(pathworks_setdir);
4165 return(ERROR(ERRDOS,ERRnoaccess));
4168 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE|STR_CONVERT);
4170 if (strlen(newdir) == 0) {
4173 ok = vfs_directory_exist(conn,newdir,NULL);
4175 string_set(&conn->connectpath,newdir);
4180 END_PROFILE(pathworks_setdir);
4181 return(ERROR(ERRDOS,ERRbadpath));
4184 outsize = set_message(outbuf,0,0,True);
4185 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4187 DEBUG(3,("setdir %s\n", newdir));
4189 END_PROFILE(pathworks_setdir);
4193 /****************************************************************************
4194 Get a lock count, dealing with large count requests.
4195 ****************************************************************************/
4197 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4199 SMB_BIG_UINT count = 0;
4201 if(!large_file_format) {
4202 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4205 #if defined(HAVE_LONGLONG)
4206 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4207 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4208 #else /* HAVE_LONGLONG */
4211 * NT4.x seems to be broken in that it sends large file (64 bit)
4212 * lockingX calls even if the CAP_LARGE_FILES was *not*
4213 * negotiated. For boxes without large unsigned ints truncate the
4214 * lock count by dropping the top 32 bits.
4217 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4218 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4219 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4220 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4221 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4224 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4225 #endif /* HAVE_LONGLONG */
4231 /****************************************************************************
4232 Get a lock offset, dealing with large offset requests.
4233 ****************************************************************************/
4235 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4237 SMB_BIG_UINT offset = 0;
4241 if(!large_file_format) {
4242 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4245 #if defined(HAVE_LONGLONG)
4246 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4247 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4248 #else /* HAVE_LONGLONG */
4251 * NT4.x seems to be broken in that it sends large file (64 bit)
4252 * lockingX calls even if the CAP_LARGE_FILES was *not*
4253 * negotiated. For boxes without large unsigned ints mangle the
4254 * lock offset by mapping the top 32 bits onto the lower 32.
4257 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4258 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4259 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4262 if((new_low = map_lock_offset(high, low)) == 0) {
4264 return (SMB_BIG_UINT)-1;
4267 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4268 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4269 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4270 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4273 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4274 #endif /* HAVE_LONGLONG */
4280 /****************************************************************************
4281 reply to a lockingX request
4282 ****************************************************************************/
4284 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4286 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4287 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4288 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4289 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4290 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4291 SMB_BIG_UINT count = 0, offset = 0;
4292 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4295 uint32 ecode=0, dummy2;
4296 int eclass=0, dummy1;
4297 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4299 START_PROFILE(SMBlockingX);
4301 CHECK_FSP(fsp,conn);
4304 data = smb_buf(inbuf);
4306 /* Check if this is an oplock break on a file
4307 we have granted an oplock on.
4309 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4311 /* Client can insist on breaking to none. */
4312 BOOL break_to_none = (oplocklevel == 0);
4314 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4315 fsp->fnum, (unsigned int)oplocklevel ));
4318 * Make sure we have granted an exclusive or batch oplock on this file.
4321 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4323 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4324 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4326 /* if this is a pure oplock break request then don't send a reply */
4327 if (num_locks == 0 && num_ulocks == 0) {
4328 END_PROFILE(SMBlockingX);
4331 END_PROFILE(SMBlockingX);
4332 return ERROR(ERRDOS,ERRlock);
4336 if (remove_oplock(fsp, break_to_none) == False) {
4337 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4341 /* if this is a pure oplock break request then don't send a reply */
4342 if (num_locks == 0 && num_ulocks == 0)
4344 /* Sanity check - ensure a pure oplock break is not a
4346 if(CVAL(inbuf,smb_vwv0) != 0xff)
4347 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4348 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4349 END_PROFILE(SMBlockingX);
4355 * We do this check *after* we have checked this is not a oplock break
4356 * response message. JRA.
4359 release_level_2_oplocks_on_change(fsp);
4361 /* Data now points at the beginning of the list
4362 of smb_unlkrng structs */
4363 for(i = 0; i < (int)num_ulocks; i++) {
4364 count = get_lock_count( data, i, large_file_format);
4365 offset = get_lock_offset( data, i, large_file_format, &err);
4368 * There is no error code marked "stupid client bug".... :-).
4371 END_PROFILE(SMBlockingX);
4372 return ERROR(ERRDOS,ERRnoaccess);
4375 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
4376 (double)offset, (double)count, fsp->fsp_name ));
4378 if(!do_unlock(fsp,conn,count,offset, &eclass, &ecode)) {
4379 END_PROFILE(SMBlockingX);
4380 return ERROR(eclass,ecode);
4384 /* Setup the timeout in seconds. */
4385 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4387 /* Now do any requested locks */
4388 data += ((large_file_format ? 20 : 10)*num_ulocks);
4390 /* Data now points at the beginning of the list
4391 of smb_lkrng structs */
4393 for(i = 0; i < (int)num_locks; i++) {
4394 count = get_lock_count( data, i, large_file_format);
4395 offset = get_lock_offset( data, i, large_file_format, &err);
4398 * There is no error code marked "stupid client bug".... :-).
4401 END_PROFILE(SMBlockingX);
4402 return ERROR(ERRDOS,ERRnoaccess);
4405 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
4406 (double)offset, (double)count, fsp->fsp_name ));
4408 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4410 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4412 * A blocking lock was requested. Package up
4413 * this smb into a queued request and push it
4414 * onto the blocking lock queue.
4416 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4417 END_PROFILE(SMBlockingX);
4425 /* If any of the above locks failed, then we must unlock
4426 all of the previous locks (X/Open spec). */
4427 if(i != num_locks && num_locks != 0) {
4429 * Ensure we don't do a remove on the lock that just failed,
4430 * as under POSIX rules, if we have a lock already there, we
4431 * will delete it (and we shouldn't) .....
4433 for(i--; i >= 0; i--) {
4434 count = get_lock_count( data, i, large_file_format);
4435 offset = get_lock_offset( data, i, large_file_format, &err);
4438 * There is no error code marked "stupid client bug".... :-).
4441 END_PROFILE(SMBlockingX);
4442 return ERROR(ERRDOS,ERRnoaccess);
4445 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
4447 END_PROFILE(SMBlockingX);
4448 return ERROR(eclass,ecode);
4451 set_message(outbuf,2,0,True);
4453 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4454 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4456 END_PROFILE(SMBlockingX);
4457 return chain_reply(inbuf,outbuf,length,bufsize);
4461 /****************************************************************************
4462 reply to a SMBreadbmpx (read block multiplex) request
4463 ****************************************************************************/
4464 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4475 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4476 START_PROFILE(SMBreadBmpx);
4478 /* this function doesn't seem to work - disable by default */
4479 if (!lp_readbmpx()) {
4480 END_PROFILE(SMBreadBmpx);
4481 return(ERROR(ERRSRV,ERRuseSTD));
4484 outsize = set_message(outbuf,8,0,True);
4486 CHECK_FSP(fsp,conn);
4490 startpos = IVAL(inbuf,smb_vwv1);
4491 maxcount = SVAL(inbuf,smb_vwv3);
4493 data = smb_buf(outbuf);
4494 pad = ((long)data)%4;
4495 if (pad) pad = 4 - pad;
4498 max_per_packet = bufsize-(outsize+pad);
4502 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
4503 END_PROFILE(SMBreadBmpx);
4504 return(ERROR(ERRDOS,ERRlock));
4509 size_t N = MIN(max_per_packet,tcount-total_read);
4511 nread = read_file(fsp,data,startpos,N);
4513 if (nread <= 0) nread = 0;
4515 if (nread < (ssize_t)N)
4516 tcount = total_read + nread;
4518 set_message(outbuf,8,nread,False);
4519 SIVAL(outbuf,smb_vwv0,startpos);
4520 SSVAL(outbuf,smb_vwv2,tcount);
4521 SSVAL(outbuf,smb_vwv6,nread);
4522 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4524 send_smb(smbd_server_fd(),outbuf);
4526 total_read += nread;
4529 while (total_read < (ssize_t)tcount);
4531 END_PROFILE(SMBreadBmpx);
4535 /****************************************************************************
4536 reply to a SMBwritebmpx (write block multiplex primary) request
4537 ****************************************************************************/
4539 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4542 ssize_t nwritten = -1;
4549 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4550 START_PROFILE(SMBwriteBmpx);
4552 CHECK_FSP(fsp,conn);
4556 tcount = SVAL(inbuf,smb_vwv1);
4557 startpos = IVAL(inbuf,smb_vwv3);
4558 write_through = BITSETW(inbuf+smb_vwv7,0);
4559 numtowrite = SVAL(inbuf,smb_vwv10);
4560 smb_doff = SVAL(inbuf,smb_vwv11);
4562 data = smb_base(inbuf) + smb_doff;
4564 /* If this fails we need to send an SMBwriteC response,
4565 not an SMBwritebmpx - set this up now so we don't forget */
4566 CVAL(outbuf,smb_com) = SMBwritec;
4568 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
4569 END_PROFILE(SMBwriteBmpx);
4570 return(ERROR(ERRDOS,ERRlock));
4573 nwritten = write_file(fsp,data,startpos,numtowrite);
4575 if(lp_syncalways(SNUM(conn)) || write_through)
4576 sync_file(conn,fsp);
4578 if(nwritten < (ssize_t)numtowrite) {
4579 END_PROFILE(SMBwriteBmpx);
4580 return(UNIXERROR(ERRHRD,ERRdiskfull));
4583 /* If the maximum to be written to this file
4584 is greater than what we just wrote then set
4585 up a secondary struct to be attached to this
4586 fd, we will use this to cache error messages etc. */
4587 if((ssize_t)tcount > nwritten)
4589 write_bmpx_struct *wbms;
4590 if(fsp->wbmpx_ptr != NULL)
4591 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4593 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4596 DEBUG(0,("Out of memory in reply_readmpx\n"));
4597 END_PROFILE(SMBwriteBmpx);
4598 return(ERROR(ERRSRV,ERRnoresource));
4600 wbms->wr_mode = write_through;
4601 wbms->wr_discard = False; /* No errors yet */
4602 wbms->wr_total_written = nwritten;
4603 wbms->wr_errclass = 0;
4605 fsp->wbmpx_ptr = wbms;
4608 /* We are returning successfully, set the message type back to
4610 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4612 outsize = set_message(outbuf,1,0,True);
4614 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4616 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4617 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4619 if (write_through && tcount==nwritten) {
4620 /* we need to send both a primary and a secondary response */
4621 smb_setlen(outbuf,outsize - 4);
4622 send_smb(smbd_server_fd(),outbuf);
4624 /* now the secondary */
4625 outsize = set_message(outbuf,1,0,True);
4626 CVAL(outbuf,smb_com) = SMBwritec;
4627 SSVAL(outbuf,smb_vwv0,nwritten);
4630 END_PROFILE(SMBwriteBmpx);
4635 /****************************************************************************
4636 reply to a SMBwritebs (write block multiplex secondary) request
4637 ****************************************************************************/
4638 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4641 ssize_t nwritten = -1;
4648 write_bmpx_struct *wbms;
4649 BOOL send_response = False;
4650 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4651 START_PROFILE(SMBwriteBs);
4653 CHECK_FSP(fsp,conn);
4656 tcount = SVAL(inbuf,smb_vwv1);
4657 startpos = IVAL(inbuf,smb_vwv2);
4658 numtowrite = SVAL(inbuf,smb_vwv6);
4659 smb_doff = SVAL(inbuf,smb_vwv7);
4661 data = smb_base(inbuf) + smb_doff;
4663 /* We need to send an SMBwriteC response, not an SMBwritebs */
4664 CVAL(outbuf,smb_com) = SMBwritec;
4666 /* This fd should have an auxiliary struct attached,
4667 check that it does */
4668 wbms = fsp->wbmpx_ptr;
4670 END_PROFILE(SMBwriteBs);
4674 /* If write through is set we can return errors, else we must
4676 write_through = wbms->wr_mode;
4678 /* Check for an earlier error */
4679 if(wbms->wr_discard) {
4680 END_PROFILE(SMBwriteBs);
4681 return -1; /* Just discard the packet */
4684 nwritten = write_file(fsp,data,startpos,numtowrite);
4686 if(lp_syncalways(SNUM(conn)) || write_through)
4687 sync_file(conn,fsp);
4689 if (nwritten < (ssize_t)numtowrite)
4693 /* We are returning an error - we can delete the aux struct */
4694 if (wbms) free((char *)wbms);
4695 fsp->wbmpx_ptr = NULL;
4696 END_PROFILE(SMBwriteBs);
4697 return(ERROR(ERRHRD,ERRdiskfull));
4699 END_PROFILE(SMBwriteBs);
4700 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4703 /* Increment the total written, if this matches tcount
4704 we can discard the auxiliary struct (hurrah !) and return a writeC */
4705 wbms->wr_total_written += nwritten;
4706 if(wbms->wr_total_written >= tcount)
4710 outsize = set_message(outbuf,1,0,True);
4711 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4712 send_response = True;
4716 fsp->wbmpx_ptr = NULL;
4720 END_PROFILE(SMBwriteBs);
4724 END_PROFILE(SMBwriteBs);
4729 /****************************************************************************
4730 reply to a SMBsetattrE
4731 ****************************************************************************/
4733 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4735 struct utimbuf unix_times;
4737 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4738 START_PROFILE(SMBsetattrE);
4740 outsize = set_message(outbuf,0,0,True);
4742 CHECK_FSP(fsp,conn);
4745 /* Convert the DOS times into unix times. Ignore create
4746 time as UNIX can't set this.
4748 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4749 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4752 * Patch from Ray Frush <frush@engr.colostate.edu>
4753 * Sometimes times are sent as zero - ignore them.
4756 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4758 /* Ignore request */
4761 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4762 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4764 END_PROFILE(SMBsetattrE);
4767 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4769 /* set modify time = to access time if modify time was 0 */
4770 unix_times.modtime = unix_times.actime;
4773 /* Set the date on this file */
4774 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4775 END_PROFILE(SMBsetattrE);
4776 return(ERROR(ERRDOS,ERRnoaccess));
4779 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4780 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4782 END_PROFILE(SMBsetattrE);
4787 /****************************************************************************
4788 reply to a SMBgetattrE
4789 ****************************************************************************/
4791 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4793 SMB_STRUCT_STAT sbuf;
4796 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4797 START_PROFILE(SMBgetattrE);
4799 outsize = set_message(outbuf,11,0,True);
4801 CHECK_FSP(fsp,conn);
4804 /* Do an fstat on this file */
4805 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4806 END_PROFILE(SMBgetattrE);
4807 return(UNIXERROR(ERRDOS,ERRnoaccess));
4810 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4812 /* Convert the times into dos times. Set create
4813 date to be last modify date as UNIX doesn't save
4815 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4816 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4817 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4820 SIVAL(outbuf,smb_vwv6,0);
4821 SIVAL(outbuf,smb_vwv8,0);
4825 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4826 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4828 SSVAL(outbuf,smb_vwv10, mode);
4830 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4832 END_PROFILE(SMBgetattrE);