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() );
60 /****************************************************************************
61 reply to an special message
62 ****************************************************************************/
64 int reply_special(char *inbuf,char *outbuf)
67 int msg_type = CVAL(inbuf,0);
68 int msg_flags = CVAL(inbuf,1);
70 extern fstring remote_machine;
71 extern fstring local_machine;
77 memset(outbuf,'\0',smb_size);
82 case 0x81: /* session request */
83 CVAL(outbuf,0) = 0x82;
85 if (name_len(inbuf+4) > 50 ||
86 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
87 DEBUG(0,("Invalid name length in session request\n"));
90 name_extract(inbuf,4,name1);
91 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
92 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
95 fstrcpy(remote_machine,name2);
96 remote_machine[15] = 0;
97 trim_string(remote_machine," "," ");
98 strlower(remote_machine);
99 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
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);
109 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
111 DEBUG(2,("netbios connect: local=%s remote=%s\n",
112 local_machine, remote_machine ));
114 if (name_type == 'R') {
115 /* We are being asked for a pathworks session ---
117 CVAL(outbuf, 0) = 0x83;
121 /* only add the client's machine name to the list
122 of possibly valid usernames if we are operating
123 in share mode security */
124 if (lp_security() == SEC_SHARE) {
125 add_session_user(remote_machine);
128 reload_services(True);
132 claim_connection(NULL,"",MAXSTATUS,True);
137 case 0x89: /* session keepalive request
138 (some old clients produce this?) */
139 CVAL(outbuf,0) = 0x85;
143 case 0x82: /* positive session response */
144 case 0x83: /* negative session response */
145 case 0x84: /* retarget session response */
146 DEBUG(0,("Unexpected session response\n"));
149 case 0x85: /* session keepalive */
154 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
155 msg_type, msg_flags));
161 /*******************************************************************
162 work out what error to give to a failed connection
163 ********************************************************************/
165 static int connection_error(char *inbuf,char *outbuf,int ecode)
167 if (ecode == ERRnoipc || ecode == ERRnosuchshare)
168 return(ERROR(ERRDOS,ecode));
170 return(ERROR(ERRSRV,ecode));
174 /****************************************************************************
176 ****************************************************************************/
178 int reply_tcon(connection_struct *conn,
179 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
186 uint16 vuid = SVAL(inbuf,smb_uid);
191 START_PROFILE(SMBtcon);
193 *service = *user = *password = *dev = 0;
195 p = smb_buf(inbuf)+1;
196 p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1;
197 p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
198 p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1;
201 p = strchr_m(service,'%');
207 p = strrchr_m(service,'\\');
209 pstrcpy(service, p+1);
213 * If the vuid is valid, we should be using that....
216 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
217 pstrcpy(user,validated_username(vuid));
221 * Pass the user through the NT -> unix user mapping
225 (void)map_username(user);
228 * Do any UNIX username case mangling.
230 (void)Get_Pwnam( user, True);
233 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
236 END_PROFILE(SMBtcon);
237 return(connection_error(inbuf,outbuf,ecode));
240 outsize = set_message(outbuf,2,0,True);
241 SSVAL(outbuf,smb_vwv0,max_recv);
242 SSVAL(outbuf,smb_vwv1,conn->cnum);
243 SSVAL(outbuf,smb_tid,conn->cnum);
245 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
246 service, user, conn->cnum));
248 END_PROFILE(SMBtcon);
252 /****************************************************************************
253 Reply to a tcon and X.
254 ****************************************************************************/
256 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
263 uint16 vuid = SVAL(inbuf,smb_uid);
264 int passlen = SVAL(inbuf,smb_vwv3);
267 START_PROFILE(SMBtconX);
269 *service = *user = *password = *devicename = 0;
271 /* we might have to close an old one */
272 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
273 close_cnum(conn,vuid);
276 if (passlen > MAX_PASS_LEN) {
277 overflow_attack(passlen);
278 return(ERROR(ERRDOS,ERRbuftoosmall));
281 memcpy(password,smb_buf(inbuf),passlen);
283 p = smb_buf(inbuf) + passlen;
284 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
287 if (strequal(password," "))
289 passlen = strlen(password);
292 q = strchr_m(path+2,'\\');
294 END_PROFILE(SMBtconX);
295 return(ERROR(ERRDOS,ERRnosuchshare));
297 fstrcpy(service,q+1);
298 q = strchr_m(service,'%');
303 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
305 DEBUG(4,("Got device type %s\n",devicename));
308 * If the vuid is valid, we should be using that....
311 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
312 pstrcpy(user,validated_username(vuid));
316 * Pass the user through the NT -> unix user mapping
320 (void)map_username(user);
323 * Do any UNIX username case mangling.
325 (void)Get_Pwnam(user, True);
329 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
332 END_PROFILE(SMBtconX);
333 return(connection_error(inbuf,outbuf,ecode));
336 if (Protocol < PROTOCOL_NT1) {
337 set_message(outbuf,2,0,True);
339 p += srvstr_push(outbuf, p, devicename, -1,
340 STR_TERMINATE|STR_ASCII);
341 set_message_end(outbuf,p);
343 /* NT sets the fstype of IPC$ to the null string */
344 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
346 set_message(outbuf,3,0,True);
349 p += srvstr_push(outbuf, p, devicename, -1,
350 STR_TERMINATE|STR_ASCII);
351 p += srvstr_push(outbuf, p, fsname, -1,
354 set_message_end(outbuf,p);
356 /* what does setting this bit do? It is set by NT4 and
357 may affect the ability to autorun mounted cdroms */
358 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
360 init_dfsroot(conn, inbuf, outbuf);
364 DEBUG(3,("tconX service=%s user=%s\n",
367 /* set the incoming and outgoing tid to the just created one */
368 SSVAL(inbuf,smb_tid,conn->cnum);
369 SSVAL(outbuf,smb_tid,conn->cnum);
371 END_PROFILE(SMBtconX);
372 return chain_reply(inbuf,outbuf,length,bufsize);
376 /****************************************************************************
377 reply to an unknown type
378 ****************************************************************************/
379 int reply_unknown(char *inbuf,char *outbuf)
382 type = CVAL(inbuf,smb_com);
384 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
385 smb_fn_name(type), type, type));
387 return(ERROR(ERRSRV,ERRunknownsmb));
391 /****************************************************************************
393 ****************************************************************************/
394 int reply_ioctl(connection_struct *conn,
395 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
397 uint16 device = SVAL(inbuf,smb_vwv1);
398 uint16 function = SVAL(inbuf,smb_vwv2);
399 uint32 ioctl_code = (device << 16) + function;
400 int replysize, outsize;
402 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
403 START_PROFILE(SMBioctl);
405 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
409 case IOCTL_QUERY_JOB_INFO:
413 END_PROFILE(SMBioctl);
414 return(ERROR(ERRSRV,ERRnosupport));
417 outsize = set_message(outbuf,8,replysize+1,True);
418 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
419 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
420 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
421 p = smb_buf(outbuf) + 1; /* Allow for alignment */
425 case IOCTL_QUERY_JOB_INFO:
426 SSVAL(p,0,fsp->print_jobid); /* Job number */
427 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
428 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
432 END_PROFILE(SMBioctl);
436 /****************************************************************************
437 always return an error: it's just a matter of which one...
438 ****************************************************************************/
439 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
440 char *smb_passwd, int smb_passlen,
441 char *smb_nt_passwd, int smb_nt_passlen)
443 /* check if trust account exists */
444 SAM_ACCOUNT *sam_trust_acct = NULL;
448 pdb_init_sam(&sam_trust_acct);
450 if (lp_security() == SEC_USER) {
451 ret = pdb_getsampwnam(sam_trust_acct, user);
453 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
454 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
455 pdb_free_sam(sam_trust_acct);
456 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
460 /* lkclXXXX: workstation entry doesn't exist */
461 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
462 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
463 pdb_free_sam(sam_trust_acct);
464 return(ERROR(0, NT_STATUS_NO_SUCH_USER));
466 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
467 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
468 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
469 pdb_free_sam(sam_trust_acct);
470 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
473 if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) {
474 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
475 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
476 pdb_free_sam(sam_trust_acct);
477 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
480 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
481 pdb_free_sam(sam_trust_acct);
482 if (acct_ctrl & ACB_DOMTRUST) {
483 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
484 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
485 return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
488 if (acct_ctrl & ACB_SVRTRUST) {
489 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
490 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
491 return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
494 if (acct_ctrl & ACB_WSTRUST) {
495 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
496 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
497 return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
501 /* don't know what to do: indicate logon failure */
502 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
503 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
506 /****************************************************************************
507 Create a UNIX user on demand.
508 ****************************************************************************/
510 int smb_create_user(char *unix_user, char *homedir)
515 pstrcpy(add_script, lp_adduser_script());
516 if (! *add_script) return -1;
517 all_string_sub(add_script, "%u", unix_user, sizeof(pstring));
519 all_string_sub(add_script, "%H", homedir, sizeof(pstring));
520 ret = smbrun(add_script,NULL);
521 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
525 /****************************************************************************
526 Delete a UNIX user on demand.
527 ****************************************************************************/
529 static int smb_delete_user(char *unix_user)
534 pstrcpy(del_script, lp_deluser_script());
535 if (! *del_script) return -1;
536 all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
537 ret = smbrun(del_script,NULL);
538 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
542 /****************************************************************************
543 Check user is in correct domain if required
544 ****************************************************************************/
546 static BOOL check_domain_match(char *user, char *domain)
549 * If we aren't serving to trusted domains, we must make sure that
550 * the validation request comes from an account in the same domain
551 * as the Samba server
554 if (!lp_allow_trusted_domains() &&
555 !strequal(lp_workgroup(), domain) ) {
556 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
563 /****************************************************************************
564 Check for a valid username and password in security=server mode.
565 ****************************************************************************/
567 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
568 char *smb_apasswd, int smb_apasslen,
569 char *smb_ntpasswd, int smb_ntpasslen)
573 if(lp_security() != SEC_SERVER)
576 if (!check_domain_match(orig_user, domain))
579 ret = server_validate(orig_user, domain,
580 smb_apasswd, smb_apasslen,
581 smb_ntpasswd, smb_ntpasslen);
583 struct passwd *pwd=NULL;
586 * User validated ok against Domain controller.
587 * If the admin wants us to try and create a UNIX
588 * user on the fly, do so.
589 * Note that we can never delete users when in server
590 * level security as we never know if it was a failure
591 * due to a bad password, or the user really doesn't exist.
593 if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
594 smb_create_user(unix_user, NULL);
597 if(lp_adduser_script() && pwd) {
601 * Also call smb_create_user if the users home directory
602 * doesn't exist. Used with winbindd to allow the script to
603 * create the home directory for a user mapped with winbindd.
606 if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
607 smb_create_user(unix_user, pwd->pw_dir);
614 /****************************************************************************
615 Check for a valid username and password in security=domain mode.
616 ****************************************************************************/
618 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
619 char *smb_apasswd, int smb_apasslen,
620 char *smb_ntpasswd, int smb_ntpasslen)
623 BOOL user_exists = True;
624 struct passwd *pwd=NULL;
626 if(lp_security() != SEC_DOMAIN)
629 if (!check_domain_match(orig_user, domain))
632 ret = domain_client_validate(orig_user, domain,
633 smb_apasswd, smb_apasslen,
634 smb_ntpasswd, smb_ntpasslen,
639 * User validated ok against Domain controller.
640 * If the admin wants us to try and create a UNIX
641 * user on the fly, do so.
643 if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True)))
644 smb_create_user(unix_user, NULL);
646 if(lp_adduser_script() && pwd) {
650 * Also call smb_create_user if the users home directory
651 * doesn't exist. Used with winbindd to allow the script to
652 * create the home directory for a user mapped with winbindd.
655 if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
656 smb_create_user(unix_user, pwd->pw_dir);
661 * User failed to validate ok against Domain controller.
662 * If the failure was "user doesn't exist" and admin
663 * wants us to try and delete that UNIX user on the fly,
666 if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True))
667 smb_delete_user(unix_user);
673 /****************************************************************************
674 Return a bad password error configured for the correct client type.
675 ****************************************************************************/
677 static int bad_password_error(char *inbuf,char *outbuf)
679 enum remote_arch_types ra_type = get_remote_arch();
681 if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
682 (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
683 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
684 return(ERROR(0,NT_STATUS_LOGON_FAILURE));
687 return(ERROR(ERRSRV,ERRbadpw));
690 /****************************************************************************
691 reply to a session setup command
692 ****************************************************************************/
694 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
700 int smb_apasslen = 0;
702 int smb_ntpasslen = 0;
703 pstring smb_ntpasswd;
704 BOOL valid_nt_password = False;
705 BOOL valid_lm_password = False;
710 fstring native_lanman;
712 static BOOL done_sesssetup = False;
713 BOOL doencrypt = SMBENCRYPT();
714 START_PROFILE(SMBsesssetupX);
719 smb_bufsize = SVAL(inbuf,smb_vwv2);
721 if (Protocol < PROTOCOL_NT1) {
722 smb_apasslen = SVAL(inbuf,smb_vwv7);
723 if (smb_apasslen > MAX_PASS_LEN) {
724 overflow_attack(smb_apasslen);
725 return(ERROR(ERRDOS,ERRbuftoosmall));
728 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
729 srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE);
731 if (!doencrypt && (lp_security() != SEC_SERVER)) {
732 smb_apasslen = strlen(smb_apasswd);
735 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
736 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
737 enum remote_arch_types ra_type = get_remote_arch();
738 char *p = smb_buf(inbuf);
740 if(global_client_caps == 0)
741 global_client_caps = IVAL(inbuf,smb_vwv11);
743 /* client_caps is used as final determination if client is NT or Win95.
744 This is needed to return the correct error codes in some
748 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
749 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
750 set_remote_arch( RA_WIN95);
754 if (passlen1 != 24 && passlen2 != 24)
757 if (passlen1 > MAX_PASS_LEN) {
758 overflow_attack(passlen1);
759 return(ERROR(ERRDOS,ERRbuftoosmall));
762 passlen1 = MIN(passlen1, MAX_PASS_LEN);
763 passlen2 = MIN(passlen2, MAX_PASS_LEN);
766 /* both Win95 and WinNT stuff up the password lengths for
767 non-encrypting systems. Uggh.
769 if passlen1==24 its a win95 system, and its setting the
770 password length incorrectly. Luckily it still works with the
771 default code because Win95 will null terminate the password
774 if passlen1>0 and passlen2>0 then maybe its a NT box and its
775 setting passlen2 to some random value which really stuffs
776 things up. we need to fix that one. */
778 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
782 if (lp_restrict_anonymous()) {
783 /* there seems to be no reason behind the differences in MS clients formatting
784 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
785 * in particular seems to have an extra null byte between the username and the
786 * domain, or the password length calculation is wrong, which throws off the
787 * string extraction routines below. This makes the value of domain be the
788 * empty string, which fails the restrict anonymous check further down.
789 * This compensates for that, and allows browsing to work in mixed NT and
790 * win95 environments even when restrict anonymous is true. AAB
792 dump_data(100, p, 0x70);
793 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
794 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
795 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
796 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
797 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
802 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
803 /* Save the lanman2 password and the NT md4 password. */
804 smb_apasslen = passlen1;
805 memcpy(smb_apasswd,p,smb_apasslen);
806 smb_apasswd[smb_apasslen] = 0;
807 smb_ntpasslen = passlen2;
808 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
809 smb_ntpasswd[smb_ntpasslen] = 0;
811 /* we use the first password that they gave */
812 smb_apasslen = passlen1;
813 StrnCpy(smb_apasswd,p,smb_apasslen);
815 /* trim the password */
816 smb_apasslen = strlen(smb_apasswd);
818 /* wfwg sometimes uses a space instead of a null */
819 if (strequal(smb_apasswd," ")) {
825 p += passlen1 + passlen2;
826 p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
829 * Incoming user and domain are in DOS codepage format. Convert
832 p += srvstr_pull(inbuf, domain, p, sizeof(domain),
834 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
836 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
838 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
839 domain,native_os,native_lanman));
842 /* don't allow for weird usernames or domains */
843 alpha_strcpy(user, user, ". _-$", sizeof(user));
844 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
845 if (strstr(user, "..") || strstr(domain,"..")) {
846 return bad_password_error(inbuf, outbuf);
849 DEBUG(3,("sesssetupX:name=[%s]\n",user));
851 /* If name ends in $ then I think it's asking about whether a */
852 /* computer with that name (minus the $) has access. For now */
853 /* say yes to everything ending in $. */
855 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
856 END_PROFILE(SMBsesssetupX);
857 return session_trust_account(conn, inbuf, outbuf, user,
858 smb_apasswd, smb_apasslen,
859 smb_ntpasswd, smb_ntpasslen);
862 if (done_sesssetup && lp_restrict_anonymous()) {
863 /* tests show that even if browsing is done over already validated connections
864 * without a username and password the domain is still provided, which it
865 * wouldn't be if it was a purely anonymous connection. So, in order to
866 * restrict anonymous, we only deny connections that have no session
867 * information. If a domain has been provided, then it's not a purely
868 * anonymous connection. AAB
870 if (!*user && !*smb_apasswd && !*domain) {
871 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
872 END_PROFILE(SMBsesssetupX);
873 return(ERROR(ERRDOS,ERRnoaccess));
877 /* If no username is sent use the guest account */
879 pstrcpy(user,lp_guestaccount(-1));
883 pstrcpy(current_user_info.smb_name,user);
885 reload_services(True);
888 * Save the username before mapping. We will use
889 * the original username sent to us for security=server
890 * and security=domain checking.
893 pstrcpy( orig_user, user);
896 * Always try the "DOMAIN\user" lookup first, as this is the most
897 * specific case. If this fails then try the simple "user" lookup.
898 * But don't do this for guests, as this is always a local user.
904 /* Work out who's who */
906 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
907 domain, lp_winbind_separator(), user);
909 if (sys_getpwnam(dom_user) != NULL) {
910 pstrcpy(user, dom_user);
911 DEBUG(3,("Using unix username %s\n", dom_user));
915 * Pass the user through the NT -> unix user mapping
919 (void)map_username(user);
922 * Do any UNIX username case mangling.
924 smb_getpwnam(user, True);
927 add_session_user(user);
930 * Check with orig_user for security=server and
934 if (!guest && !check_server_security(orig_user, domain, user,
935 smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
936 !check_domain_security(orig_user, domain, user, smb_apasswd,
937 smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
938 !check_hosts_equiv(user))
941 * If we get here then the user wasn't guest and the remote
942 * authentication methods failed. Check the authentication
943 * methods on this local server.
945 * If an NT password was supplied try and validate with that
946 * first. This is superior as the passwords are mixed case
947 * 128 length unicode.
952 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen))
953 DEBUG(2,("NT Password did not match for user '%s'!\n", user));
955 valid_nt_password = True;
959 /* check the LanMan password only if necessary and if allowed
960 by lp_lanman_auth() */
961 if (!valid_nt_password && lp_lanman_auth())
963 DEBUG(2,("Defaulting to Lanman password for %s\n", user));
964 valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen);
968 /* The true branch will be executed if
969 (1) the NT password failed (or was not tried), and
970 (2) LanMan authentication failed (or was disabled)
972 if (!valid_nt_password && !valid_lm_password)
974 if (lp_security() >= SEC_USER)
976 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
978 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
979 END_PROFILE(SMBsesssetupX);
980 return bad_password_error(inbuf,outbuf);
983 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
985 if (smb_getpwnam(user,True))
987 DEBUG(1,("Rejecting user '%s': bad password\n", user));
988 END_PROFILE(SMBsesssetupX);
989 return bad_password_error(inbuf,outbuf);
994 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
995 * Then always map to guest account - as done below.
999 if (*smb_apasswd || !smb_getpwnam(user,True))
1000 pstrcpy(user,lp_guestaccount(-1));
1001 DEBUG(3,("Registered username %s for guest access\n",user));
1006 if (!smb_getpwnam(user,True)) {
1007 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
1008 pstrcpy(user,lp_guestaccount(-1));
1012 if (!strequal(user,lp_guestaccount(-1)) &&
1013 lp_servicenumber(user) < 0)
1015 add_home_service(user,get_user_home_dir(user));
1019 /* it's ok - setup a reply */
1020 if (Protocol < PROTOCOL_NT1) {
1021 set_message(outbuf,3,0,True);
1024 set_message(outbuf,3,0,True);
1025 p = smb_buf(outbuf);
1026 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
1027 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
1028 p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE);
1029 set_message_end(outbuf,p);
1030 /* perhaps grab OS version here?? */
1033 /* Set the correct uid in the outgoing and incoming packets
1034 We will use this on future requests to determine which
1035 user we should become.
1038 const struct passwd *pw = smb_getpwnam(user,False);
1040 DEBUG(1,("Username %s is invalid on this system\n",user));
1041 END_PROFILE(SMBsesssetupX);
1042 return bad_password_error(inbuf,outbuf);
1049 SSVAL(outbuf,smb_vwv2,1);
1051 /* register the name and uid as being validated, so further connections
1052 to a uid can get through without a password, on the same VC */
1054 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest);
1056 if (sess_vuid == -1) {
1057 return(ERROR(ERRDOS,ERRnoaccess));
1061 SSVAL(outbuf,smb_uid,sess_vuid);
1062 SSVAL(inbuf,smb_uid,sess_vuid);
1064 if (!done_sesssetup)
1065 max_send = MIN(max_send,smb_bufsize);
1067 DEBUG(6,("Client requested max send size of %d\n", max_send));
1069 done_sesssetup = True;
1071 END_PROFILE(SMBsesssetupX);
1072 return chain_reply(inbuf,outbuf,length,bufsize);
1075 /****************************************************************************
1077 ****************************************************************************/
1078 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1084 BOOL bad_path = False;
1085 SMB_STRUCT_STAT sbuf;
1086 START_PROFILE(SMBchkpth);
1088 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1090 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1092 unix_convert(name,conn,0,&bad_path,&sbuf);
1094 mode = SVAL(inbuf,smb_vwv0);
1096 if (check_name(name,conn)) {
1097 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
1098 ok = S_ISDIR(sbuf.st_mode);
1103 /* We special case this - as when a Windows machine
1104 is parsing a path is steps through the components
1105 one at a time - if a component fails it expects
1106 ERRbadpath, not ERRbadfile.
1110 unix_ERR_class = ERRDOS;
1111 unix_ERR_code = ERRbadpath;
1115 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1116 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1117 (get_remote_arch() == RA_WINNT))
1119 unix_ERR_class = ERRDOS;
1120 unix_ERR_code = ERRbaddirectory;
1124 return(UNIXERROR(ERRDOS,ERRbadpath));
1127 outsize = set_message(outbuf,0,0,True);
1129 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1131 END_PROFILE(SMBchkpth);
1136 /****************************************************************************
1138 ****************************************************************************/
1139 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1143 SMB_STRUCT_STAT sbuf;
1148 BOOL bad_path = False;
1150 START_PROFILE(SMBgetatr);
1152 p = smb_buf(inbuf) + 1;
1153 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1155 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1157 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1158 under WfWg - weird! */
1161 mode = aHIDDEN | aDIR;
1162 if (!CAN_WRITE(conn)) mode |= aRONLY;
1169 unix_convert(fname,conn,0,&bad_path,&sbuf);
1170 if (check_name(fname,conn))
1172 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1174 mode = dos_mode(conn,fname,&sbuf);
1175 size = sbuf.st_size;
1176 mtime = sbuf.st_mtime;
1182 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1188 if((errno == ENOENT) && bad_path)
1190 unix_ERR_class = ERRDOS;
1191 unix_ERR_code = ERRbadpath;
1194 END_PROFILE(SMBgetatr);
1195 return(UNIXERROR(ERRDOS,ERRbadfile));
1198 outsize = set_message(outbuf,10,0,True);
1200 SSVAL(outbuf,smb_vwv0,mode);
1201 if(lp_dos_filetime_resolution(SNUM(conn)) )
1202 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1204 put_dos_date3(outbuf,smb_vwv1,mtime);
1205 SIVAL(outbuf,smb_vwv3,(uint32)size);
1207 if (Protocol >= PROTOCOL_NT1) {
1208 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1211 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1213 END_PROFILE(SMBgetatr);
1218 /****************************************************************************
1220 ****************************************************************************/
1221 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1228 SMB_STRUCT_STAT sbuf;
1229 BOOL bad_path = False;
1232 START_PROFILE(SMBsetatr);
1234 p = smb_buf(inbuf) + 1;
1235 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1236 unix_convert(fname,conn,0,&bad_path,&sbuf);
1238 mode = SVAL(inbuf,smb_vwv0);
1239 mtime = make_unix_date3(inbuf+smb_vwv1);
1241 if (VALID_STAT_OF_DIR(sbuf))
1243 if (check_name(fname,conn))
1244 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1246 ok = set_filetime(conn,fname,mtime);
1250 if((errno == ENOENT) && bad_path)
1252 unix_ERR_class = ERRDOS;
1253 unix_ERR_code = ERRbadpath;
1256 END_PROFILE(SMBsetatr);
1257 return(UNIXERROR(ERRDOS,ERRnoaccess));
1260 outsize = set_message(outbuf,0,0,True);
1262 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1264 END_PROFILE(SMBsetatr);
1269 /****************************************************************************
1271 ****************************************************************************/
1272 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1275 SMB_BIG_UINT dfree,dsize,bsize;
1276 START_PROFILE(SMBdskattr);
1278 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1280 outsize = set_message(outbuf,5,0,True);
1282 SSVAL(outbuf,smb_vwv0,dsize);
1283 SSVAL(outbuf,smb_vwv1,bsize/512);
1284 SSVAL(outbuf,smb_vwv2,512);
1285 SSVAL(outbuf,smb_vwv3,dfree);
1287 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1289 END_PROFILE(SMBdskattr);
1294 /****************************************************************************
1296 Can be called from SMBsearch, SMBffirst or SMBfunique.
1297 ****************************************************************************/
1298 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1309 BOOL finished = False;
1318 BOOL check_descend = False;
1319 BOOL expect_close = False;
1320 BOOL can_open = True;
1321 BOOL bad_path = False;
1322 START_PROFILE(SMBsearch);
1324 *mask = *directory = *fname = 0;
1326 /* If we were called as SMBffirst then we must expect close. */
1327 if(CVAL(inbuf,smb_com) == SMBffirst)
1328 expect_close = True;
1330 outsize = set_message(outbuf,1,3,True);
1331 maxentries = SVAL(inbuf,smb_vwv0);
1332 dirtype = SVAL(inbuf,smb_vwv1);
1333 p = smb_buf(inbuf) + 1;
1334 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1336 status_len = SVAL(p, 0);
1339 /* dirtype &= ~aDIR; */
1341 if (status_len == 0)
1343 SMB_STRUCT_STAT sbuf;
1346 pstrcpy(directory,path);
1348 unix_convert(directory,conn,0,&bad_path,&sbuf);
1351 if (!check_name(directory,conn))
1354 p = strrchr_m(dir2,'/');
1366 p = strrchr_m(directory,'/');
1372 if (strlen(directory) == 0)
1373 pstrcpy(directory,"./");
1374 memset((char *)status,'\0',21);
1375 CVAL(status,0) = dirtype;
1379 memcpy(status,p,21);
1380 dirtype = CVAL(status,0) & 0x1F;
1381 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1384 string_set(&conn->dirpath,dptr_path(dptr_num));
1385 fstrcpy(mask, dptr_wcard(dptr_num));
1390 p = smb_buf(outbuf) + 3;
1394 if (status_len == 0)
1396 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1401 if((errno == ENOENT) && bad_path)
1403 unix_ERR_class = ERRDOS;
1404 unix_ERR_code = ERRbadpath;
1406 END_PROFILE(SMBsearch);
1407 return (UNIXERROR(ERRDOS,ERRnofids));
1409 END_PROFILE(SMBsearch);
1410 return(ERROR(ERRDOS,ERRnofids));
1412 dptr_set_wcard(dptr_num, strdup(mask));
1415 DEBUG(4,("dptr_num is %d\n",dptr_num));
1419 if ((dirtype&0x1F) == aVOLID)
1421 memcpy(p,status,21);
1422 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1423 dptr_fill(p+12,dptr_num);
1424 if (dptr_zero(p+12) && (status_len==0))
1428 p += DIR_STRUCT_SIZE;
1432 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1433 conn->dirpath,lp_dontdescend(SNUM(conn))));
1434 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1435 check_descend = True;
1437 for (i=numentries;(i<maxentries) && !finished;i++)
1440 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1443 memcpy(p,status,21);
1444 make_dir_struct(p,mask,fname,size,mode,date);
1445 dptr_fill(p+12,dptr_num);
1448 p += DIR_STRUCT_SIZE;
1457 if (numentries == 0 || !ok)
1459 CVAL(outbuf,smb_rcls) = ERRDOS;
1460 SSVAL(outbuf,smb_err,ERRnofiles);
1461 dptr_close(&dptr_num);
1464 /* If we were called as SMBffirst with smb_search_id == NULL
1465 and no entries were found then return error and close dirptr
1468 if(ok && expect_close && numentries == 0 && status_len == 0)
1470 CVAL(outbuf,smb_rcls) = ERRDOS;
1471 SSVAL(outbuf,smb_err,ERRnofiles);
1472 /* Also close the dptr - we know it's gone */
1473 dptr_close(&dptr_num);
1476 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1477 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1478 dptr_close(&dptr_num);
1480 SSVAL(outbuf,smb_vwv0,numentries);
1481 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1482 CVAL(smb_buf(outbuf),0) = 5;
1483 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1485 if (Protocol >= PROTOCOL_NT1) {
1486 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1489 outsize += DIR_STRUCT_SIZE*numentries;
1490 smb_setlen(outbuf,outsize - 4);
1492 if ((! *directory) && dptr_path(dptr_num))
1493 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1495 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1496 smb_fn_name(CVAL(inbuf,smb_com)),
1497 mask, directory, dirtype, numentries, maxentries ) );
1499 END_PROFILE(SMBsearch);
1504 /****************************************************************************
1505 reply to a fclose (stop directory search)
1506 ****************************************************************************/
1507 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1516 START_PROFILE(SMBfclose);
1518 outsize = set_message(outbuf,1,0,True);
1519 p = smb_buf(inbuf) + 1;
1520 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1522 status_len = SVAL(p,0);
1525 if (status_len == 0) {
1526 END_PROFILE(SMBfclose);
1527 return(ERROR(ERRSRV,ERRsrverror));
1530 memcpy(status,p,21);
1532 if(dptr_fetch(status+12,&dptr_num)) {
1533 /* Close the dptr - we know it's gone */
1534 dptr_close(&dptr_num);
1537 SSVAL(outbuf,smb_vwv0,0);
1539 DEBUG(3,("search close\n"));
1541 END_PROFILE(SMBfclose);
1546 /****************************************************************************
1548 ****************************************************************************/
1550 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1560 SMB_STRUCT_STAT sbuf;
1561 BOOL bad_path = False;
1563 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1564 START_PROFILE(SMBopen);
1566 share_mode = SVAL(inbuf,smb_vwv0);
1568 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1570 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1572 unix_convert(fname,conn,0,&bad_path,&sbuf);
1574 unixmode = unix_mode(conn,aARCH,fname);
1576 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1577 unixmode, oplock_request,&rmode,NULL);
1581 if((errno == ENOENT) && bad_path)
1583 unix_ERR_class = ERRDOS;
1584 unix_ERR_code = ERRbadpath;
1586 END_PROFILE(SMBopen);
1587 return(UNIXERROR(ERRDOS,ERRnoaccess));
1590 size = sbuf.st_size;
1591 fmode = dos_mode(conn,fname,&sbuf);
1592 mtime = sbuf.st_mtime;
1595 DEBUG(3,("attempt to open a directory %s\n",fname));
1596 close_file(fsp,False);
1597 END_PROFILE(SMBopen);
1598 return(ERROR(ERRDOS,ERRnoaccess));
1601 outsize = set_message(outbuf,7,0,True);
1602 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1603 SSVAL(outbuf,smb_vwv1,fmode);
1604 if(lp_dos_filetime_resolution(SNUM(conn)) )
1605 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1607 put_dos_date3(outbuf,smb_vwv2,mtime);
1608 SIVAL(outbuf,smb_vwv4,(uint32)size);
1609 SSVAL(outbuf,smb_vwv6,rmode);
1611 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1612 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1615 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1616 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1617 END_PROFILE(SMBopen);
1622 /****************************************************************************
1623 reply to an open and X
1624 ****************************************************************************/
1625 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1628 int smb_mode = SVAL(inbuf,smb_vwv3);
1629 int smb_attr = SVAL(inbuf,smb_vwv5);
1630 /* Breakout the oplock request bits so we can set the
1631 reply bits separately. */
1632 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1633 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1634 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1636 int open_flags = SVAL(inbuf,smb_vwv2);
1637 int smb_sattr = SVAL(inbuf,smb_vwv4);
1638 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1640 int smb_ofun = SVAL(inbuf,smb_vwv8);
1643 int fmode=0,mtime=0,rmode=0;
1644 SMB_STRUCT_STAT sbuf;
1646 BOOL bad_path = False;
1648 START_PROFILE(SMBopenX);
1650 /* If it's an IPC, pass off the pipe handler. */
1652 if (lp_nt_pipe_support()) {
1653 END_PROFILE(SMBopenX);
1654 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1656 END_PROFILE(SMBopenX);
1657 return (ERROR(ERRSRV,ERRaccess));
1661 /* XXXX we need to handle passed times, sattr and flags */
1662 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1664 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1666 unix_convert(fname,conn,0,&bad_path,&sbuf);
1668 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1670 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1671 oplock_request, &rmode,&smb_action);
1675 if((errno == ENOENT) && bad_path)
1677 unix_ERR_class = ERRDOS;
1678 unix_ERR_code = ERRbadpath;
1680 END_PROFILE(SMBopenX);
1681 return(UNIXERROR(ERRDOS,ERRnoaccess));
1684 size = sbuf.st_size;
1685 fmode = dos_mode(conn,fname,&sbuf);
1686 mtime = sbuf.st_mtime;
1688 close_file(fsp,False);
1689 END_PROFILE(SMBopenX);
1690 return(ERROR(ERRDOS,ERRnoaccess));
1693 /* If the caller set the extended oplock request bit
1694 and we granted one (by whatever means) - set the
1695 correct bit for extended oplock reply.
1698 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1699 smb_action |= EXTENDED_OPLOCK_GRANTED;
1702 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1703 smb_action |= EXTENDED_OPLOCK_GRANTED;
1706 /* If the caller set the core oplock request bit
1707 and we granted one (by whatever means) - set the
1708 correct bit for core oplock reply.
1711 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1712 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1715 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1716 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1719 set_message(outbuf,15,0,True);
1720 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1721 SSVAL(outbuf,smb_vwv3,fmode);
1722 if(lp_dos_filetime_resolution(SNUM(conn)) )
1723 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1725 put_dos_date3(outbuf,smb_vwv4,mtime);
1726 SIVAL(outbuf,smb_vwv6,(uint32)size);
1727 SSVAL(outbuf,smb_vwv8,rmode);
1728 SSVAL(outbuf,smb_vwv11,smb_action);
1730 END_PROFILE(SMBopenX);
1731 return chain_reply(inbuf,outbuf,length,bufsize);
1735 /****************************************************************************
1736 reply to a SMBulogoffX
1737 ****************************************************************************/
1738 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1740 uint16 vuid = SVAL(inbuf,smb_uid);
1741 user_struct *vuser = get_valid_user_struct(vuid);
1742 START_PROFILE(SMBulogoffX);
1745 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1748 /* in user level security we are supposed to close any files
1749 open by this user */
1750 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1751 file_close_user(vuid);
1754 invalidate_vuid(vuid);
1756 set_message(outbuf,2,0,True);
1758 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1760 END_PROFILE(SMBulogoffX);
1761 return chain_reply(inbuf,outbuf,length,bufsize);
1765 /****************************************************************************
1766 reply to a mknew or a create
1767 ****************************************************************************/
1768 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1776 BOOL bad_path = False;
1778 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1779 SMB_STRUCT_STAT sbuf;
1780 START_PROFILE(SMBcreate);
1782 com = SVAL(inbuf,smb_com);
1784 createmode = SVAL(inbuf,smb_vwv0);
1785 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1787 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1789 unix_convert(fname,conn,0,&bad_path,&sbuf);
1791 if (createmode & aVOLID) {
1792 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1795 unixmode = unix_mode(conn,createmode,fname);
1799 /* We should fail if file exists. */
1800 ofun = FILE_CREATE_IF_NOT_EXIST;
1804 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1805 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1808 /* Open file in dos compatibility share mode. */
1809 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1810 ofun, unixmode, oplock_request, NULL, NULL);
1814 if((errno == ENOENT) && bad_path)
1816 unix_ERR_class = ERRDOS;
1817 unix_ERR_code = ERRbadpath;
1819 END_PROFILE(SMBcreate);
1820 return(UNIXERROR(ERRDOS,ERRnoaccess));
1823 outsize = set_message(outbuf,1,0,True);
1824 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1826 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1827 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1830 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1831 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1833 DEBUG( 2, ( "new file %s\n", fname ) );
1834 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1835 fname, fsp->fd, createmode, (int)unixmode ) );
1837 END_PROFILE(SMBcreate);
1842 /****************************************************************************
1843 reply to a create temporary file
1844 ****************************************************************************/
1845 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1851 BOOL bad_path = False;
1853 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1855 SMB_STRUCT_STAT sbuf;
1858 START_PROFILE(SMBctemp);
1860 createmode = SVAL(inbuf,smb_vwv0);
1861 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1862 pstrcat(fname,"/TMXXXXXX");
1864 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1866 unix_convert(fname,conn,0,&bad_path,&sbuf);
1868 unixmode = unix_mode(conn,createmode,fname);
1870 tmpfd = smb_mkstemp(fname);
1872 END_PROFILE(SMBctemp);
1873 return(UNIXERROR(ERRDOS,ERRnoaccess));
1876 vfs_stat(conn,fname,&sbuf);
1878 /* Open file in dos compatibility share mode. */
1879 /* We should fail if file does not exist. */
1880 fsp = open_file_shared(conn,fname,&sbuf,
1881 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1882 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1883 unixmode, oplock_request, NULL, NULL);
1885 /* close fd from smb_mkstemp() */
1890 if((errno == ENOENT) && bad_path)
1892 unix_ERR_class = ERRDOS;
1893 unix_ERR_code = ERRbadpath;
1895 END_PROFILE(SMBctemp);
1896 return(UNIXERROR(ERRDOS,ERRnoaccess));
1899 outsize = set_message(outbuf,1,0,True);
1900 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1901 CVAL(smb_buf(outbuf),0) = 4;
1902 p = smb_buf(outbuf) + 1;
1903 p += srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1904 set_message_end(outbuf, p);
1906 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1907 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1910 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1911 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1913 DEBUG( 2, ( "created temp file %s\n", fname ) );
1914 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1915 fname, fsp->fd, createmode, (int)unixmode ) );
1917 END_PROFILE(SMBctemp);
1922 /*******************************************************************
1923 check if a user is allowed to delete a file
1924 ********************************************************************/
1925 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1927 SMB_STRUCT_STAT sbuf;
1930 if (!CAN_WRITE(conn)) return(False);
1932 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
1933 fmode = dos_mode(conn,fname,&sbuf);
1934 if (fmode & aDIR) return(False);
1935 if (!lp_delete_readonly(SNUM(conn))) {
1936 if (fmode & aRONLY) return(False);
1938 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1940 if (!check_file_sharing(conn,fname,False)) return(False);
1944 /****************************************************************************
1945 The guts of the unlink command, split out so it may be called by the NT SMB
1947 ****************************************************************************/
1949 int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
1950 int dirtype, char *name)
1956 int error = ERRnoaccess;
1959 BOOL bad_path = False;
1961 SMB_STRUCT_STAT sbuf;
1963 *directory = *mask = 0;
1965 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1967 p = strrchr_m(name,'/');
1969 pstrcpy(directory,"./");
1973 pstrcpy(directory,name);
1978 * We should only check the mangled cache
1979 * here if unix_convert failed. This means
1980 * that the path in 'mask' doesn't exist
1981 * on the file system and so we need to look
1982 * for a possible mangle. This patch from
1983 * Tine Smukavec <valentin.smukavec@hermes.si>.
1986 if (!rc && is_mangled(mask))
1987 check_mangled_cache( mask );
1989 has_wild = ms_has_wild(mask);
1992 pstrcat(directory,"/");
1993 pstrcat(directory,mask);
1994 if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory))
1997 exists = vfs_file_exist(conn,directory,&sbuf);
1999 void *dirptr = NULL;
2002 if (check_name(directory,conn))
2003 dirptr = OpenDir(conn, directory, True);
2005 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2006 the pattern matches against the long name, otherwise the short name
2007 We don't implement this yet XXXX
2014 if (strequal(mask,"????????.???"))
2017 while ((dname = ReadDirName(dirptr)))
2020 pstrcpy(fname,dname);
2022 if(!mask_match(fname, mask, case_sensitive)) continue;
2024 error = ERRnoaccess;
2025 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2026 if (!can_delete(fname,conn,dirtype)) continue;
2027 if (!vfs_unlink(conn,fname)) count++;
2028 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2036 return(ERROR(ERRDOS,error));
2038 if((errno == ENOENT) && bad_path) {
2039 unix_ERR_class = ERRDOS;
2040 unix_ERR_code = ERRbadpath;
2042 return(UNIXERROR(ERRDOS,error));
2049 /****************************************************************************
2051 ****************************************************************************/
2053 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2058 START_PROFILE(SMBunlink);
2060 dirtype = SVAL(inbuf,smb_vwv0);
2062 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
2064 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
2066 DEBUG(3,("reply_unlink : %s\n",name));
2068 outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
2072 * Win2k needs a changenotify request response before it will
2073 * update after a rename..
2076 process_pending_change_notify_queue((time_t)0);
2078 outsize = set_message(outbuf,0,0,True);
2081 END_PROFILE(SMBunlink);
2086 /****************************************************************************
2087 reply to a readbraw (core+ protocol)
2088 ****************************************************************************/
2090 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2092 size_t maxcount,mincount;
2095 char *header = outbuf;
2098 START_PROFILE(SMBreadbraw);
2101 * Special check if an oplock break has been issued
2102 * and the readraw request croses on the wire, we must
2103 * return a zero length response here.
2106 if(global_oplock_break)
2108 _smb_setlen(header,0);
2109 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2110 DEBUG(5,("readbraw - oplock break finished\n"));
2111 END_PROFILE(SMBreadbraw);
2115 fsp = file_fsp(inbuf,smb_vwv0);
2117 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2119 * fsp could be NULL here so use the value from the packet. JRA.
2121 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2122 _smb_setlen(header,0);
2123 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2124 END_PROFILE(SMBreadbraw);
2128 CHECK_FSP(fsp,conn);
2130 flush_write_cache(fsp, READRAW_FLUSH);
2132 startpos = IVAL(inbuf,smb_vwv1);
2133 if(CVAL(inbuf,smb_wct) == 10) {
2135 * This is a large offset (64 bit) read.
2137 #ifdef LARGE_SMB_OFF_T
2139 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2141 #else /* !LARGE_SMB_OFF_T */
2144 * Ensure we haven't been sent a >32 bit offset.
2147 if(IVAL(inbuf,smb_vwv8) != 0) {
2148 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2149 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2150 _smb_setlen(header,0);
2151 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2152 END_PROFILE(SMBreadbraw);
2156 #endif /* LARGE_SMB_OFF_T */
2159 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2160 (double)startpos ));
2161 _smb_setlen(header,0);
2162 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2163 END_PROFILE(SMBreadbraw);
2167 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2168 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2170 /* ensure we don't overrun the packet size */
2171 maxcount = MIN(65535,maxcount);
2172 maxcount = MAX(mincount,maxcount);
2174 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False))
2176 SMB_OFF_T size = fsp->size;
2177 SMB_OFF_T sizeneeded = startpos + maxcount;
2179 if (size < sizeneeded)
2182 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2184 if (!fsp->can_write)
2188 nread = MIN(maxcount,(size - startpos));
2191 if (nread < mincount)
2194 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2195 fsp->fnum, (double)startpos,
2196 (int)maxcount, (int)mincount, (int)nread ) );
2200 BOOL seek_fail = False;
2202 _smb_setlen(header,nread);
2204 if ((nread-predict) > 0) {
2205 if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
2206 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2213 ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
2214 (SMB_OFF_T)(nread-predict),header,4+predict,
2219 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2220 fsp->fsp_name,startpos,nread,ret));
2222 #else /* UNSAFE_READRAW */
2223 ret = read_file(fsp,header+4,startpos,nread);
2224 if (ret < mincount) ret = 0;
2226 _smb_setlen(header,ret);
2227 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2228 #endif /* UNSAFE_READRAW */
2230 DEBUG(5,("readbraw finished\n"));
2231 END_PROFILE(SMBreadbraw);
2236 /****************************************************************************
2237 reply to a lockread (core+ protocol)
2238 ****************************************************************************/
2239 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2248 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2249 START_PROFILE(SMBlockread);
2251 CHECK_FSP(fsp,conn);
2255 release_level_2_oplocks_on_change(fsp);
2257 numtoread = SVAL(inbuf,smb_vwv1);
2258 startpos = IVAL(inbuf,smb_vwv2);
2260 outsize = set_message(outbuf,5,3,True);
2261 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2262 data = smb_buf(outbuf) + 3;
2265 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2266 * protocol request that predates the read/write lock concept.
2267 * Thus instead of asking for a read lock here we need to ask
2268 * for a write lock. JRA.
2271 if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2272 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2274 * A blocking lock was requested. Package up
2275 * this smb into a queued request and push it
2276 * onto the blocking lock queue.
2278 if(push_blocking_lock_request(inbuf, length, -1, 0))
2279 END_PROFILE(SMBlockread);
2282 END_PROFILE(SMBlockread);
2283 return (ERROR(eclass,ecode));
2286 nread = read_file(fsp,data,startpos,numtoread);
2289 END_PROFILE(SMBlockread);
2290 return(UNIXERROR(ERRDOS,ERRnoaccess));
2294 SSVAL(outbuf,smb_vwv0,nread);
2295 SSVAL(outbuf,smb_vwv5,nread+3);
2296 SSVAL(smb_buf(outbuf),1,nread);
2298 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2299 fsp->fnum, (int)numtoread, (int)nread ) );
2301 END_PROFILE(SMBlockread);
2306 /****************************************************************************
2308 ****************************************************************************/
2310 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2317 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2318 START_PROFILE(SMBread);
2320 CHECK_FSP(fsp,conn);
2324 numtoread = SVAL(inbuf,smb_vwv1);
2325 startpos = IVAL(inbuf,smb_vwv2);
2327 outsize = set_message(outbuf,5,3,True);
2328 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2329 data = smb_buf(outbuf) + 3;
2331 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2332 END_PROFILE(SMBread);
2333 return(ERROR(ERRDOS,ERRlock));
2337 nread = read_file(fsp,data,startpos,numtoread);
2340 END_PROFILE(SMBread);
2341 return(UNIXERROR(ERRDOS,ERRnoaccess));
2345 SSVAL(outbuf,smb_vwv0,nread);
2346 SSVAL(outbuf,smb_vwv5,nread+3);
2347 CVAL(smb_buf(outbuf),0) = 1;
2348 SSVAL(smb_buf(outbuf),1,nread);
2350 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2351 fsp->fnum, (int)numtoread, (int)nread ) );
2353 END_PROFILE(SMBread);
2358 /****************************************************************************
2359 reply to a read and X
2360 ****************************************************************************/
2361 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2363 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2364 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2365 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2366 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2369 START_PROFILE(SMBreadX);
2371 /* If it's an IPC, pass off the pipe handler. */
2373 END_PROFILE(SMBreadX);
2374 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2377 CHECK_FSP(fsp,conn);
2381 set_message(outbuf,12,0,True);
2382 data = smb_buf(outbuf);
2384 if(CVAL(inbuf,smb_wct) == 12) {
2385 #ifdef LARGE_SMB_OFF_T
2387 * This is a large offset (64 bit) read.
2389 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2391 #else /* !LARGE_SMB_OFF_T */
2394 * Ensure we haven't been sent a >32 bit offset.
2397 if(IVAL(inbuf,smb_vwv10) != 0) {
2398 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2399 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2400 END_PROFILE(SMBreadX);
2401 return(ERROR(ERRDOS,ERRbadaccess));
2404 #endif /* LARGE_SMB_OFF_T */
2408 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2409 END_PROFILE(SMBreadX);
2410 return(ERROR(ERRDOS,ERRlock));
2412 nread = read_file(fsp,data,startpos,smb_maxcnt);
2415 END_PROFILE(SMBreadX);
2416 return(UNIXERROR(ERRDOS,ERRnoaccess));
2419 SSVAL(outbuf,smb_vwv5,nread);
2420 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2421 SSVAL(smb_buf(outbuf),-2,nread);
2423 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2424 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2426 END_PROFILE(SMBreadX);
2427 return chain_reply(inbuf,outbuf,length,bufsize);
2430 /****************************************************************************
2431 reply to a writebraw (core+ or LANMAN1.0 protocol)
2432 ****************************************************************************/
2434 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2437 ssize_t total_written=0;
2438 size_t numtowrite=0;
2443 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2445 START_PROFILE(SMBwritebraw);
2447 CHECK_FSP(fsp,conn);
2451 tcount = IVAL(inbuf,smb_vwv1);
2452 startpos = IVAL(inbuf,smb_vwv3);
2453 write_through = BITSETW(inbuf+smb_vwv7,0);
2455 /* We have to deal with slightly different formats depending
2456 on whether we are using the core+ or lanman1.0 protocol */
2457 if(Protocol <= PROTOCOL_COREPLUS) {
2458 numtowrite = SVAL(smb_buf(inbuf),-2);
2459 data = smb_buf(inbuf);
2461 numtowrite = SVAL(inbuf,smb_vwv10);
2462 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2465 /* force the error type */
2466 CVAL(inbuf,smb_com) = SMBwritec;
2467 CVAL(outbuf,smb_com) = SMBwritec;
2469 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2470 END_PROFILE(SMBwritebraw);
2471 return(ERROR(ERRDOS,ERRlock));
2475 nwritten = write_file(fsp,data,startpos,numtowrite);
2477 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2478 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2480 if (nwritten < numtowrite) {
2481 END_PROFILE(SMBwritebraw);
2482 return(UNIXERROR(ERRHRD,ERRdiskfull));
2485 total_written = nwritten;
2487 /* Return a message to the redirector to tell it
2488 to send more bytes */
2489 CVAL(outbuf,smb_com) = SMBwritebraw;
2490 SSVALS(outbuf,smb_vwv0,-1);
2491 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2492 if (!send_smb(smbd_server_fd(),outbuf))
2493 exit_server("reply_writebraw: send_smb failed.\n");
2495 /* Now read the raw data into the buffer and write it */
2496 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2497 exit_server("secondary writebraw failed");
2500 /* Even though this is not an smb message, smb_len
2501 returns the generic length of an smb message */
2502 numtowrite = smb_len(inbuf);
2504 if (tcount > nwritten+numtowrite) {
2505 DEBUG(3,("Client overestimated the write %d %d %d\n",
2506 (int)tcount,(int)nwritten,(int)numtowrite));
2509 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2510 (SMB_OFF_T)numtowrite,NULL,0,
2512 total_written += nwritten;
2514 /* Set up outbuf to return the correct return */
2515 outsize = set_message(outbuf,1,0,True);
2516 CVAL(outbuf,smb_com) = SMBwritec;
2517 SSVAL(outbuf,smb_vwv0,total_written);
2519 if (nwritten < (ssize_t)numtowrite) {
2520 CVAL(outbuf,smb_rcls) = ERRHRD;
2521 SSVAL(outbuf,smb_err,ERRdiskfull);
2524 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2525 lp_strict_sync(SNUM(conn)))
2526 sync_file(conn,fsp);
2528 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2529 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2531 /* we won't return a status if write through is not selected - this
2532 follows what WfWg does */
2533 END_PROFILE(SMBwritebraw);
2534 if (!write_through && total_written==tcount) {
2536 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2537 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2539 if (!send_keepalive(smbd_server_fd()))
2540 exit_server("reply_writebraw: send of keepalive failed");
2547 /****************************************************************************
2548 reply to a writeunlock (core+)
2549 ****************************************************************************/
2551 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2553 ssize_t nwritten = -1;
2559 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2561 START_PROFILE(SMBwriteunlock);
2563 CHECK_FSP(fsp,conn);
2567 numtowrite = SVAL(inbuf,smb_vwv1);
2568 startpos = IVAL(inbuf,smb_vwv2);
2569 data = smb_buf(inbuf) + 3;
2571 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2572 END_PROFILE(SMBwriteunlock);
2573 return(ERROR(ERRDOS,ERRlock));
2576 /* The special X/Open SMB protocol handling of
2577 zero length writes is *NOT* done for
2582 nwritten = write_file(fsp,data,startpos,numtowrite);
2584 if (lp_syncalways(SNUM(conn)))
2585 sync_file(conn,fsp);
2587 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2588 END_PROFILE(SMBwriteunlock);
2589 return(UNIXERROR(ERRDOS,ERRnoaccess));
2592 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) {
2593 END_PROFILE(SMBwriteunlock);
2594 return(ERROR(eclass,ecode));
2597 outsize = set_message(outbuf,1,0,True);
2599 SSVAL(outbuf,smb_vwv0,nwritten);
2601 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2602 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2604 END_PROFILE(SMBwriteunlock);
2608 /****************************************************************************
2610 ****************************************************************************/
2611 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2614 ssize_t nwritten = -1;
2617 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2619 START_PROFILE(SMBwrite);
2621 /* If it's an IPC, pass off the pipe handler. */
2623 END_PROFILE(SMBwrite);
2624 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2627 CHECK_FSP(fsp,conn);
2631 numtowrite = SVAL(inbuf,smb_vwv1);
2632 startpos = IVAL(inbuf,smb_vwv2);
2633 data = smb_buf(inbuf) + 3;
2635 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2636 END_PROFILE(SMBwrite);
2637 return(ERROR(ERRDOS,ERRlock));
2640 /* X/Open SMB protocol says that if smb_vwv1 is
2641 zero then the file size should be extended or
2642 truncated to the size given in smb_vwv[2-3] */
2643 if(numtowrite == 0) {
2644 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2646 nwritten = write_file(fsp,data,startpos,numtowrite);
2648 if (lp_syncalways(SNUM(conn)))
2649 sync_file(conn,fsp);
2651 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2652 END_PROFILE(SMBwrite);
2653 return(UNIXERROR(ERRDOS,ERRnoaccess));
2656 outsize = set_message(outbuf,1,0,True);
2658 SSVAL(outbuf,smb_vwv0,nwritten);
2660 if (nwritten < (ssize_t)numtowrite) {
2661 CVAL(outbuf,smb_rcls) = ERRHRD;
2662 SSVAL(outbuf,smb_err,ERRdiskfull);
2665 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2666 fsp->fnum, (int)numtowrite, (int)nwritten));
2668 END_PROFILE(SMBwrite);
2673 /****************************************************************************
2674 reply to a write and X
2675 ****************************************************************************/
2676 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2678 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2679 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2680 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2681 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2682 ssize_t nwritten = -1;
2683 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2684 unsigned int smblen = smb_len(inbuf);
2686 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2687 START_PROFILE(SMBwriteX);
2689 /* If it's an IPC, pass off the pipe handler. */
2691 END_PROFILE(SMBwriteX);
2692 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2695 CHECK_FSP(fsp,conn);
2699 /* Deal with possible LARGE_WRITEX */
2701 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2703 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2704 END_PROFILE(SMBwriteX);
2705 return(ERROR(ERRDOS,ERRbadmem));
2708 data = smb_base(inbuf) + smb_doff;
2710 if(CVAL(inbuf,smb_wct) == 14) {
2711 #ifdef LARGE_SMB_OFF_T
2713 * This is a large offset (64 bit) write.
2715 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2717 #else /* !LARGE_SMB_OFF_T */
2720 * Ensure we haven't been sent a >32 bit offset.
2723 if(IVAL(inbuf,smb_vwv12) != 0) {
2724 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2725 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2726 END_PROFILE(SMBwriteX);
2727 return(ERROR(ERRDOS,ERRbadaccess));
2730 #endif /* LARGE_SMB_OFF_T */
2733 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2734 END_PROFILE(SMBwriteX);
2735 return(ERROR(ERRDOS,ERRlock));
2738 /* X/Open SMB protocol says that, unlike SMBwrite
2739 if the length is zero then NO truncation is
2740 done, just a write of zero. To truncate a file,
2745 nwritten = write_file(fsp,data,startpos,numtowrite);
2747 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2748 END_PROFILE(SMBwriteX);
2749 return(UNIXERROR(ERRDOS,ERRnoaccess));
2752 set_message(outbuf,6,0,True);
2754 SSVAL(outbuf,smb_vwv2,nwritten);
2756 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2758 if (nwritten < (ssize_t)numtowrite) {
2759 CVAL(outbuf,smb_rcls) = ERRHRD;
2760 SSVAL(outbuf,smb_err,ERRdiskfull);
2763 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2764 fsp->fnum, (int)numtowrite, (int)nwritten));
2766 if (lp_syncalways(SNUM(conn)) || write_through)
2767 sync_file(conn,fsp);
2769 END_PROFILE(SMBwriteX);
2770 return chain_reply(inbuf,outbuf,length,bufsize);
2774 /****************************************************************************
2776 ****************************************************************************/
2778 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2784 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2785 START_PROFILE(SMBlseek);
2787 CHECK_FSP(fsp,conn);
2790 flush_write_cache(fsp, SEEK_FLUSH);
2792 mode = SVAL(inbuf,smb_vwv1) & 3;
2793 startpos = IVALS(inbuf,smb_vwv2);
2796 case 0: umode = SEEK_SET; break;
2797 case 1: umode = SEEK_CUR; break;
2798 case 2: umode = SEEK_END; break;
2800 umode = SEEK_SET; break;
2803 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2805 * Check for the special case where a seek before the start
2806 * of the file sets the offset to zero. Added in the CIFS spec,
2810 if(errno == EINVAL) {
2811 SMB_OFF_T current_pos = startpos;
2813 if(umode == SEEK_CUR) {
2815 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2816 END_PROFILE(SMBlseek);
2817 return(UNIXERROR(ERRDOS,ERRnoaccess));
2820 current_pos += startpos;
2822 } else if (umode == SEEK_END) {
2824 SMB_STRUCT_STAT sbuf;
2826 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2827 END_PROFILE(SMBlseek);
2828 return(UNIXERROR(ERRDOS,ERRnoaccess));
2831 current_pos += sbuf.st_size;
2835 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2839 END_PROFILE(SMBlseek);
2840 return(UNIXERROR(ERRDOS,ERRnoaccess));
2846 outsize = set_message(outbuf,2,0,True);
2847 SIVAL(outbuf,smb_vwv0,res);
2849 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2850 fsp->fnum, (double)startpos, (double)res, mode));
2852 END_PROFILE(SMBlseek);
2856 /****************************************************************************
2858 ****************************************************************************/
2860 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2862 int outsize = set_message(outbuf,0,0,True);
2863 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2864 START_PROFILE(SMBflush);
2867 CHECK_FSP(fsp,conn);
2872 file_sync_all(conn);
2874 sync_file(conn,fsp);
2877 DEBUG(3,("flush\n"));
2878 END_PROFILE(SMBflush);
2883 /****************************************************************************
2885 ****************************************************************************/
2886 int reply_exit(connection_struct *conn,
2887 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2890 START_PROFILE(SMBexit);
2891 outsize = set_message(outbuf,0,0,True);
2893 DEBUG(3,("exit\n"));
2895 END_PROFILE(SMBexit);
2900 /****************************************************************************
2901 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2902 ****************************************************************************/
2903 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2908 int32 eclass = 0, err = 0;
2909 files_struct *fsp = NULL;
2910 START_PROFILE(SMBclose);
2912 outsize = set_message(outbuf,0,0,True);
2914 /* If it's an IPC, pass off to the pipe handler. */
2916 END_PROFILE(SMBclose);
2917 return reply_pipe_close(conn, inbuf,outbuf);
2920 fsp = file_fsp(inbuf,smb_vwv0);
2923 * We can only use CHECK_FSP if we know it's not a directory.
2926 if(!fsp || (fsp->conn != conn)) {
2927 END_PROFILE(SMBclose);
2928 return(ERROR(ERRDOS,ERRbadfid));
2931 if(HAS_CACHED_ERROR(fsp)) {
2932 eclass = fsp->wbmpx_ptr->wr_errclass;
2933 err = fsp->wbmpx_ptr->wr_error;
2936 if(fsp->is_directory || fsp->stat_open) {
2938 * Special case - close NT SMB directory or stat file
2941 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2942 close_file(fsp,True);
2945 * Close ordinary file.
2950 * If there was a modify time outstanding,
2951 * try and set it here.
2953 if(fsp->pending_modtime)
2954 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2957 * Now take care of any time sent in the close.
2959 mtime = make_unix_date3(inbuf+smb_vwv1);
2961 /* try and set the date */
2962 set_filetime(conn, fsp->fsp_name,mtime);
2964 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2966 conn->num_files_open));
2969 * close_file() returns the unix errno if an error
2970 * was detected on close - normally this is due to
2971 * a disk full error. If not then it was probably an I/O error.
2974 if((close_err = close_file(fsp,True)) != 0) {
2976 END_PROFILE(SMBclose);
2977 return (UNIXERROR(ERRHRD,ERRgeneral));
2981 /* We have a cached error */
2983 END_PROFILE(SMBclose);
2984 return(ERROR(eclass,err));
2987 END_PROFILE(SMBclose);
2992 /****************************************************************************
2993 reply to a writeclose (Core+ protocol)
2994 ****************************************************************************/
2996 int reply_writeclose(connection_struct *conn,
2997 char *inbuf,char *outbuf, int size, int dum_buffsize)
3000 ssize_t nwritten = -1;
3006 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3007 START_PROFILE(SMBwriteclose);
3009 CHECK_FSP(fsp,conn);
3013 numtowrite = SVAL(inbuf,smb_vwv1);
3014 startpos = IVAL(inbuf,smb_vwv2);
3015 mtime = make_unix_date3(inbuf+smb_vwv4);
3016 data = smb_buf(inbuf) + 1;
3018 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
3019 END_PROFILE(SMBwriteclose);
3020 return(ERROR(ERRDOS,ERRlock));
3023 nwritten = write_file(fsp,data,startpos,numtowrite);
3025 set_filetime(conn, fsp->fsp_name,mtime);
3027 close_err = close_file(fsp,True);
3029 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3030 fsp->fnum, (int)numtowrite, (int)nwritten,
3031 conn->num_files_open));
3033 if (nwritten <= 0) {
3034 END_PROFILE(SMBwriteclose);
3035 return(UNIXERROR(ERRDOS,ERRnoaccess));
3038 if(close_err != 0) {
3040 END_PROFILE(SMBwriteclose);
3041 return(UNIXERROR(ERRHRD,ERRgeneral));
3044 outsize = set_message(outbuf,1,0,True);
3046 SSVAL(outbuf,smb_vwv0,nwritten);
3047 END_PROFILE(SMBwriteclose);
3052 /****************************************************************************
3054 ****************************************************************************/
3055 int reply_lock(connection_struct *conn,
3056 char *inbuf,char *outbuf, int length, int dum_buffsize)
3058 int outsize = set_message(outbuf,0,0,True);
3059 SMB_BIG_UINT count,offset;
3062 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3063 START_PROFILE(SMBlock);
3065 CHECK_FSP(fsp,conn);
3068 release_level_2_oplocks_on_change(fsp);
3070 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3071 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3073 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3074 fsp->fd, fsp->fnum, (double)offset, (double)count));
3076 if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &eclass, &ecode)) {
3077 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
3079 * A blocking lock was requested. Package up
3080 * this smb into a queued request and push it
3081 * onto the blocking lock queue.
3083 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
3084 END_PROFILE(SMBlock);
3088 END_PROFILE(SMBlock);
3089 return (ERROR(eclass,ecode));
3092 END_PROFILE(SMBlock);
3097 /****************************************************************************
3099 ****************************************************************************/
3100 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3102 int outsize = set_message(outbuf,0,0,True);
3103 SMB_BIG_UINT count,offset;
3106 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3107 START_PROFILE(SMBunlock);
3109 CHECK_FSP(fsp,conn);
3112 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3113 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3115 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, &eclass, &ecode)) {
3116 END_PROFILE(SMBunlock);
3117 return (ERROR(eclass,ecode));
3120 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3121 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3123 END_PROFILE(SMBunlock);
3128 /****************************************************************************
3130 ****************************************************************************/
3131 int reply_tdis(connection_struct *conn,
3132 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3134 int outsize = set_message(outbuf,0,0,True);
3136 START_PROFILE(SMBtdis);
3138 vuid = SVAL(inbuf,smb_uid);
3141 DEBUG(4,("Invalid connection in tdis\n"));
3142 END_PROFILE(SMBtdis);
3143 return(ERROR(ERRSRV,ERRinvnid));
3148 close_cnum(conn,vuid);
3150 END_PROFILE(SMBtdis);
3156 /****************************************************************************
3158 ****************************************************************************/
3159 int reply_echo(connection_struct *conn,
3160 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3162 int smb_reverb = SVAL(inbuf,smb_vwv0);
3164 unsigned int data_len = smb_buflen(inbuf);
3165 int outsize = set_message(outbuf,1,data_len,True);
3166 START_PROFILE(SMBecho);
3168 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3170 /* copy any incoming data back out */
3172 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3174 if (smb_reverb > 100) {
3175 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3179 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3180 SSVAL(outbuf,smb_vwv0,seq_num);
3182 smb_setlen(outbuf,outsize - 4);
3184 if (!send_smb(smbd_server_fd(),outbuf))
3185 exit_server("reply_echo: send_smb failed.\n");
3188 DEBUG(3,("echo %d times\n", smb_reverb));
3192 END_PROFILE(SMBecho);
3197 /****************************************************************************
3198 reply to a printopen
3199 ****************************************************************************/
3200 int reply_printopen(connection_struct *conn,
3201 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3205 START_PROFILE(SMBsplopen);
3207 if (!CAN_PRINT(conn)) {
3208 END_PROFILE(SMBsplopen);
3209 return(ERROR(ERRDOS,ERRnoaccess));
3212 /* Open for exclusive use, write only. */
3213 fsp = print_fsp_open(conn);
3216 END_PROFILE(SMBsplopen);
3217 return(UNIXERROR(ERRDOS,ERRnoaccess));
3220 outsize = set_message(outbuf,1,0,True);
3221 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3223 DEBUG(3,("openprint fd=%d fnum=%d\n",
3224 fsp->fd, fsp->fnum));
3226 END_PROFILE(SMBsplopen);
3231 /****************************************************************************
3232 reply to a printclose
3233 ****************************************************************************/
3234 int reply_printclose(connection_struct *conn,
3235 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3237 int outsize = set_message(outbuf,0,0,True);
3238 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3240 START_PROFILE(SMBsplclose);
3242 CHECK_FSP(fsp,conn);
3245 if (!CAN_PRINT(conn)) {
3246 END_PROFILE(SMBsplclose);
3247 return(ERROR(ERRDOS,ERRnoaccess));
3250 DEBUG(3,("printclose fd=%d fnum=%d\n",
3251 fsp->fd,fsp->fnum));
3253 close_err = close_file(fsp,True);
3255 if(close_err != 0) {
3257 END_PROFILE(SMBsplclose);
3258 return(UNIXERROR(ERRHRD,ERRgeneral));
3261 END_PROFILE(SMBsplclose);
3266 /****************************************************************************
3267 reply to a printqueue
3268 ****************************************************************************/
3269 int reply_printqueue(connection_struct *conn,
3270 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3272 int outsize = set_message(outbuf,2,3,True);
3273 int max_count = SVAL(inbuf,smb_vwv0);
3274 int start_index = SVAL(inbuf,smb_vwv1);
3275 START_PROFILE(SMBsplretq);
3277 /* we used to allow the client to get the cnum wrong, but that
3278 is really quite gross and only worked when there was only
3279 one printer - I think we should now only accept it if they
3280 get it right (tridge) */
3281 if (!CAN_PRINT(conn)) {
3282 END_PROFILE(SMBsplretq);
3283 return(ERROR(ERRDOS,ERRnoaccess));
3286 SSVAL(outbuf,smb_vwv0,0);
3287 SSVAL(outbuf,smb_vwv1,0);
3288 CVAL(smb_buf(outbuf),0) = 1;
3289 SSVAL(smb_buf(outbuf),1,0);
3291 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3292 start_index, max_count));
3295 print_queue_struct *queue = NULL;
3296 char *p = smb_buf(outbuf) + 3;
3297 int count = print_queue_status(SNUM(conn), &queue,NULL);
3298 int num_to_get = ABS(max_count);
3299 int first = (max_count>0?start_index:start_index+max_count+1);
3305 num_to_get = MIN(num_to_get,count-first);
3308 for (i=first;i<first+num_to_get;i++) {
3309 put_dos_date2(p,0,queue[i].time);
3310 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3311 SSVAL(p,5, queue[i].job);
3312 SIVAL(p,7,queue[i].size);
3314 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII);
3319 outsize = set_message(outbuf,2,28*count+3,False);
3320 SSVAL(outbuf,smb_vwv0,count);
3321 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3322 CVAL(smb_buf(outbuf),0) = 1;
3323 SSVAL(smb_buf(outbuf),1,28*count);
3326 if (queue) free(queue);
3328 DEBUG(3,("%d entries returned in queue\n",count));
3331 END_PROFILE(SMBsplretq);
3336 /****************************************************************************
3337 reply to a printwrite
3338 ****************************************************************************/
3339 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3342 int outsize = set_message(outbuf,0,0,True);
3344 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3345 START_PROFILE(SMBsplwr);
3347 if (!CAN_PRINT(conn)) {
3348 END_PROFILE(SMBsplwr);
3349 return(ERROR(ERRDOS,ERRnoaccess));
3352 CHECK_FSP(fsp,conn);
3356 numtowrite = SVAL(smb_buf(inbuf),1);
3357 data = smb_buf(inbuf) + 3;
3359 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3360 END_PROFILE(SMBsplwr);
3361 return(UNIXERROR(ERRDOS,ERRnoaccess));
3364 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3366 END_PROFILE(SMBsplwr);
3371 /****************************************************************************
3372 The guts of the mkdir command, split out so it may be called by the NT SMB
3374 ****************************************************************************/
3375 int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
3377 BOOL bad_path = False;
3378 SMB_STRUCT_STAT sbuf;
3381 unix_convert(directory,conn,0,&bad_path,&sbuf);
3383 if (check_name(directory, conn))
3384 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3388 if((errno == ENOENT) && bad_path)
3390 unix_ERR_class = ERRDOS;
3391 unix_ERR_code = ERRbadpath;
3393 return(UNIXERROR(ERRDOS,ERRnoaccess));
3399 /****************************************************************************
3401 ****************************************************************************/
3402 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3406 START_PROFILE(SMBmkdir);
3408 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3410 outsize=mkdir_internal(conn, inbuf, outbuf, directory);
3412 outsize = set_message(outbuf,0,0,True);
3414 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3416 END_PROFILE(SMBmkdir);
3420 /****************************************************************************
3421 Static function used by reply_rmdir to delete an entire directory
3423 ****************************************************************************/
3425 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3429 void *dirptr = OpenDir(NULL, directory, False);
3434 while((dname = ReadDirName(dirptr)))
3439 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3442 /* Construct the full name. */
3443 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3449 pstrcpy(fullname, directory);
3450 pstrcat(fullname, "/");
3451 pstrcat(fullname, dname);
3453 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3459 if(st.st_mode & S_IFDIR)
3461 if(recursive_rmdir(conn, fullname)!=0)
3466 if(vfs_rmdir(conn,fullname) != 0)
3472 else if(vfs_unlink(conn,fullname) != 0)
3482 /****************************************************************************
3483 The internals of the rmdir code - called elsewhere.
3484 ****************************************************************************/
3486 BOOL rmdir_internals(connection_struct *conn, char *directory)
3490 ok = (vfs_rmdir(conn,directory) == 0);
3491 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3494 * Check to see if the only thing in this directory are
3495 * vetoed files/directories. If so then delete them and
3496 * retry. If we fail to delete any of them (and we *don't*
3497 * do a recursive delete) then fail the rmdir.
3499 BOOL all_veto_files = True;
3501 void *dirptr = OpenDir(conn, directory, False);
3505 int dirpos = TellDir(dirptr);
3506 while ((dname = ReadDirName(dirptr)))
3508 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3510 if(!IS_VETO_PATH(conn, dname))
3512 all_veto_files = False;
3518 SeekDir(dirptr,dirpos);
3519 while ((dname = ReadDirName(dirptr)))
3524 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3527 /* Construct the full name. */
3528 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3533 pstrcpy(fullname, directory);
3534 pstrcat(fullname, "/");
3535 pstrcat(fullname, dname);
3537 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3539 if(st.st_mode & S_IFDIR)
3541 if(lp_recursive_veto_delete(SNUM(conn)))
3543 if(recursive_rmdir(conn, fullname) != 0)
3546 if(vfs_rmdir(conn,fullname) != 0)
3549 else if(vfs_unlink(conn,fullname) != 0)
3553 /* Retry the rmdir */
3554 ok = (vfs_rmdir(conn,directory) == 0);
3564 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3565 directory,strerror(errno)));
3570 /****************************************************************************
3572 ****************************************************************************/
3574 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3579 BOOL bad_path = False;
3580 SMB_STRUCT_STAT sbuf;
3581 START_PROFILE(SMBrmdir);
3583 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3585 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3587 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3589 if (check_name(directory,conn))
3591 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3592 ok = rmdir_internals(conn, directory);
3597 if((errno == ENOENT) && bad_path)
3599 unix_ERR_class = ERRDOS;
3600 unix_ERR_code = ERRbadpath;
3602 END_PROFILE(SMBrmdir);
3603 return(UNIXERROR(ERRDOS,ERRbadpath));
3606 outsize = set_message(outbuf,0,0,True);
3608 DEBUG( 3, ( "rmdir %s\n", directory ) );
3610 END_PROFILE(SMBrmdir);
3615 /*******************************************************************
3616 resolve wildcards in a filename rename
3617 ********************************************************************/
3618 static BOOL resolve_wildcards(char *name1,char *name2)
3620 fstring root1,root2;
3624 name1 = strrchr_m(name1,'/');
3625 name2 = strrchr_m(name2,'/');
3627 if (!name1 || !name2) return(False);
3629 fstrcpy(root1,name1);
3630 fstrcpy(root2,name2);
3631 p = strrchr_m(root1,'.');
3638 p = strrchr_m(root2,'.');
3670 pstrcpy(name2,root2);
3673 pstrcat(name2,ext2);
3679 /*******************************************************************
3680 check if a user is allowed to rename a file
3681 ********************************************************************/
3682 static BOOL can_rename(char *fname,connection_struct *conn)
3684 SMB_STRUCT_STAT sbuf;
3686 if (!CAN_WRITE(conn)) return(False);
3688 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
3689 if (!check_file_sharing(conn,fname,True)) return(False);
3693 /****************************************************************************
3694 The guts of the rename command, split out so it may be called by the NT SMB
3696 ****************************************************************************/
3697 int rename_internals(connection_struct *conn,
3698 char *inbuf, char *outbuf, char *name,
3699 char *newname, BOOL replace_if_exists)
3703 pstring newname_last_component;
3706 BOOL bad_path1 = False;
3707 BOOL bad_path2 = False;
3709 int error = ERRnoaccess;
3712 SMB_STRUCT_STAT sbuf1, sbuf2;
3714 *directory = *mask = 0;
3716 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3717 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3720 * Split the old name into directory and last component
3721 * strings. Note that unix_convert may have stripped off a
3722 * leading ./ from both name and newname if the rename is
3723 * at the root of the share. We need to make sure either both
3724 * name and newname contain a / character or neither of them do
3725 * as this is checked in resolve_wildcards().
3728 p = strrchr_m(name,'/');
3730 pstrcpy(directory,".");
3734 pstrcpy(directory,name);
3736 *p = '/'; /* Replace needed for exceptional test below. */
3740 * We should only check the mangled cache
3741 * here if unix_convert failed. This means
3742 * that the path in 'mask' doesn't exist
3743 * on the file system and so we need to look
3744 * for a possible mangle. This patch from
3745 * Tine Smukavec <valentin.smukavec@hermes.si>.
3748 if (!rc && is_mangled(mask))
3749 check_mangled_cache( mask );
3751 has_wild = ms_has_wild(mask);
3755 * No wildcards - just process the one file.
3757 BOOL is_short_name = is_8_3(name, True);
3759 /* Add a terminating '/' to the directory name. */
3760 pstrcat(directory,"/");
3761 pstrcat(directory,mask);
3763 /* Ensure newname contains a '/' also */
3764 if(strrchr_m(newname,'/') == 0) {
3767 pstrcpy(tmpstr, "./");
3768 pstrcat(tmpstr, newname);
3769 pstrcpy(newname, tmpstr);
3772 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",
3773 case_sensitive, case_preserve, short_case_preserve, directory,
3774 newname, newname_last_component, is_short_name));
3777 * Check for special case with case preserving and not
3778 * case sensitive, if directory and newname are identical,
3779 * and the old last component differs from the original
3780 * last component only by case, then we should allow
3781 * the rename (user is trying to change the case of the
3784 if((case_sensitive == False) &&
3785 (((case_preserve == True) &&
3786 (is_short_name == False)) ||
3787 ((short_case_preserve == True) &&
3788 (is_short_name == True))) &&
3789 strcsequal(directory, newname)) {
3790 pstring newname_modified_last_component;
3793 * Get the last component of the modified name.
3794 * Note that we guarantee that newname contains a '/'
3797 p = strrchr_m(newname,'/');
3798 pstrcpy(newname_modified_last_component,p+1);
3800 if(strcsequal(newname_modified_last_component,
3801 newname_last_component) == False) {
3803 * Replace the modified last component with
3806 pstrcpy(p+1, newname_last_component);
3810 if(replace_if_exists) {
3812 * NT SMB specific flag - rename can overwrite
3813 * file with the same name so don't check for
3817 if(resolve_wildcards(directory,newname) &&
3818 can_rename(directory,conn) &&
3819 !conn->vfs_ops.rename(conn,directory,newname))
3822 if (resolve_wildcards(directory,newname) &&
3823 can_rename(directory,conn) &&
3824 !vfs_file_exist(conn,newname,NULL) &&
3825 !conn->vfs_ops.rename(conn,directory,newname))
3829 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3830 directory,newname));
3832 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3833 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3839 * Wildcards - process each file that matches.
3841 void *dirptr = NULL;
3845 if (check_name(directory,conn))
3846 dirptr = OpenDir(conn, directory, True);
3851 if (strequal(mask,"????????.???"))
3854 while ((dname = ReadDirName(dirptr))) {
3857 pstrcpy(fname,dname);
3859 if(!mask_match(fname, mask, case_sensitive))
3862 error = ERRnoaccess;
3863 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3864 if (!can_rename(fname,conn)) {
3865 DEBUG(6,("rename %s refused\n", fname));
3868 pstrcpy(destname,newname);
3870 if (!resolve_wildcards(fname,destname)) {
3871 DEBUG(6,("resolve_wildcards %s %s failed\n",
3876 if (!replace_if_exists &&
3877 vfs_file_exist(conn,destname, NULL)) {
3878 DEBUG(6,("file_exist %s\n", destname));
3883 if (!conn->vfs_ops.rename(conn,fname,destname))
3885 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3893 return(ERROR(ERRDOS,error));
3895 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3896 unix_ERR_class = ERRDOS;
3897 unix_ERR_code = ERRbadpath;
3899 return(UNIXERROR(ERRDOS,error));
3906 /****************************************************************************
3908 ****************************************************************************/
3910 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3917 START_PROFILE(SMBmv);
3919 p = smb_buf(inbuf) + 1;
3920 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3922 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3924 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3925 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3927 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3929 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3933 * Win2k needs a changenotify request response before it will
3934 * update after a rename..
3937 process_pending_change_notify_queue((time_t)0);
3939 outsize = set_message(outbuf,0,0,True);
3946 /*******************************************************************
3947 copy a file as part of a reply_copy
3948 ******************************************************************/
3950 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3951 int count,BOOL target_is_directory, int *err_ret)
3954 SMB_STRUCT_STAT src_sbuf, sbuf2;
3956 files_struct *fsp1,*fsp2;
3961 pstrcpy(dest,dest1);
3962 if (target_is_directory) {
3963 char *p = strrchr_m(src,'/');
3972 if (!vfs_file_exist(conn,src,&src_sbuf))
3975 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3976 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3982 if (!target_is_directory && count)
3983 ofun = FILE_EXISTS_OPEN;
3985 vfs_stat(conn,dest,&sbuf2);
3986 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3987 ofun,src_sbuf.st_mode,0,&Access,&action);
3990 close_file(fsp1,False);
3994 if ((ofun&3) == 1) {
3995 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3996 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3999 * Stop the copy from occurring.
4002 src_sbuf.st_size = 0;
4006 if (src_sbuf.st_size)
4007 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
4009 close_file(fsp1,False);
4011 * As we are opening fsp1 read-only we only expect
4012 * an error on close on fsp2 if we are out of space.
4013 * Thus we don't look at the error return from the
4016 *err_ret = close_file(fsp2,False);
4018 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4023 /****************************************************************************
4024 reply to a file copy.
4025 ****************************************************************************/
4026 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4031 pstring mask,newname;
4034 int error = ERRnoaccess;
4038 int tid2 = SVAL(inbuf,smb_vwv0);
4039 int ofun = SVAL(inbuf,smb_vwv1);
4040 int flags = SVAL(inbuf,smb_vwv2);
4041 BOOL target_is_directory=False;
4042 BOOL bad_path1 = False;
4043 BOOL bad_path2 = False;
4045 SMB_STRUCT_STAT sbuf1, sbuf2;
4046 START_PROFILE(SMBcopy);
4048 *directory = *mask = 0;
4051 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
4052 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
4054 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4056 if (tid2 != conn->cnum) {
4057 /* can't currently handle inter share copies XXXX */
4058 DEBUG(3,("Rejecting inter-share copy\n"));
4059 END_PROFILE(SMBcopy);
4060 return(ERROR(ERRSRV,ERRinvdevice));
4063 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4064 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4066 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4067 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4069 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4071 if ((flags&1) && target_is_directory) {
4072 END_PROFILE(SMBcopy);
4073 return(ERROR(ERRDOS,ERRbadfile));
4076 if ((flags&2) && !target_is_directory) {
4077 END_PROFILE(SMBcopy);
4078 return(ERROR(ERRDOS,ERRbadpath));
4081 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4082 /* wants a tree copy! XXXX */
4083 DEBUG(3,("Rejecting tree copy\n"));
4084 END_PROFILE(SMBcopy);
4085 return(ERROR(ERRSRV,ERRerror));
4088 p = strrchr_m(name,'/');
4090 pstrcpy(directory,"./");
4094 pstrcpy(directory,name);
4099 * We should only check the mangled cache
4100 * here if unix_convert failed. This means
4101 * that the path in 'mask' doesn't exist
4102 * on the file system and so we need to look
4103 * for a possible mangle. This patch from
4104 * Tine Smukavec <valentin.smukavec@hermes.si>.
4107 if (!rc && is_mangled(mask))
4108 check_mangled_cache( mask );
4110 has_wild = ms_has_wild(mask);
4113 pstrcat(directory,"/");
4114 pstrcat(directory,mask);
4115 if (resolve_wildcards(directory,newname) &&
4116 copy_file(directory,newname,conn,ofun,
4117 count,target_is_directory,&err)) count++;
4120 END_PROFILE(SMBcopy);
4121 return(UNIXERROR(ERRHRD,ERRgeneral));
4123 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4125 void *dirptr = NULL;
4129 if (check_name(directory,conn))
4130 dirptr = OpenDir(conn, directory, True);
4135 if (strequal(mask,"????????.???"))
4138 while ((dname = ReadDirName(dirptr))) {
4140 pstrcpy(fname,dname);
4142 if(!mask_match(fname, mask, case_sensitive))
4145 error = ERRnoaccess;
4146 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4147 pstrcpy(destname,newname);
4148 if (resolve_wildcards(fname,destname) &&
4149 copy_file(fname,destname,conn,ofun,
4150 count,target_is_directory,&err)) count++;
4151 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4159 /* Error on close... */
4161 END_PROFILE(SMBcopy);
4162 return(UNIXERROR(ERRHRD,ERRgeneral));
4166 END_PROFILE(SMBcopy);
4167 return(ERROR(ERRDOS,error));
4170 if((errno == ENOENT) && (bad_path1 || bad_path2))
4172 unix_ERR_class = ERRDOS;
4173 unix_ERR_code = ERRbadpath;
4175 END_PROFILE(SMBcopy);
4176 return(UNIXERROR(ERRDOS,error));
4180 outsize = set_message(outbuf,1,0,True);
4181 SSVAL(outbuf,smb_vwv0,count);
4183 END_PROFILE(SMBcopy);
4187 /****************************************************************************
4189 ****************************************************************************/
4190 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4196 START_PROFILE(pathworks_setdir);
4199 if (!CAN_SETDIR(snum)) {
4200 END_PROFILE(pathworks_setdir);
4201 return(ERROR(ERRDOS,ERRnoaccess));
4204 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
4206 if (strlen(newdir) == 0) {
4209 ok = vfs_directory_exist(conn,newdir,NULL);
4211 string_set(&conn->connectpath,newdir);
4216 END_PROFILE(pathworks_setdir);
4217 return(ERROR(ERRDOS,ERRbadpath));
4220 outsize = set_message(outbuf,0,0,True);
4221 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4223 DEBUG(3,("setdir %s\n", newdir));
4225 END_PROFILE(pathworks_setdir);
4229 /****************************************************************************
4230 Get a lock pid, dealing with large count requests.
4231 ****************************************************************************/
4233 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4235 if(!large_file_format)
4236 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4238 return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
4241 /****************************************************************************
4242 Get a lock count, dealing with large count requests.
4243 ****************************************************************************/
4245 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4247 SMB_BIG_UINT count = 0;
4249 if(!large_file_format) {
4250 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4253 #if defined(HAVE_LONGLONG)
4254 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4255 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4256 #else /* HAVE_LONGLONG */
4259 * NT4.x seems to be broken in that it sends large file (64 bit)
4260 * lockingX calls even if the CAP_LARGE_FILES was *not*
4261 * negotiated. For boxes without large unsigned ints truncate the
4262 * lock count by dropping the top 32 bits.
4265 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4266 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4267 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4268 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4269 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4272 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4273 #endif /* HAVE_LONGLONG */
4279 /****************************************************************************
4280 Get a lock offset, dealing with large offset requests.
4281 ****************************************************************************/
4283 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4285 SMB_BIG_UINT offset = 0;
4289 if(!large_file_format) {
4290 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4293 #if defined(HAVE_LONGLONG)
4294 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4295 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4296 #else /* HAVE_LONGLONG */
4299 * NT4.x seems to be broken in that it sends large file (64 bit)
4300 * lockingX calls even if the CAP_LARGE_FILES was *not*
4301 * negotiated. For boxes without large unsigned ints mangle the
4302 * lock offset by mapping the top 32 bits onto the lower 32.
4305 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4306 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4307 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4310 if((new_low = map_lock_offset(high, low)) == 0) {
4312 return (SMB_BIG_UINT)-1;
4315 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4316 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4317 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4318 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4321 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4322 #endif /* HAVE_LONGLONG */
4328 /****************************************************************************
4329 reply to a lockingX request
4330 ****************************************************************************/
4332 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4334 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4335 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4336 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4337 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4338 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4339 SMB_BIG_UINT count = 0, offset = 0;
4341 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4344 uint32 ecode=0, dummy2;
4345 int eclass=0, dummy1;
4346 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4348 START_PROFILE(SMBlockingX);
4350 CHECK_FSP(fsp,conn);
4353 data = smb_buf(inbuf);
4355 /* Check if this is an oplock break on a file
4356 we have granted an oplock on.
4358 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4360 /* Client can insist on breaking to none. */
4361 BOOL break_to_none = (oplocklevel == 0);
4363 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4364 (unsigned int)oplocklevel, fsp->fnum ));
4367 * Make sure we have granted an exclusive or batch oplock on this file.
4370 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4372 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4373 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4375 /* if this is a pure oplock break request then don't send a reply */
4376 if (num_locks == 0 && num_ulocks == 0) {
4377 END_PROFILE(SMBlockingX);
4380 END_PROFILE(SMBlockingX);
4381 return ERROR(ERRDOS,ERRlock);
4385 if (remove_oplock(fsp, break_to_none) == False) {
4386 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4390 /* if this is a pure oplock break request then don't send a reply */
4391 if (num_locks == 0 && num_ulocks == 0)
4393 /* Sanity check - ensure a pure oplock break is not a
4395 if(CVAL(inbuf,smb_vwv0) != 0xff)
4396 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4397 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4398 END_PROFILE(SMBlockingX);
4404 * We do this check *after* we have checked this is not a oplock break
4405 * response message. JRA.
4408 release_level_2_oplocks_on_change(fsp);
4410 /* Data now points at the beginning of the list
4411 of smb_unlkrng structs */
4412 for(i = 0; i < (int)num_ulocks; i++) {
4413 lock_pid = get_lock_pid( data, i, large_file_format);
4414 count = get_lock_count( data, i, large_file_format);
4415 offset = get_lock_offset( data, i, large_file_format, &err);
4418 * There is no error code marked "stupid client bug".... :-).
4421 END_PROFILE(SMBlockingX);
4422 return ERROR(ERRDOS,ERRnoaccess);
4425 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4426 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4428 if(!do_unlock(fsp,conn,lock_pid,count,offset, &eclass, &ecode)) {
4429 END_PROFILE(SMBlockingX);
4430 return ERROR(eclass,ecode);
4434 /* Setup the timeout in seconds. */
4435 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4437 /* Now do any requested locks */
4438 data += ((large_file_format ? 20 : 10)*num_ulocks);
4440 /* Data now points at the beginning of the list
4441 of smb_lkrng structs */
4443 for(i = 0; i < (int)num_locks; i++) {
4444 lock_pid = get_lock_pid( data, i, large_file_format);
4445 count = get_lock_count( data, i, large_file_format);
4446 offset = get_lock_offset( data, i, large_file_format, &err);
4449 * There is no error code marked "stupid client bug".... :-).
4452 END_PROFILE(SMBlockingX);
4453 return ERROR(ERRDOS,ERRnoaccess);
4456 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
4457 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4459 if(!do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4461 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4463 * A blocking lock was requested. Package up
4464 * this smb into a queued request and push it
4465 * onto the blocking lock queue.
4467 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4468 END_PROFILE(SMBlockingX);
4476 /* If any of the above locks failed, then we must unlock
4477 all of the previous locks (X/Open spec). */
4478 if(i != num_locks && num_locks != 0) {
4480 * Ensure we don't do a remove on the lock that just failed,
4481 * as under POSIX rules, if we have a lock already there, we
4482 * will delete it (and we shouldn't) .....
4484 for(i--; i >= 0; i--) {
4485 lock_pid = get_lock_pid( data, i, large_file_format);
4486 count = get_lock_count( data, i, large_file_format);
4487 offset = get_lock_offset( data, i, large_file_format, &err);
4490 * There is no error code marked "stupid client bug".... :-).
4493 END_PROFILE(SMBlockingX);
4494 return ERROR(ERRDOS,ERRnoaccess);
4497 do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2);
4499 END_PROFILE(SMBlockingX);
4500 return ERROR(eclass,ecode);
4503 set_message(outbuf,2,0,True);
4505 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4506 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4508 END_PROFILE(SMBlockingX);
4509 return chain_reply(inbuf,outbuf,length,bufsize);
4513 /****************************************************************************
4514 reply to a SMBreadbmpx (read block multiplex) request
4515 ****************************************************************************/
4516 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4527 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4528 START_PROFILE(SMBreadBmpx);
4530 /* this function doesn't seem to work - disable by default */
4531 if (!lp_readbmpx()) {
4532 END_PROFILE(SMBreadBmpx);
4533 return(ERROR(ERRSRV,ERRuseSTD));
4536 outsize = set_message(outbuf,8,0,True);
4538 CHECK_FSP(fsp,conn);
4542 startpos = IVAL(inbuf,smb_vwv1);
4543 maxcount = SVAL(inbuf,smb_vwv3);
4545 data = smb_buf(outbuf);
4546 pad = ((long)data)%4;
4547 if (pad) pad = 4 - pad;
4550 max_per_packet = bufsize-(outsize+pad);
4554 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4555 END_PROFILE(SMBreadBmpx);
4556 return(ERROR(ERRDOS,ERRlock));
4561 size_t N = MIN(max_per_packet,tcount-total_read);
4563 nread = read_file(fsp,data,startpos,N);
4565 if (nread <= 0) nread = 0;
4567 if (nread < (ssize_t)N)
4568 tcount = total_read + nread;
4570 set_message(outbuf,8,nread,False);
4571 SIVAL(outbuf,smb_vwv0,startpos);
4572 SSVAL(outbuf,smb_vwv2,tcount);
4573 SSVAL(outbuf,smb_vwv6,nread);
4574 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4576 if (!send_smb(smbd_server_fd(),outbuf))
4577 exit_server("reply_readbmpx: send_smb failed.\n");
4579 total_read += nread;
4582 while (total_read < (ssize_t)tcount);
4584 END_PROFILE(SMBreadBmpx);
4588 /****************************************************************************
4589 reply to a SMBwritebmpx (write block multiplex primary) request
4590 ****************************************************************************/
4592 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4595 ssize_t nwritten = -1;
4602 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4603 START_PROFILE(SMBwriteBmpx);
4605 CHECK_FSP(fsp,conn);
4609 tcount = SVAL(inbuf,smb_vwv1);
4610 startpos = IVAL(inbuf,smb_vwv3);
4611 write_through = BITSETW(inbuf+smb_vwv7,0);
4612 numtowrite = SVAL(inbuf,smb_vwv10);
4613 smb_doff = SVAL(inbuf,smb_vwv11);
4615 data = smb_base(inbuf) + smb_doff;
4617 /* If this fails we need to send an SMBwriteC response,
4618 not an SMBwritebmpx - set this up now so we don't forget */
4619 CVAL(outbuf,smb_com) = SMBwritec;
4621 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4622 END_PROFILE(SMBwriteBmpx);
4623 return(ERROR(ERRDOS,ERRlock));
4626 nwritten = write_file(fsp,data,startpos,numtowrite);
4628 if(lp_syncalways(SNUM(conn)) || write_through)
4629 sync_file(conn,fsp);
4631 if(nwritten < (ssize_t)numtowrite) {
4632 END_PROFILE(SMBwriteBmpx);
4633 return(UNIXERROR(ERRHRD,ERRdiskfull));
4636 /* If the maximum to be written to this file
4637 is greater than what we just wrote then set
4638 up a secondary struct to be attached to this
4639 fd, we will use this to cache error messages etc. */
4640 if((ssize_t)tcount > nwritten)
4642 write_bmpx_struct *wbms;
4643 if(fsp->wbmpx_ptr != NULL)
4644 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4646 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4649 DEBUG(0,("Out of memory in reply_readmpx\n"));
4650 END_PROFILE(SMBwriteBmpx);
4651 return(ERROR(ERRSRV,ERRnoresource));
4653 wbms->wr_mode = write_through;
4654 wbms->wr_discard = False; /* No errors yet */
4655 wbms->wr_total_written = nwritten;
4656 wbms->wr_errclass = 0;
4658 fsp->wbmpx_ptr = wbms;
4661 /* We are returning successfully, set the message type back to
4663 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4665 outsize = set_message(outbuf,1,0,True);
4667 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4669 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4670 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4672 if (write_through && tcount==nwritten) {
4673 /* we need to send both a primary and a secondary response */
4674 smb_setlen(outbuf,outsize - 4);
4675 if (!send_smb(smbd_server_fd(),outbuf))
4676 exit_server("reply_writebmpx: send_smb failed.\n");
4678 /* now the secondary */
4679 outsize = set_message(outbuf,1,0,True);
4680 CVAL(outbuf,smb_com) = SMBwritec;
4681 SSVAL(outbuf,smb_vwv0,nwritten);
4684 END_PROFILE(SMBwriteBmpx);
4689 /****************************************************************************
4690 reply to a SMBwritebs (write block multiplex secondary) request
4691 ****************************************************************************/
4692 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4695 ssize_t nwritten = -1;
4702 write_bmpx_struct *wbms;
4703 BOOL send_response = False;
4704 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4705 START_PROFILE(SMBwriteBs);
4707 CHECK_FSP(fsp,conn);
4710 tcount = SVAL(inbuf,smb_vwv1);
4711 startpos = IVAL(inbuf,smb_vwv2);
4712 numtowrite = SVAL(inbuf,smb_vwv6);
4713 smb_doff = SVAL(inbuf,smb_vwv7);
4715 data = smb_base(inbuf) + smb_doff;
4717 /* We need to send an SMBwriteC response, not an SMBwritebs */
4718 CVAL(outbuf,smb_com) = SMBwritec;
4720 /* This fd should have an auxiliary struct attached,
4721 check that it does */
4722 wbms = fsp->wbmpx_ptr;
4724 END_PROFILE(SMBwriteBs);
4728 /* If write through is set we can return errors, else we must
4730 write_through = wbms->wr_mode;
4732 /* Check for an earlier error */
4733 if(wbms->wr_discard) {
4734 END_PROFILE(SMBwriteBs);
4735 return -1; /* Just discard the packet */
4738 nwritten = write_file(fsp,data,startpos,numtowrite);
4740 if(lp_syncalways(SNUM(conn)) || write_through)
4741 sync_file(conn,fsp);
4743 if (nwritten < (ssize_t)numtowrite)
4747 /* We are returning an error - we can delete the aux struct */
4748 if (wbms) free((char *)wbms);
4749 fsp->wbmpx_ptr = NULL;
4750 END_PROFILE(SMBwriteBs);
4751 return(ERROR(ERRHRD,ERRdiskfull));
4753 END_PROFILE(SMBwriteBs);
4754 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4757 /* Increment the total written, if this matches tcount
4758 we can discard the auxiliary struct (hurrah !) and return a writeC */
4759 wbms->wr_total_written += nwritten;
4760 if(wbms->wr_total_written >= tcount)
4764 outsize = set_message(outbuf,1,0,True);
4765 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4766 send_response = True;
4770 fsp->wbmpx_ptr = NULL;
4774 END_PROFILE(SMBwriteBs);
4778 END_PROFILE(SMBwriteBs);
4783 /****************************************************************************
4784 reply to a SMBsetattrE
4785 ****************************************************************************/
4787 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4789 struct utimbuf unix_times;
4791 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4792 START_PROFILE(SMBsetattrE);
4794 outsize = set_message(outbuf,0,0,True);
4796 CHECK_FSP(fsp,conn);
4799 /* Convert the DOS times into unix times. Ignore create
4800 time as UNIX can't set this.
4802 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4803 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4806 * Patch from Ray Frush <frush@engr.colostate.edu>
4807 * Sometimes times are sent as zero - ignore them.
4810 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4812 /* Ignore request */
4815 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4816 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4818 END_PROFILE(SMBsetattrE);
4821 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4823 /* set modify time = to access time if modify time was 0 */
4824 unix_times.modtime = unix_times.actime;
4827 /* Set the date on this file */
4828 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4829 END_PROFILE(SMBsetattrE);
4830 return(ERROR(ERRDOS,ERRnoaccess));
4833 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4834 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4836 END_PROFILE(SMBsetattrE);
4841 /****************************************************************************
4842 reply to a SMBgetattrE
4843 ****************************************************************************/
4845 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4847 SMB_STRUCT_STAT sbuf;
4850 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4851 START_PROFILE(SMBgetattrE);
4853 outsize = set_message(outbuf,11,0,True);
4855 CHECK_FSP(fsp,conn);
4858 /* Do an fstat on this file */
4859 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4860 END_PROFILE(SMBgetattrE);
4861 return(UNIXERROR(ERRDOS,ERRnoaccess));
4864 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4866 /* Convert the times into dos times. Set create
4867 date to be last modify date as UNIX doesn't save
4869 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4870 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4871 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4874 SIVAL(outbuf,smb_vwv6,0);
4875 SIVAL(outbuf,smb_vwv8,0);
4879 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4880 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4882 SSVAL(outbuf,smb_vwv10, mode);
4884 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4886 END_PROFILE(SMBgetattrE);