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);
232 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
235 END_PROFILE(SMBtcon);
236 return(connection_error(inbuf,outbuf,ecode));
239 outsize = set_message(outbuf,2,0,True);
240 SSVAL(outbuf,smb_vwv0,max_recv);
241 SSVAL(outbuf,smb_vwv1,conn->cnum);
242 SSVAL(outbuf,smb_tid,conn->cnum);
244 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
245 service, user, conn->cnum));
247 END_PROFILE(SMBtcon);
251 /****************************************************************************
252 Reply to a tcon and X.
253 ****************************************************************************/
255 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
262 uint16 vuid = SVAL(inbuf,smb_uid);
263 int passlen = SVAL(inbuf,smb_vwv3);
266 START_PROFILE(SMBtconX);
268 *service = *user = *password = *devicename = 0;
270 /* we might have to close an old one */
271 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
272 close_cnum(conn,vuid);
275 if (passlen > MAX_PASS_LEN) {
276 overflow_attack(passlen);
277 return(ERROR(ERRDOS,ERRbuftoosmall));
280 memcpy(password,smb_buf(inbuf),passlen);
282 p = smb_buf(inbuf) + passlen;
283 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
286 if (strequal(password," "))
288 passlen = strlen(password);
291 q = strchr_m(path+2,'\\');
293 END_PROFILE(SMBtconX);
294 return(ERROR(ERRDOS,ERRnosuchshare));
296 fstrcpy(service,q+1);
297 q = strchr_m(service,'%');
302 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
304 DEBUG(4,("Got device type %s\n",devicename));
307 * If the vuid is valid, we should be using that....
310 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
311 pstrcpy(user,validated_username(vuid));
315 * Pass the user through the NT -> unix user mapping
319 (void)map_username(user);
322 * Do any UNIX username case mangling.
324 (void)Get_Pwnam(user, True);
326 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
329 END_PROFILE(SMBtconX);
330 return(connection_error(inbuf,outbuf,ecode));
333 if (Protocol < PROTOCOL_NT1) {
334 set_message(outbuf,2,0,True);
336 p += srvstr_push(outbuf, p, devicename, -1,
337 STR_TERMINATE|STR_ASCII);
338 set_message_end(outbuf,p);
340 /* NT sets the fstype of IPC$ to the null string */
341 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
343 set_message(outbuf,3,0,True);
346 p += srvstr_push(outbuf, p, devicename, -1,
347 STR_TERMINATE|STR_ASCII);
348 p += srvstr_push(outbuf, p, fsname, -1,
351 set_message_end(outbuf,p);
353 /* what does setting this bit do? It is set by NT4 and
354 may affect the ability to autorun mounted cdroms */
355 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
357 init_dfsroot(conn, inbuf, outbuf);
361 DEBUG(3,("tconX service=%s user=%s\n",
364 /* set the incoming and outgoing tid to the just created one */
365 SSVAL(inbuf,smb_tid,conn->cnum);
366 SSVAL(outbuf,smb_tid,conn->cnum);
368 END_PROFILE(SMBtconX);
369 return chain_reply(inbuf,outbuf,length,bufsize);
373 /****************************************************************************
374 reply to an unknown type
375 ****************************************************************************/
376 int reply_unknown(char *inbuf,char *outbuf)
379 type = CVAL(inbuf,smb_com);
381 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
382 smb_fn_name(type), type, type));
384 return(ERROR(ERRSRV,ERRunknownsmb));
388 /****************************************************************************
390 ****************************************************************************/
391 int reply_ioctl(connection_struct *conn,
392 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
394 uint16 device = SVAL(inbuf,smb_vwv1);
395 uint16 function = SVAL(inbuf,smb_vwv2);
396 uint32 ioctl_code = (device << 16) + function;
397 int replysize, outsize;
399 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
400 START_PROFILE(SMBioctl);
402 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
406 case IOCTL_QUERY_JOB_INFO:
410 END_PROFILE(SMBioctl);
411 return(ERROR(ERRSRV,ERRnosupport));
414 outsize = set_message(outbuf,8,replysize+1,True);
415 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
416 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
417 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
418 p = smb_buf(outbuf) + 1; /* Allow for alignment */
422 case IOCTL_QUERY_JOB_INFO:
423 SSVAL(p,0,fsp->print_jobid); /* Job number */
424 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
425 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
429 END_PROFILE(SMBioctl);
433 /****************************************************************************
434 always return an error: it's just a matter of which one...
435 ****************************************************************************/
436 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
437 char *smb_passwd, int smb_passlen,
438 char *smb_nt_passwd, int smb_nt_passlen)
440 /* check if trust account exists */
441 SAM_ACCOUNT *sam_trust_acct = NULL;
445 pdb_init_sam(&sam_trust_acct);
447 if (lp_security() == SEC_USER) {
448 ret = pdb_getsampwnam(sam_trust_acct, user);
450 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
451 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
452 pdb_free_sam(sam_trust_acct);
453 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
457 /* lkclXXXX: workstation entry doesn't exist */
458 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
459 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
460 pdb_free_sam(sam_trust_acct);
461 return(ERROR(0, NT_STATUS_NO_SUCH_USER));
463 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
464 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
465 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
466 pdb_free_sam(sam_trust_acct);
467 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
470 if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) {
471 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
472 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
473 pdb_free_sam(sam_trust_acct);
474 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
477 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
478 pdb_free_sam(sam_trust_acct);
479 if (acct_ctrl & ACB_DOMTRUST) {
480 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
481 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
482 return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
485 if (acct_ctrl & ACB_SVRTRUST) {
486 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
487 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
488 return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
491 if (acct_ctrl & ACB_WSTRUST) {
492 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
493 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
494 return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
498 /* don't know what to do: indicate logon failure */
499 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
500 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
503 /****************************************************************************
504 Create a UNIX user on demand.
505 ****************************************************************************/
507 int smb_create_user(char *unix_user, char *homedir)
512 pstrcpy(add_script, lp_adduser_script());
513 if (! *add_script) return -1;
514 all_string_sub(add_script, "%u", unix_user, sizeof(pstring));
516 all_string_sub(add_script, "%H", homedir, sizeof(pstring));
517 ret = smbrun(add_script,NULL);
518 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
522 /****************************************************************************
523 Delete a UNIX user on demand.
524 ****************************************************************************/
526 static int smb_delete_user(char *unix_user)
531 pstrcpy(del_script, lp_deluser_script());
532 if (! *del_script) return -1;
533 all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
534 ret = smbrun(del_script,NULL);
535 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
539 /****************************************************************************
540 Check user is in correct domain if required
541 ****************************************************************************/
543 static BOOL check_domain_match(char *user, char *domain)
546 * If we aren't serving to trusted domains, we must make sure that
547 * the validation request comes from an account in the same domain
548 * as the Samba server
551 if (!lp_allow_trusted_domains() &&
552 !strequal(lp_workgroup(), domain) ) {
553 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
560 /****************************************************************************
561 Check for a valid username and password in security=server mode.
562 ****************************************************************************/
564 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
565 char *smb_apasswd, int smb_apasslen,
566 char *smb_ntpasswd, int smb_ntpasslen)
570 if(lp_security() != SEC_SERVER)
573 if (!check_domain_match(orig_user, domain))
576 ret = server_validate(orig_user, domain,
577 smb_apasswd, smb_apasslen,
578 smb_ntpasswd, smb_ntpasslen);
580 struct passwd *pwd=NULL;
583 * User validated ok against Domain controller.
584 * If the admin wants us to try and create a UNIX
585 * user on the fly, do so.
586 * Note that we can never delete users when in server
587 * level security as we never know if it was a failure
588 * due to a bad password, or the user really doesn't exist.
590 if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
591 smb_create_user(unix_user, NULL);
594 if(lp_adduser_script() && pwd) {
598 * Also call smb_create_user if the users home directory
599 * doesn't exist. Used with winbindd to allow the script to
600 * create the home directory for a user mapped with winbindd.
603 if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
604 smb_create_user(unix_user, pwd->pw_dir);
611 /****************************************************************************
612 Check for a valid username and password in security=domain mode.
613 ****************************************************************************/
615 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
616 char *smb_apasswd, int smb_apasslen,
617 char *smb_ntpasswd, int smb_ntpasslen)
620 BOOL user_exists = True;
621 struct passwd *pwd=NULL;
623 if(lp_security() != SEC_DOMAIN)
626 if (!check_domain_match(orig_user, domain))
629 ret = domain_client_validate(orig_user, domain,
630 smb_apasswd, smb_apasslen,
631 smb_ntpasswd, smb_ntpasslen,
636 * User validated ok against Domain controller.
637 * If the admin wants us to try and create a UNIX
638 * user on the fly, do so.
640 if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True)))
641 smb_create_user(unix_user, NULL);
643 if(lp_adduser_script() && pwd) {
647 * Also call smb_create_user if the users home directory
648 * doesn't exist. Used with winbindd to allow the script to
649 * create the home directory for a user mapped with winbindd.
652 if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
653 smb_create_user(unix_user, pwd->pw_dir);
658 * User failed to validate ok against Domain controller.
659 * If the failure was "user doesn't exist" and admin
660 * wants us to try and delete that UNIX user on the fly,
663 if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True))
664 smb_delete_user(unix_user);
670 /****************************************************************************
671 Return a bad password error configured for the correct client type.
672 ****************************************************************************/
674 static int bad_password_error(char *inbuf,char *outbuf)
676 enum remote_arch_types ra_type = get_remote_arch();
678 if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
679 (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
680 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
681 return(ERROR(0,NT_STATUS_LOGON_FAILURE));
684 return(ERROR(ERRSRV,ERRbadpw));
687 /****************************************************************************
688 reply to a session setup command
689 ****************************************************************************/
691 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
697 int smb_apasslen = 0;
699 int smb_ntpasslen = 0;
700 pstring smb_ntpasswd;
701 BOOL valid_nt_password = False;
702 BOOL valid_lm_password = False;
707 fstring native_lanman;
709 static BOOL done_sesssetup = False;
710 BOOL doencrypt = SMBENCRYPT();
711 START_PROFILE(SMBsesssetupX);
716 smb_bufsize = SVAL(inbuf,smb_vwv2);
718 if (Protocol < PROTOCOL_NT1) {
719 smb_apasslen = SVAL(inbuf,smb_vwv7);
720 if (smb_apasslen > MAX_PASS_LEN) {
721 overflow_attack(smb_apasslen);
722 return(ERROR(ERRDOS,ERRbuftoosmall));
725 srvstr_pull(inbuf, smb_apasswd, smb_buf(inbuf), sizeof(smb_apasswd), smb_apasslen, 0);
726 srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE);
728 if (!doencrypt && (lp_security() != SEC_SERVER)) {
729 smb_apasslen = strlen(smb_apasswd);
732 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
733 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
734 enum remote_arch_types ra_type = get_remote_arch();
735 char *p = smb_buf(inbuf);
737 if(global_client_caps == 0)
738 global_client_caps = IVAL(inbuf,smb_vwv11);
740 /* client_caps is used as final determination if client is NT or Win95.
741 This is needed to return the correct error codes in some
745 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
746 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
747 set_remote_arch( RA_WIN95);
751 if (passlen1 != 24 && passlen2 != 24)
754 if (passlen1 > MAX_PASS_LEN) {
755 overflow_attack(passlen1);
756 return(ERROR(ERRDOS,ERRbuftoosmall));
759 passlen1 = MIN(passlen1, MAX_PASS_LEN);
760 passlen2 = MIN(passlen2, MAX_PASS_LEN);
763 /* both Win95 and WinNT stuff up the password lengths for
764 non-encrypting systems. Uggh.
766 if passlen1==24 its a win95 system, and its setting the
767 password length incorrectly. Luckily it still works with the
768 default code because Win95 will null terminate the password
771 if passlen1>0 and passlen2>0 then maybe its a NT box and its
772 setting passlen2 to some random value which really stuffs
773 things up. we need to fix that one. */
775 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
779 if (lp_restrict_anonymous()) {
780 /* there seems to be no reason behind the differences in MS clients formatting
781 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
782 * in particular seems to have an extra null byte between the username and the
783 * domain, or the password length calculation is wrong, which throws off the
784 * string extraction routines below. This makes the value of domain be the
785 * empty string, which fails the restrict anonymous check further down.
786 * This compensates for that, and allows browsing to work in mixed NT and
787 * win95 environments even when restrict anonymous is true. AAB
789 dump_data(100, p, 0x70);
790 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
791 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
792 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
793 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
794 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
799 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
800 /* Save the lanman2 password and the NT md4 password. */
801 smb_apasslen = passlen1;
802 memcpy(smb_apasswd,p,smb_apasslen);
803 smb_apasswd[smb_apasslen] = 0;
804 smb_ntpasslen = passlen2;
805 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
806 smb_ntpasswd[smb_ntpasslen] = 0;
808 /* we use the first password that they gave */
809 smb_apasslen = passlen1;
810 StrnCpy(smb_apasswd,p,smb_apasslen);
812 /* trim the password */
813 smb_apasslen = strlen(smb_apasswd);
815 /* wfwg sometimes uses a space instead of a null */
816 if (strequal(smb_apasswd," ")) {
822 p += passlen1 + passlen2;
823 p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
826 * Incoming user and domain are in DOS codepage format. Convert
829 p += srvstr_pull(inbuf, domain, p, sizeof(domain),
831 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
833 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
835 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
836 domain,native_os,native_lanman));
839 /* don't allow for weird usernames or domains */
840 alpha_strcpy(user, user, ". _-$", sizeof(user));
841 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
842 if (strstr(user, "..") || strstr(domain,"..")) {
843 return bad_password_error(inbuf, outbuf);
846 DEBUG(3,("sesssetupX:name=[%s]\n",user));
848 /* If name ends in $ then I think it's asking about whether a */
849 /* computer with that name (minus the $) has access. For now */
850 /* say yes to everything ending in $. */
852 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
853 END_PROFILE(SMBsesssetupX);
854 return session_trust_account(conn, inbuf, outbuf, user,
855 smb_apasswd, smb_apasslen,
856 smb_ntpasswd, smb_ntpasslen);
859 if (done_sesssetup && lp_restrict_anonymous()) {
860 /* tests show that even if browsing is done over already validated connections
861 * without a username and password the domain is still provided, which it
862 * wouldn't be if it was a purely anonymous connection. So, in order to
863 * restrict anonymous, we only deny connections that have no session
864 * information. If a domain has been provided, then it's not a purely
865 * anonymous connection. AAB
867 if (!*user && !*smb_apasswd && !*domain) {
868 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
869 END_PROFILE(SMBsesssetupX);
870 return(ERROR(ERRDOS,ERRnoaccess));
874 /* If no username is sent use the guest account */
876 pstrcpy(user,lp_guestaccount(-1));
880 pstrcpy(current_user_info.smb_name,user);
882 reload_services(True);
885 * Save the username before mapping. We will use
886 * the original username sent to us for security=server
887 * and security=domain checking.
890 pstrcpy( orig_user, user);
893 * Always try the "DOMAIN\user" lookup first, as this is the most
894 * specific case. If this fails then try the simple "user" lookup.
900 /* Work out who's who */
902 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
903 domain, lp_winbind_separator(), user);
905 if (sys_getpwnam(dom_user) != NULL) {
906 pstrcpy(user, dom_user);
907 DEBUG(3,("Using unix username %s\n", dom_user));
912 * Pass the user through the NT -> unix user mapping
916 (void)map_username(user);
919 * Do any UNIX username case mangling.
921 smb_getpwnam(user, True);
923 add_session_user(user);
926 * Check with orig_user for security=server and
930 if (!guest && !check_server_security(orig_user, domain, user,
931 smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
932 !check_domain_security(orig_user, domain, user, smb_apasswd,
933 smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
934 !check_hosts_equiv(user))
937 * If we get here then the user wasn't guest and the remote
938 * authentication methods failed. Check the authentication
939 * methods on this local server.
941 * If an NT password was supplied try and validate with that
942 * first. This is superior as the passwords are mixed case
943 * 128 length unicode.
948 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen))
949 DEBUG(2,("NT Password did not match for user '%s'!\n", user));
951 valid_nt_password = True;
955 /* check the LanMan password only if necessary and if allowed
956 by lp_lanman_auth() */
957 if (!valid_nt_password && lp_lanman_auth())
959 DEBUG(2,("Defaulting to Lanman password for %s\n", user));
960 valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen);
964 /* The true branch will be executed if
965 (1) the NT password failed (or was not tried), and
966 (2) LanMan authentication failed (or was disabled)
968 if (!valid_nt_password && !valid_lm_password)
970 if (lp_security() >= SEC_USER)
972 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
974 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
975 END_PROFILE(SMBsesssetupX);
976 return bad_password_error(inbuf,outbuf);
979 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
981 if (smb_getpwnam(user,True))
983 DEBUG(1,("Rejecting user '%s': bad password\n", user));
984 END_PROFILE(SMBsesssetupX);
985 return bad_password_error(inbuf,outbuf);
990 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
991 * Then always map to guest account - as done below.
995 if (*smb_apasswd || !smb_getpwnam(user,True))
996 pstrcpy(user,lp_guestaccount(-1));
997 DEBUG(3,("Registered username %s for guest access\n",user));
1002 if (!smb_getpwnam(user,True)) {
1003 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
1004 pstrcpy(user,lp_guestaccount(-1));
1008 if (!strequal(user,lp_guestaccount(-1)) &&
1009 lp_servicenumber(user) < 0)
1011 add_home_service(user,get_user_home_dir(user));
1015 /* it's ok - setup a reply */
1016 if (Protocol < PROTOCOL_NT1) {
1017 set_message(outbuf,3,0,True);
1020 set_message(outbuf,3,0,True);
1021 p = smb_buf(outbuf);
1022 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
1023 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
1024 p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE);
1025 set_message_end(outbuf,p);
1026 /* perhaps grab OS version here?? */
1029 /* Set the correct uid in the outgoing and incoming packets
1030 We will use this on future requests to determine which
1031 user we should become.
1034 const struct passwd *pw = smb_getpwnam(user,False);
1036 DEBUG(1,("Username %s is invalid on this system\n",user));
1037 END_PROFILE(SMBsesssetupX);
1038 return bad_password_error(inbuf,outbuf);
1045 SSVAL(outbuf,smb_vwv2,1);
1047 /* register the name and uid as being validated, so further connections
1048 to a uid can get through without a password, on the same VC */
1050 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest);
1052 if (sess_vuid == -1) {
1053 return(ERROR(ERRDOS,ERRnoaccess));
1057 SSVAL(outbuf,smb_uid,sess_vuid);
1058 SSVAL(inbuf,smb_uid,sess_vuid);
1060 if (!done_sesssetup)
1061 max_send = MIN(max_send,smb_bufsize);
1063 DEBUG(6,("Client requested max send size of %d\n", max_send));
1065 done_sesssetup = True;
1067 END_PROFILE(SMBsesssetupX);
1068 return chain_reply(inbuf,outbuf,length,bufsize);
1071 /****************************************************************************
1073 ****************************************************************************/
1074 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1080 BOOL bad_path = False;
1081 SMB_STRUCT_STAT sbuf;
1082 START_PROFILE(SMBchkpth);
1084 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1086 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1088 unix_convert(name,conn,0,&bad_path,&sbuf);
1090 mode = SVAL(inbuf,smb_vwv0);
1092 if (check_name(name,conn)) {
1093 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
1094 ok = S_ISDIR(sbuf.st_mode);
1099 /* We special case this - as when a Windows machine
1100 is parsing a path is steps through the components
1101 one at a time - if a component fails it expects
1102 ERRbadpath, not ERRbadfile.
1106 unix_ERR_class = ERRDOS;
1107 unix_ERR_code = ERRbadpath;
1111 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1112 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1113 (get_remote_arch() == RA_WINNT))
1115 unix_ERR_class = ERRDOS;
1116 unix_ERR_code = ERRbaddirectory;
1120 return(UNIXERROR(ERRDOS,ERRbadpath));
1123 outsize = set_message(outbuf,0,0,True);
1125 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1127 END_PROFILE(SMBchkpth);
1132 /****************************************************************************
1134 ****************************************************************************/
1135 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1139 SMB_STRUCT_STAT sbuf;
1144 BOOL bad_path = False;
1146 START_PROFILE(SMBgetatr);
1148 p = smb_buf(inbuf) + 1;
1149 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1151 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1153 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1154 under WfWg - weird! */
1157 mode = aHIDDEN | aDIR;
1158 if (!CAN_WRITE(conn)) mode |= aRONLY;
1165 unix_convert(fname,conn,0,&bad_path,&sbuf);
1166 if (check_name(fname,conn))
1168 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1170 mode = dos_mode(conn,fname,&sbuf);
1171 size = sbuf.st_size;
1172 mtime = sbuf.st_mtime;
1178 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1184 if((errno == ENOENT) && bad_path)
1186 unix_ERR_class = ERRDOS;
1187 unix_ERR_code = ERRbadpath;
1190 END_PROFILE(SMBgetatr);
1191 return(UNIXERROR(ERRDOS,ERRbadfile));
1194 outsize = set_message(outbuf,10,0,True);
1196 SSVAL(outbuf,smb_vwv0,mode);
1197 if(lp_dos_filetime_resolution(SNUM(conn)) )
1198 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1200 put_dos_date3(outbuf,smb_vwv1,mtime);
1201 SIVAL(outbuf,smb_vwv3,(uint32)size);
1203 if (Protocol >= PROTOCOL_NT1) {
1204 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1207 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1209 END_PROFILE(SMBgetatr);
1214 /****************************************************************************
1216 ****************************************************************************/
1217 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1224 SMB_STRUCT_STAT sbuf;
1225 BOOL bad_path = False;
1228 START_PROFILE(SMBsetatr);
1230 p = smb_buf(inbuf) + 1;
1231 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1232 unix_convert(fname,conn,0,&bad_path,&sbuf);
1234 mode = SVAL(inbuf,smb_vwv0);
1235 mtime = make_unix_date3(inbuf+smb_vwv1);
1237 if (VALID_STAT_OF_DIR(sbuf))
1239 if (check_name(fname,conn))
1240 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1242 ok = set_filetime(conn,fname,mtime);
1246 if((errno == ENOENT) && bad_path)
1248 unix_ERR_class = ERRDOS;
1249 unix_ERR_code = ERRbadpath;
1252 END_PROFILE(SMBsetatr);
1253 return(UNIXERROR(ERRDOS,ERRnoaccess));
1256 outsize = set_message(outbuf,0,0,True);
1258 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1260 END_PROFILE(SMBsetatr);
1265 /****************************************************************************
1267 ****************************************************************************/
1268 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1271 SMB_BIG_UINT dfree,dsize,bsize;
1272 START_PROFILE(SMBdskattr);
1274 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1276 outsize = set_message(outbuf,5,0,True);
1278 SSVAL(outbuf,smb_vwv0,dsize);
1279 SSVAL(outbuf,smb_vwv1,bsize/512);
1280 SSVAL(outbuf,smb_vwv2,512);
1281 SSVAL(outbuf,smb_vwv3,dfree);
1283 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1285 END_PROFILE(SMBdskattr);
1290 /****************************************************************************
1292 Can be called from SMBsearch, SMBffirst or SMBfunique.
1293 ****************************************************************************/
1294 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1305 BOOL finished = False;
1314 BOOL check_descend = False;
1315 BOOL expect_close = False;
1316 BOOL can_open = True;
1317 BOOL bad_path = False;
1318 START_PROFILE(SMBsearch);
1320 *mask = *directory = *fname = 0;
1322 /* If we were called as SMBffirst then we must expect close. */
1323 if(CVAL(inbuf,smb_com) == SMBffirst)
1324 expect_close = True;
1326 outsize = set_message(outbuf,1,3,True);
1327 maxentries = SVAL(inbuf,smb_vwv0);
1328 dirtype = SVAL(inbuf,smb_vwv1);
1329 p = smb_buf(inbuf) + 1;
1330 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1332 status_len = SVAL(p, 0);
1335 /* dirtype &= ~aDIR; */
1337 if (status_len == 0)
1339 SMB_STRUCT_STAT sbuf;
1342 pstrcpy(directory,path);
1344 unix_convert(directory,conn,0,&bad_path,&sbuf);
1347 if (!check_name(directory,conn))
1350 p = strrchr_m(dir2,'/');
1362 p = strrchr_m(directory,'/');
1368 if (strlen(directory) == 0)
1369 pstrcpy(directory,"./");
1370 memset((char *)status,'\0',21);
1371 CVAL(status,0) = dirtype;
1375 memcpy(status,p,21);
1376 dirtype = CVAL(status,0) & 0x1F;
1377 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1380 string_set(&conn->dirpath,dptr_path(dptr_num));
1381 fstrcpy(mask, dptr_wcard(dptr_num));
1386 p = smb_buf(outbuf) + 3;
1390 if (status_len == 0)
1392 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1397 if((errno == ENOENT) && bad_path)
1399 unix_ERR_class = ERRDOS;
1400 unix_ERR_code = ERRbadpath;
1402 END_PROFILE(SMBsearch);
1403 return (UNIXERROR(ERRDOS,ERRnofids));
1405 END_PROFILE(SMBsearch);
1406 return(ERROR(ERRDOS,ERRnofids));
1408 dptr_set_wcard(dptr_num, strdup(mask));
1411 DEBUG(4,("dptr_num is %d\n",dptr_num));
1415 if ((dirtype&0x1F) == aVOLID)
1417 memcpy(p,status,21);
1418 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1419 dptr_fill(p+12,dptr_num);
1420 if (dptr_zero(p+12) && (status_len==0))
1424 p += DIR_STRUCT_SIZE;
1428 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1429 conn->dirpath,lp_dontdescend(SNUM(conn))));
1430 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1431 check_descend = True;
1433 for (i=numentries;(i<maxentries) && !finished;i++)
1436 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1439 memcpy(p,status,21);
1440 make_dir_struct(p,mask,fname,size,mode,date);
1441 dptr_fill(p+12,dptr_num);
1444 p += DIR_STRUCT_SIZE;
1453 if (numentries == 0 || !ok)
1455 CVAL(outbuf,smb_rcls) = ERRDOS;
1456 SSVAL(outbuf,smb_err,ERRnofiles);
1457 dptr_close(&dptr_num);
1460 /* If we were called as SMBffirst with smb_search_id == NULL
1461 and no entries were found then return error and close dirptr
1464 if(ok && expect_close && numentries == 0 && status_len == 0)
1466 CVAL(outbuf,smb_rcls) = ERRDOS;
1467 SSVAL(outbuf,smb_err,ERRnofiles);
1468 /* Also close the dptr - we know it's gone */
1469 dptr_close(&dptr_num);
1472 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1473 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1474 dptr_close(&dptr_num);
1476 SSVAL(outbuf,smb_vwv0,numentries);
1477 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1478 CVAL(smb_buf(outbuf),0) = 5;
1479 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1481 if (Protocol >= PROTOCOL_NT1) {
1482 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1485 outsize += DIR_STRUCT_SIZE*numentries;
1486 smb_setlen(outbuf,outsize - 4);
1488 if ((! *directory) && dptr_path(dptr_num))
1489 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1491 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1492 smb_fn_name(CVAL(inbuf,smb_com)),
1493 mask, directory, dirtype, numentries, maxentries ) );
1495 END_PROFILE(SMBsearch);
1500 /****************************************************************************
1501 reply to a fclose (stop directory search)
1502 ****************************************************************************/
1503 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1512 START_PROFILE(SMBfclose);
1514 outsize = set_message(outbuf,1,0,True);
1515 p = smb_buf(inbuf) + 1;
1516 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1518 status_len = SVAL(p,0);
1521 if (status_len == 0) {
1522 END_PROFILE(SMBfclose);
1523 return(ERROR(ERRSRV,ERRsrverror));
1526 memcpy(status,p,21);
1528 if(dptr_fetch(status+12,&dptr_num)) {
1529 /* Close the dptr - we know it's gone */
1530 dptr_close(&dptr_num);
1533 SSVAL(outbuf,smb_vwv0,0);
1535 DEBUG(3,("search close\n"));
1537 END_PROFILE(SMBfclose);
1542 /****************************************************************************
1544 ****************************************************************************/
1546 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1556 SMB_STRUCT_STAT sbuf;
1557 BOOL bad_path = False;
1559 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1560 START_PROFILE(SMBopen);
1562 share_mode = SVAL(inbuf,smb_vwv0);
1564 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1566 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1568 unix_convert(fname,conn,0,&bad_path,&sbuf);
1570 unixmode = unix_mode(conn,aARCH,fname);
1572 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1573 unixmode, oplock_request,&rmode,NULL);
1577 if((errno == ENOENT) && bad_path)
1579 unix_ERR_class = ERRDOS;
1580 unix_ERR_code = ERRbadpath;
1582 END_PROFILE(SMBopen);
1583 return(UNIXERROR(ERRDOS,ERRnoaccess));
1586 size = sbuf.st_size;
1587 fmode = dos_mode(conn,fname,&sbuf);
1588 mtime = sbuf.st_mtime;
1591 DEBUG(3,("attempt to open a directory %s\n",fname));
1592 close_file(fsp,False);
1593 END_PROFILE(SMBopen);
1594 return(ERROR(ERRDOS,ERRnoaccess));
1597 outsize = set_message(outbuf,7,0,True);
1598 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1599 SSVAL(outbuf,smb_vwv1,fmode);
1600 if(lp_dos_filetime_resolution(SNUM(conn)) )
1601 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1603 put_dos_date3(outbuf,smb_vwv2,mtime);
1604 SIVAL(outbuf,smb_vwv4,(uint32)size);
1605 SSVAL(outbuf,smb_vwv6,rmode);
1607 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1608 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1611 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1612 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1613 END_PROFILE(SMBopen);
1618 /****************************************************************************
1619 reply to an open and X
1620 ****************************************************************************/
1621 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1624 int smb_mode = SVAL(inbuf,smb_vwv3);
1625 int smb_attr = SVAL(inbuf,smb_vwv5);
1626 /* Breakout the oplock request bits so we can set the
1627 reply bits separately. */
1628 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1629 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1630 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1632 int open_flags = SVAL(inbuf,smb_vwv2);
1633 int smb_sattr = SVAL(inbuf,smb_vwv4);
1634 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1636 int smb_ofun = SVAL(inbuf,smb_vwv8);
1639 int fmode=0,mtime=0,rmode=0;
1640 SMB_STRUCT_STAT sbuf;
1642 BOOL bad_path = False;
1644 START_PROFILE(SMBopenX);
1646 /* If it's an IPC, pass off the pipe handler. */
1648 if (lp_nt_pipe_support()) {
1649 END_PROFILE(SMBopenX);
1650 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1652 END_PROFILE(SMBopenX);
1653 return (ERROR(ERRSRV,ERRaccess));
1657 /* XXXX we need to handle passed times, sattr and flags */
1658 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1660 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1662 unix_convert(fname,conn,0,&bad_path,&sbuf);
1664 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1666 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1667 oplock_request, &rmode,&smb_action);
1671 if((errno == ENOENT) && bad_path)
1673 unix_ERR_class = ERRDOS;
1674 unix_ERR_code = ERRbadpath;
1676 END_PROFILE(SMBopenX);
1677 return(UNIXERROR(ERRDOS,ERRnoaccess));
1680 size = sbuf.st_size;
1681 fmode = dos_mode(conn,fname,&sbuf);
1682 mtime = sbuf.st_mtime;
1684 close_file(fsp,False);
1685 END_PROFILE(SMBopenX);
1686 return(ERROR(ERRDOS,ERRnoaccess));
1689 /* If the caller set the extended oplock request bit
1690 and we granted one (by whatever means) - set the
1691 correct bit for extended oplock reply.
1694 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1695 smb_action |= EXTENDED_OPLOCK_GRANTED;
1698 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1699 smb_action |= EXTENDED_OPLOCK_GRANTED;
1702 /* If the caller set the core oplock request bit
1703 and we granted one (by whatever means) - set the
1704 correct bit for core oplock reply.
1707 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1708 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1711 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1712 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1715 set_message(outbuf,15,0,True);
1716 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1717 SSVAL(outbuf,smb_vwv3,fmode);
1718 if(lp_dos_filetime_resolution(SNUM(conn)) )
1719 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1721 put_dos_date3(outbuf,smb_vwv4,mtime);
1722 SIVAL(outbuf,smb_vwv6,(uint32)size);
1723 SSVAL(outbuf,smb_vwv8,rmode);
1724 SSVAL(outbuf,smb_vwv11,smb_action);
1726 END_PROFILE(SMBopenX);
1727 return chain_reply(inbuf,outbuf,length,bufsize);
1731 /****************************************************************************
1732 reply to a SMBulogoffX
1733 ****************************************************************************/
1734 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1736 uint16 vuid = SVAL(inbuf,smb_uid);
1737 user_struct *vuser = get_valid_user_struct(vuid);
1738 START_PROFILE(SMBulogoffX);
1741 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1744 /* in user level security we are supposed to close any files
1745 open by this user */
1746 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1747 file_close_user(vuid);
1750 invalidate_vuid(vuid);
1752 set_message(outbuf,2,0,True);
1754 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1756 END_PROFILE(SMBulogoffX);
1757 return chain_reply(inbuf,outbuf,length,bufsize);
1761 /****************************************************************************
1762 reply to a mknew or a create
1763 ****************************************************************************/
1764 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1772 BOOL bad_path = False;
1774 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1775 SMB_STRUCT_STAT sbuf;
1776 START_PROFILE(SMBcreate);
1778 com = SVAL(inbuf,smb_com);
1780 createmode = SVAL(inbuf,smb_vwv0);
1781 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1783 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1785 unix_convert(fname,conn,0,&bad_path,&sbuf);
1787 if (createmode & aVOLID) {
1788 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1791 unixmode = unix_mode(conn,createmode,fname);
1795 /* We should fail if file exists. */
1796 ofun = FILE_CREATE_IF_NOT_EXIST;
1800 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1801 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1804 /* Open file in dos compatibility share mode. */
1805 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1806 ofun, unixmode, oplock_request, NULL, NULL);
1810 if((errno == ENOENT) && bad_path)
1812 unix_ERR_class = ERRDOS;
1813 unix_ERR_code = ERRbadpath;
1815 END_PROFILE(SMBcreate);
1816 return(UNIXERROR(ERRDOS,ERRnoaccess));
1819 outsize = set_message(outbuf,1,0,True);
1820 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1822 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1823 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1826 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1827 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1829 DEBUG( 2, ( "new file %s\n", fname ) );
1830 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1831 fname, fsp->fd, createmode, (int)unixmode ) );
1833 END_PROFILE(SMBcreate);
1838 /****************************************************************************
1839 reply to a create temporary file
1840 ****************************************************************************/
1841 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1847 BOOL bad_path = False;
1849 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1851 SMB_STRUCT_STAT sbuf;
1854 START_PROFILE(SMBctemp);
1856 createmode = SVAL(inbuf,smb_vwv0);
1857 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1858 pstrcat(fname,"/TMXXXXXX");
1860 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1862 unix_convert(fname,conn,0,&bad_path,&sbuf);
1864 unixmode = unix_mode(conn,createmode,fname);
1866 tmpfd = smb_mkstemp(fname);
1868 END_PROFILE(SMBctemp);
1869 return(UNIXERROR(ERRDOS,ERRnoaccess));
1872 vfs_stat(conn,fname,&sbuf);
1874 /* Open file in dos compatibility share mode. */
1875 /* We should fail if file does not exist. */
1876 fsp = open_file_shared(conn,fname,&sbuf,
1877 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1878 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1879 unixmode, oplock_request, NULL, NULL);
1881 /* close fd from smb_mkstemp() */
1886 if((errno == ENOENT) && bad_path)
1888 unix_ERR_class = ERRDOS;
1889 unix_ERR_code = ERRbadpath;
1891 END_PROFILE(SMBctemp);
1892 return(UNIXERROR(ERRDOS,ERRnoaccess));
1895 outsize = set_message(outbuf,1,0,True);
1896 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1897 CVAL(smb_buf(outbuf),0) = 4;
1898 p = smb_buf(outbuf) + 1;
1899 p += srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1900 set_message_end(outbuf, p);
1902 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1903 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1906 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1907 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1909 DEBUG( 2, ( "created temp file %s\n", fname ) );
1910 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1911 fname, fsp->fd, createmode, (int)unixmode ) );
1913 END_PROFILE(SMBctemp);
1918 /*******************************************************************
1919 check if a user is allowed to delete a file
1920 ********************************************************************/
1921 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1923 SMB_STRUCT_STAT sbuf;
1926 if (!CAN_WRITE(conn)) return(False);
1928 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
1929 fmode = dos_mode(conn,fname,&sbuf);
1930 if (fmode & aDIR) return(False);
1931 if (!lp_delete_readonly(SNUM(conn))) {
1932 if (fmode & aRONLY) return(False);
1934 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1936 if (!check_file_sharing(conn,fname,False)) return(False);
1940 /****************************************************************************
1941 The guts of the unlink command, split out so it may be called by the NT SMB
1943 ****************************************************************************/
1945 int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
1946 int dirtype, char *name)
1952 int error = ERRnoaccess;
1955 BOOL bad_path = False;
1957 SMB_STRUCT_STAT sbuf;
1959 *directory = *mask = 0;
1961 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1963 p = strrchr_m(name,'/');
1965 pstrcpy(directory,"./");
1969 pstrcpy(directory,name);
1974 * We should only check the mangled cache
1975 * here if unix_convert failed. This means
1976 * that the path in 'mask' doesn't exist
1977 * on the file system and so we need to look
1978 * for a possible mangle. This patch from
1979 * Tine Smukavec <valentin.smukavec@hermes.si>.
1982 if (!rc && is_mangled(mask))
1983 check_mangled_cache( mask );
1985 has_wild = ms_has_wild(mask);
1988 pstrcat(directory,"/");
1989 pstrcat(directory,mask);
1990 if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory))
1993 exists = vfs_file_exist(conn,directory,&sbuf);
1995 void *dirptr = NULL;
1998 if (check_name(directory,conn))
1999 dirptr = OpenDir(conn, directory, True);
2001 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2002 the pattern matches against the long name, otherwise the short name
2003 We don't implement this yet XXXX
2010 if (strequal(mask,"????????.???"))
2013 while ((dname = ReadDirName(dirptr)))
2016 pstrcpy(fname,dname);
2018 if(!mask_match(fname, mask, case_sensitive)) continue;
2020 error = ERRnoaccess;
2021 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2022 if (!can_delete(fname,conn,dirtype)) continue;
2023 if (!vfs_unlink(conn,fname)) count++;
2024 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2032 return(ERROR(ERRDOS,error));
2034 if((errno == ENOENT) && bad_path) {
2035 unix_ERR_class = ERRDOS;
2036 unix_ERR_code = ERRbadpath;
2038 return(UNIXERROR(ERRDOS,error));
2045 /****************************************************************************
2047 ****************************************************************************/
2049 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2054 START_PROFILE(SMBunlink);
2056 dirtype = SVAL(inbuf,smb_vwv0);
2058 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
2060 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
2062 DEBUG(3,("reply_unlink : %s\n",name));
2064 outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
2068 * Win2k needs a changenotify request response before it will
2069 * update after a rename..
2072 process_pending_change_notify_queue((time_t)0);
2074 outsize = set_message(outbuf,0,0,True);
2077 END_PROFILE(SMBunlink);
2082 /****************************************************************************
2083 reply to a readbraw (core+ protocol)
2084 ****************************************************************************/
2086 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2088 size_t maxcount,mincount;
2091 char *header = outbuf;
2094 START_PROFILE(SMBreadbraw);
2097 * Special check if an oplock break has been issued
2098 * and the readraw request croses on the wire, we must
2099 * return a zero length response here.
2102 if(global_oplock_break)
2104 _smb_setlen(header,0);
2105 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2106 DEBUG(5,("readbraw - oplock break finished\n"));
2107 END_PROFILE(SMBreadbraw);
2111 fsp = file_fsp(inbuf,smb_vwv0);
2113 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2115 * fsp could be NULL here so use the value from the packet. JRA.
2117 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2118 _smb_setlen(header,0);
2119 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2120 END_PROFILE(SMBreadbraw);
2124 CHECK_FSP(fsp,conn);
2126 flush_write_cache(fsp, READRAW_FLUSH);
2128 startpos = IVAL(inbuf,smb_vwv1);
2129 if(CVAL(inbuf,smb_wct) == 10) {
2131 * This is a large offset (64 bit) read.
2133 #ifdef LARGE_SMB_OFF_T
2135 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2137 #else /* !LARGE_SMB_OFF_T */
2140 * Ensure we haven't been sent a >32 bit offset.
2143 if(IVAL(inbuf,smb_vwv8) != 0) {
2144 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2145 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2146 _smb_setlen(header,0);
2147 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2148 END_PROFILE(SMBreadbraw);
2152 #endif /* LARGE_SMB_OFF_T */
2155 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2156 (double)startpos ));
2157 _smb_setlen(header,0);
2158 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2159 END_PROFILE(SMBreadbraw);
2163 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2164 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2166 /* ensure we don't overrun the packet size */
2167 maxcount = MIN(65535,maxcount);
2168 maxcount = MAX(mincount,maxcount);
2170 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False))
2172 SMB_OFF_T size = fsp->size;
2173 SMB_OFF_T sizeneeded = startpos + maxcount;
2175 if (size < sizeneeded)
2178 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2180 if (!fsp->can_write)
2184 nread = MIN(maxcount,(size - startpos));
2187 if (nread < mincount)
2190 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2191 fsp->fnum, (double)startpos,
2192 (int)maxcount, (int)mincount, (int)nread ) );
2196 BOOL seek_fail = False;
2198 _smb_setlen(header,nread);
2200 if ((nread-predict) > 0) {
2201 if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
2202 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2209 ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
2210 (SMB_OFF_T)(nread-predict),header,4+predict,
2215 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2216 fsp->fsp_name,startpos,nread,ret));
2218 #else /* UNSAFE_READRAW */
2219 ret = read_file(fsp,header+4,startpos,nread);
2220 if (ret < mincount) ret = 0;
2222 _smb_setlen(header,ret);
2223 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2224 #endif /* UNSAFE_READRAW */
2226 DEBUG(5,("readbraw finished\n"));
2227 END_PROFILE(SMBreadbraw);
2232 /****************************************************************************
2233 reply to a lockread (core+ protocol)
2234 ****************************************************************************/
2235 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2244 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2245 START_PROFILE(SMBlockread);
2247 CHECK_FSP(fsp,conn);
2251 release_level_2_oplocks_on_change(fsp);
2253 numtoread = SVAL(inbuf,smb_vwv1);
2254 startpos = IVAL(inbuf,smb_vwv2);
2256 outsize = set_message(outbuf,5,3,True);
2257 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2258 data = smb_buf(outbuf) + 3;
2261 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2262 * protocol request that predates the read/write lock concept.
2263 * Thus instead of asking for a read lock here we need to ask
2264 * for a write lock. JRA.
2267 if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2268 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2270 * A blocking lock was requested. Package up
2271 * this smb into a queued request and push it
2272 * onto the blocking lock queue.
2274 if(push_blocking_lock_request(inbuf, length, -1, 0))
2275 END_PROFILE(SMBlockread);
2278 END_PROFILE(SMBlockread);
2279 return (ERROR(eclass,ecode));
2282 nread = read_file(fsp,data,startpos,numtoread);
2285 END_PROFILE(SMBlockread);
2286 return(UNIXERROR(ERRDOS,ERRnoaccess));
2290 SSVAL(outbuf,smb_vwv0,nread);
2291 SSVAL(outbuf,smb_vwv5,nread+3);
2292 SSVAL(smb_buf(outbuf),1,nread);
2294 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2295 fsp->fnum, (int)numtoread, (int)nread ) );
2297 END_PROFILE(SMBlockread);
2302 /****************************************************************************
2304 ****************************************************************************/
2306 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2313 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2314 START_PROFILE(SMBread);
2316 CHECK_FSP(fsp,conn);
2320 numtoread = SVAL(inbuf,smb_vwv1);
2321 startpos = IVAL(inbuf,smb_vwv2);
2323 outsize = set_message(outbuf,5,3,True);
2324 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2325 data = smb_buf(outbuf) + 3;
2327 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2328 END_PROFILE(SMBread);
2329 return(ERROR(ERRDOS,ERRlock));
2333 nread = read_file(fsp,data,startpos,numtoread);
2336 END_PROFILE(SMBread);
2337 return(UNIXERROR(ERRDOS,ERRnoaccess));
2341 SSVAL(outbuf,smb_vwv0,nread);
2342 SSVAL(outbuf,smb_vwv5,nread+3);
2343 CVAL(smb_buf(outbuf),0) = 1;
2344 SSVAL(smb_buf(outbuf),1,nread);
2346 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2347 fsp->fnum, (int)numtoread, (int)nread ) );
2349 END_PROFILE(SMBread);
2354 /****************************************************************************
2355 reply to a read and X
2356 ****************************************************************************/
2357 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2359 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2360 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2361 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2362 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2365 START_PROFILE(SMBreadX);
2367 /* If it's an IPC, pass off the pipe handler. */
2369 END_PROFILE(SMBreadX);
2370 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2373 CHECK_FSP(fsp,conn);
2377 set_message(outbuf,12,0,True);
2378 data = smb_buf(outbuf);
2380 if(CVAL(inbuf,smb_wct) == 12) {
2381 #ifdef LARGE_SMB_OFF_T
2383 * This is a large offset (64 bit) read.
2385 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2387 #else /* !LARGE_SMB_OFF_T */
2390 * Ensure we haven't been sent a >32 bit offset.
2393 if(IVAL(inbuf,smb_vwv10) != 0) {
2394 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2395 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2396 END_PROFILE(SMBreadX);
2397 return(ERROR(ERRDOS,ERRbadaccess));
2400 #endif /* LARGE_SMB_OFF_T */
2404 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2405 END_PROFILE(SMBreadX);
2406 return(ERROR(ERRDOS,ERRlock));
2408 nread = read_file(fsp,data,startpos,smb_maxcnt);
2411 END_PROFILE(SMBreadX);
2412 return(UNIXERROR(ERRDOS,ERRnoaccess));
2415 SSVAL(outbuf,smb_vwv5,nread);
2416 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2417 SSVAL(smb_buf(outbuf),-2,nread);
2419 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2420 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2422 END_PROFILE(SMBreadX);
2423 return chain_reply(inbuf,outbuf,length,bufsize);
2426 /****************************************************************************
2427 reply to a writebraw (core+ or LANMAN1.0 protocol)
2428 ****************************************************************************/
2430 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2433 ssize_t total_written=0;
2434 size_t numtowrite=0;
2439 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2441 START_PROFILE(SMBwritebraw);
2443 CHECK_FSP(fsp,conn);
2447 tcount = IVAL(inbuf,smb_vwv1);
2448 startpos = IVAL(inbuf,smb_vwv3);
2449 write_through = BITSETW(inbuf+smb_vwv7,0);
2451 /* We have to deal with slightly different formats depending
2452 on whether we are using the core+ or lanman1.0 protocol */
2453 if(Protocol <= PROTOCOL_COREPLUS) {
2454 numtowrite = SVAL(smb_buf(inbuf),-2);
2455 data = smb_buf(inbuf);
2457 numtowrite = SVAL(inbuf,smb_vwv10);
2458 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2461 /* force the error type */
2462 CVAL(inbuf,smb_com) = SMBwritec;
2463 CVAL(outbuf,smb_com) = SMBwritec;
2465 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2466 END_PROFILE(SMBwritebraw);
2467 return(ERROR(ERRDOS,ERRlock));
2471 nwritten = write_file(fsp,data,startpos,numtowrite);
2473 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2474 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2476 if (nwritten < numtowrite) {
2477 END_PROFILE(SMBwritebraw);
2478 return(UNIXERROR(ERRHRD,ERRdiskfull));
2481 total_written = nwritten;
2483 /* Return a message to the redirector to tell it
2484 to send more bytes */
2485 CVAL(outbuf,smb_com) = SMBwritebraw;
2486 SSVALS(outbuf,smb_vwv0,-1);
2487 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2488 if (!send_smb(smbd_server_fd(),outbuf))
2489 exit_server("reply_writebraw: send_smb failed.\n");
2491 /* Now read the raw data into the buffer and write it */
2492 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2493 exit_server("secondary writebraw failed");
2496 /* Even though this is not an smb message, smb_len
2497 returns the generic length of an smb message */
2498 numtowrite = smb_len(inbuf);
2500 if (tcount > nwritten+numtowrite) {
2501 DEBUG(3,("Client overestimated the write %d %d %d\n",
2502 (int)tcount,(int)nwritten,(int)numtowrite));
2505 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2506 (SMB_OFF_T)numtowrite,NULL,0,
2508 total_written += nwritten;
2510 /* Set up outbuf to return the correct return */
2511 outsize = set_message(outbuf,1,0,True);
2512 CVAL(outbuf,smb_com) = SMBwritec;
2513 SSVAL(outbuf,smb_vwv0,total_written);
2515 if (nwritten < (ssize_t)numtowrite) {
2516 CVAL(outbuf,smb_rcls) = ERRHRD;
2517 SSVAL(outbuf,smb_err,ERRdiskfull);
2520 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2521 lp_strict_sync(SNUM(conn)))
2522 sync_file(conn,fsp);
2524 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2525 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2527 /* we won't return a status if write through is not selected - this
2528 follows what WfWg does */
2529 END_PROFILE(SMBwritebraw);
2530 if (!write_through && total_written==tcount) {
2532 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2533 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2535 if (!send_keepalive(smbd_server_fd()))
2536 exit_server("reply_writebraw: send of keepalive failed");
2543 /****************************************************************************
2544 reply to a writeunlock (core+)
2545 ****************************************************************************/
2547 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2549 ssize_t nwritten = -1;
2555 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2557 START_PROFILE(SMBwriteunlock);
2559 CHECK_FSP(fsp,conn);
2563 numtowrite = SVAL(inbuf,smb_vwv1);
2564 startpos = IVAL(inbuf,smb_vwv2);
2565 data = smb_buf(inbuf) + 3;
2567 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2568 END_PROFILE(SMBwriteunlock);
2569 return(ERROR(ERRDOS,ERRlock));
2572 /* The special X/Open SMB protocol handling of
2573 zero length writes is *NOT* done for
2578 nwritten = write_file(fsp,data,startpos,numtowrite);
2580 if (lp_syncalways(SNUM(conn)))
2581 sync_file(conn,fsp);
2583 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2584 END_PROFILE(SMBwriteunlock);
2585 return(UNIXERROR(ERRDOS,ERRnoaccess));
2588 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) {
2589 END_PROFILE(SMBwriteunlock);
2590 return(ERROR(eclass,ecode));
2593 outsize = set_message(outbuf,1,0,True);
2595 SSVAL(outbuf,smb_vwv0,nwritten);
2597 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2598 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2600 END_PROFILE(SMBwriteunlock);
2604 /****************************************************************************
2606 ****************************************************************************/
2607 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2610 ssize_t nwritten = -1;
2613 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2615 START_PROFILE(SMBwrite);
2617 /* If it's an IPC, pass off the pipe handler. */
2619 END_PROFILE(SMBwrite);
2620 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2623 CHECK_FSP(fsp,conn);
2627 numtowrite = SVAL(inbuf,smb_vwv1);
2628 startpos = IVAL(inbuf,smb_vwv2);
2629 data = smb_buf(inbuf) + 3;
2631 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2632 END_PROFILE(SMBwrite);
2633 return(ERROR(ERRDOS,ERRlock));
2636 /* X/Open SMB protocol says that if smb_vwv1 is
2637 zero then the file size should be extended or
2638 truncated to the size given in smb_vwv[2-3] */
2639 if(numtowrite == 0) {
2640 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2642 nwritten = write_file(fsp,data,startpos,numtowrite);
2644 if (lp_syncalways(SNUM(conn)))
2645 sync_file(conn,fsp);
2647 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2648 END_PROFILE(SMBwrite);
2649 return(UNIXERROR(ERRDOS,ERRnoaccess));
2652 outsize = set_message(outbuf,1,0,True);
2654 SSVAL(outbuf,smb_vwv0,nwritten);
2656 if (nwritten < (ssize_t)numtowrite) {
2657 CVAL(outbuf,smb_rcls) = ERRHRD;
2658 SSVAL(outbuf,smb_err,ERRdiskfull);
2661 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2662 fsp->fnum, (int)numtowrite, (int)nwritten));
2664 END_PROFILE(SMBwrite);
2669 /****************************************************************************
2670 reply to a write and X
2671 ****************************************************************************/
2672 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2674 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2675 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2676 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2677 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2678 ssize_t nwritten = -1;
2679 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2680 unsigned int smblen = smb_len(inbuf);
2682 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2683 START_PROFILE(SMBwriteX);
2685 /* If it's an IPC, pass off the pipe handler. */
2687 END_PROFILE(SMBwriteX);
2688 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2691 CHECK_FSP(fsp,conn);
2695 /* Deal with possible LARGE_WRITEX */
2697 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2699 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2700 END_PROFILE(SMBwriteX);
2701 return(ERROR(ERRDOS,ERRbadmem));
2704 data = smb_base(inbuf) + smb_doff;
2706 if(CVAL(inbuf,smb_wct) == 14) {
2707 #ifdef LARGE_SMB_OFF_T
2709 * This is a large offset (64 bit) write.
2711 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2713 #else /* !LARGE_SMB_OFF_T */
2716 * Ensure we haven't been sent a >32 bit offset.
2719 if(IVAL(inbuf,smb_vwv12) != 0) {
2720 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2721 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2722 END_PROFILE(SMBwriteX);
2723 return(ERROR(ERRDOS,ERRbadaccess));
2726 #endif /* LARGE_SMB_OFF_T */
2729 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2730 END_PROFILE(SMBwriteX);
2731 return(ERROR(ERRDOS,ERRlock));
2734 /* X/Open SMB protocol says that, unlike SMBwrite
2735 if the length is zero then NO truncation is
2736 done, just a write of zero. To truncate a file,
2741 nwritten = write_file(fsp,data,startpos,numtowrite);
2743 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2744 END_PROFILE(SMBwriteX);
2745 return(UNIXERROR(ERRDOS,ERRnoaccess));
2748 set_message(outbuf,6,0,True);
2750 SSVAL(outbuf,smb_vwv2,nwritten);
2752 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2754 if (nwritten < (ssize_t)numtowrite) {
2755 CVAL(outbuf,smb_rcls) = ERRHRD;
2756 SSVAL(outbuf,smb_err,ERRdiskfull);
2759 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2760 fsp->fnum, (int)numtowrite, (int)nwritten));
2762 if (lp_syncalways(SNUM(conn)) || write_through)
2763 sync_file(conn,fsp);
2765 END_PROFILE(SMBwriteX);
2766 return chain_reply(inbuf,outbuf,length,bufsize);
2770 /****************************************************************************
2772 ****************************************************************************/
2774 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2780 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2781 START_PROFILE(SMBlseek);
2783 CHECK_FSP(fsp,conn);
2786 flush_write_cache(fsp, SEEK_FLUSH);
2788 mode = SVAL(inbuf,smb_vwv1) & 3;
2789 startpos = IVALS(inbuf,smb_vwv2);
2792 case 0: umode = SEEK_SET; break;
2793 case 1: umode = SEEK_CUR; break;
2794 case 2: umode = SEEK_END; break;
2796 umode = SEEK_SET; break;
2799 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2801 * Check for the special case where a seek before the start
2802 * of the file sets the offset to zero. Added in the CIFS spec,
2806 if(errno == EINVAL) {
2807 SMB_OFF_T current_pos = startpos;
2809 if(umode == SEEK_CUR) {
2811 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2812 END_PROFILE(SMBlseek);
2813 return(UNIXERROR(ERRDOS,ERRnoaccess));
2816 current_pos += startpos;
2818 } else if (umode == SEEK_END) {
2820 SMB_STRUCT_STAT sbuf;
2822 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2823 END_PROFILE(SMBlseek);
2824 return(UNIXERROR(ERRDOS,ERRnoaccess));
2827 current_pos += sbuf.st_size;
2831 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2835 END_PROFILE(SMBlseek);
2836 return(UNIXERROR(ERRDOS,ERRnoaccess));
2842 outsize = set_message(outbuf,2,0,True);
2843 SIVAL(outbuf,smb_vwv0,res);
2845 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2846 fsp->fnum, (double)startpos, (double)res, mode));
2848 END_PROFILE(SMBlseek);
2852 /****************************************************************************
2854 ****************************************************************************/
2856 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2858 int outsize = set_message(outbuf,0,0,True);
2859 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2860 START_PROFILE(SMBflush);
2863 CHECK_FSP(fsp,conn);
2868 file_sync_all(conn);
2870 sync_file(conn,fsp);
2873 DEBUG(3,("flush\n"));
2874 END_PROFILE(SMBflush);
2879 /****************************************************************************
2881 ****************************************************************************/
2882 int reply_exit(connection_struct *conn,
2883 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2886 START_PROFILE(SMBexit);
2887 outsize = set_message(outbuf,0,0,True);
2889 DEBUG(3,("exit\n"));
2891 END_PROFILE(SMBexit);
2896 /****************************************************************************
2897 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2898 ****************************************************************************/
2899 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2904 int32 eclass = 0, err = 0;
2905 files_struct *fsp = NULL;
2906 START_PROFILE(SMBclose);
2908 outsize = set_message(outbuf,0,0,True);
2910 /* If it's an IPC, pass off to the pipe handler. */
2912 END_PROFILE(SMBclose);
2913 return reply_pipe_close(conn, inbuf,outbuf);
2916 fsp = file_fsp(inbuf,smb_vwv0);
2919 * We can only use CHECK_FSP if we know it's not a directory.
2922 if(!fsp || (fsp->conn != conn)) {
2923 END_PROFILE(SMBclose);
2924 return(ERROR(ERRDOS,ERRbadfid));
2927 if(HAS_CACHED_ERROR(fsp)) {
2928 eclass = fsp->wbmpx_ptr->wr_errclass;
2929 err = fsp->wbmpx_ptr->wr_error;
2932 if(fsp->is_directory || fsp->stat_open) {
2934 * Special case - close NT SMB directory or stat file
2937 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2938 close_file(fsp,True);
2941 * Close ordinary file.
2946 * If there was a modify time outstanding,
2947 * try and set it here.
2949 if(fsp->pending_modtime)
2950 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2953 * Now take care of any time sent in the close.
2955 mtime = make_unix_date3(inbuf+smb_vwv1);
2957 /* try and set the date */
2958 set_filetime(conn, fsp->fsp_name,mtime);
2960 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2962 conn->num_files_open));
2965 * close_file() returns the unix errno if an error
2966 * was detected on close - normally this is due to
2967 * a disk full error. If not then it was probably an I/O error.
2970 if((close_err = close_file(fsp,True)) != 0) {
2972 END_PROFILE(SMBclose);
2973 return (UNIXERROR(ERRHRD,ERRgeneral));
2977 /* We have a cached error */
2979 END_PROFILE(SMBclose);
2980 return(ERROR(eclass,err));
2983 END_PROFILE(SMBclose);
2988 /****************************************************************************
2989 reply to a writeclose (Core+ protocol)
2990 ****************************************************************************/
2992 int reply_writeclose(connection_struct *conn,
2993 char *inbuf,char *outbuf, int size, int dum_buffsize)
2996 ssize_t nwritten = -1;
3002 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3003 START_PROFILE(SMBwriteclose);
3005 CHECK_FSP(fsp,conn);
3009 numtowrite = SVAL(inbuf,smb_vwv1);
3010 startpos = IVAL(inbuf,smb_vwv2);
3011 mtime = make_unix_date3(inbuf+smb_vwv4);
3012 data = smb_buf(inbuf) + 1;
3014 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
3015 END_PROFILE(SMBwriteclose);
3016 return(ERROR(ERRDOS,ERRlock));
3019 nwritten = write_file(fsp,data,startpos,numtowrite);
3021 set_filetime(conn, fsp->fsp_name,mtime);
3023 close_err = close_file(fsp,True);
3025 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3026 fsp->fnum, (int)numtowrite, (int)nwritten,
3027 conn->num_files_open));
3029 if (nwritten <= 0) {
3030 END_PROFILE(SMBwriteclose);
3031 return(UNIXERROR(ERRDOS,ERRnoaccess));
3034 if(close_err != 0) {
3036 END_PROFILE(SMBwriteclose);
3037 return(UNIXERROR(ERRHRD,ERRgeneral));
3040 outsize = set_message(outbuf,1,0,True);
3042 SSVAL(outbuf,smb_vwv0,nwritten);
3043 END_PROFILE(SMBwriteclose);
3048 /****************************************************************************
3050 ****************************************************************************/
3051 int reply_lock(connection_struct *conn,
3052 char *inbuf,char *outbuf, int length, int dum_buffsize)
3054 int outsize = set_message(outbuf,0,0,True);
3055 SMB_BIG_UINT count,offset;
3058 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3059 START_PROFILE(SMBlock);
3061 CHECK_FSP(fsp,conn);
3064 release_level_2_oplocks_on_change(fsp);
3066 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3067 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3069 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3070 fsp->fd, fsp->fnum, (double)offset, (double)count));
3072 if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &eclass, &ecode)) {
3073 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
3075 * A blocking lock was requested. Package up
3076 * this smb into a queued request and push it
3077 * onto the blocking lock queue.
3079 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
3080 END_PROFILE(SMBlock);
3084 END_PROFILE(SMBlock);
3085 return (ERROR(eclass,ecode));
3088 END_PROFILE(SMBlock);
3093 /****************************************************************************
3095 ****************************************************************************/
3096 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3098 int outsize = set_message(outbuf,0,0,True);
3099 SMB_BIG_UINT count,offset;
3102 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3103 START_PROFILE(SMBunlock);
3105 CHECK_FSP(fsp,conn);
3108 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3109 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3111 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, &eclass, &ecode)) {
3112 END_PROFILE(SMBunlock);
3113 return (ERROR(eclass,ecode));
3116 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3117 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3119 END_PROFILE(SMBunlock);
3124 /****************************************************************************
3126 ****************************************************************************/
3127 int reply_tdis(connection_struct *conn,
3128 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3130 int outsize = set_message(outbuf,0,0,True);
3132 START_PROFILE(SMBtdis);
3134 vuid = SVAL(inbuf,smb_uid);
3137 DEBUG(4,("Invalid connection in tdis\n"));
3138 END_PROFILE(SMBtdis);
3139 return(ERROR(ERRSRV,ERRinvnid));
3144 close_cnum(conn,vuid);
3146 END_PROFILE(SMBtdis);
3152 /****************************************************************************
3154 ****************************************************************************/
3155 int reply_echo(connection_struct *conn,
3156 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3158 int smb_reverb = SVAL(inbuf,smb_vwv0);
3160 unsigned int data_len = smb_buflen(inbuf);
3161 int outsize = set_message(outbuf,1,data_len,True);
3162 START_PROFILE(SMBecho);
3164 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3166 /* copy any incoming data back out */
3168 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3170 if (smb_reverb > 100) {
3171 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3175 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3176 SSVAL(outbuf,smb_vwv0,seq_num);
3178 smb_setlen(outbuf,outsize - 4);
3180 if (!send_smb(smbd_server_fd(),outbuf))
3181 exit_server("reply_echo: send_smb failed.\n");
3184 DEBUG(3,("echo %d times\n", smb_reverb));
3188 END_PROFILE(SMBecho);
3193 /****************************************************************************
3194 reply to a printopen
3195 ****************************************************************************/
3196 int reply_printopen(connection_struct *conn,
3197 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3201 START_PROFILE(SMBsplopen);
3203 if (!CAN_PRINT(conn)) {
3204 END_PROFILE(SMBsplopen);
3205 return(ERROR(ERRDOS,ERRnoaccess));
3208 /* Open for exclusive use, write only. */
3209 fsp = print_fsp_open(conn);
3212 END_PROFILE(SMBsplopen);
3213 return(UNIXERROR(ERRDOS,ERRnoaccess));
3216 outsize = set_message(outbuf,1,0,True);
3217 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3219 DEBUG(3,("openprint fd=%d fnum=%d\n",
3220 fsp->fd, fsp->fnum));
3222 END_PROFILE(SMBsplopen);
3227 /****************************************************************************
3228 reply to a printclose
3229 ****************************************************************************/
3230 int reply_printclose(connection_struct *conn,
3231 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3233 int outsize = set_message(outbuf,0,0,True);
3234 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3236 START_PROFILE(SMBsplclose);
3238 CHECK_FSP(fsp,conn);
3241 if (!CAN_PRINT(conn)) {
3242 END_PROFILE(SMBsplclose);
3243 return(ERROR(ERRDOS,ERRnoaccess));
3246 DEBUG(3,("printclose fd=%d fnum=%d\n",
3247 fsp->fd,fsp->fnum));
3249 close_err = close_file(fsp,True);
3251 if(close_err != 0) {
3253 END_PROFILE(SMBsplclose);
3254 return(UNIXERROR(ERRHRD,ERRgeneral));
3257 END_PROFILE(SMBsplclose);
3262 /****************************************************************************
3263 reply to a printqueue
3264 ****************************************************************************/
3265 int reply_printqueue(connection_struct *conn,
3266 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3268 int outsize = set_message(outbuf,2,3,True);
3269 int max_count = SVAL(inbuf,smb_vwv0);
3270 int start_index = SVAL(inbuf,smb_vwv1);
3271 START_PROFILE(SMBsplretq);
3273 /* we used to allow the client to get the cnum wrong, but that
3274 is really quite gross and only worked when there was only
3275 one printer - I think we should now only accept it if they
3276 get it right (tridge) */
3277 if (!CAN_PRINT(conn)) {
3278 END_PROFILE(SMBsplretq);
3279 return(ERROR(ERRDOS,ERRnoaccess));
3282 SSVAL(outbuf,smb_vwv0,0);
3283 SSVAL(outbuf,smb_vwv1,0);
3284 CVAL(smb_buf(outbuf),0) = 1;
3285 SSVAL(smb_buf(outbuf),1,0);
3287 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3288 start_index, max_count));
3291 print_queue_struct *queue = NULL;
3292 char *p = smb_buf(outbuf) + 3;
3293 int count = print_queue_status(SNUM(conn), &queue,NULL);
3294 int num_to_get = ABS(max_count);
3295 int first = (max_count>0?start_index:start_index+max_count+1);
3301 num_to_get = MIN(num_to_get,count-first);
3304 for (i=first;i<first+num_to_get;i++) {
3305 put_dos_date2(p,0,queue[i].time);
3306 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3307 SSVAL(p,5, queue[i].job);
3308 SIVAL(p,7,queue[i].size);
3310 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII);
3315 outsize = set_message(outbuf,2,28*count+3,False);
3316 SSVAL(outbuf,smb_vwv0,count);
3317 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3318 CVAL(smb_buf(outbuf),0) = 1;
3319 SSVAL(smb_buf(outbuf),1,28*count);
3322 if (queue) free(queue);
3324 DEBUG(3,("%d entries returned in queue\n",count));
3327 END_PROFILE(SMBsplretq);
3332 /****************************************************************************
3333 reply to a printwrite
3334 ****************************************************************************/
3335 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3338 int outsize = set_message(outbuf,0,0,True);
3340 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3341 START_PROFILE(SMBsplwr);
3343 if (!CAN_PRINT(conn)) {
3344 END_PROFILE(SMBsplwr);
3345 return(ERROR(ERRDOS,ERRnoaccess));
3348 CHECK_FSP(fsp,conn);
3352 numtowrite = SVAL(smb_buf(inbuf),1);
3353 data = smb_buf(inbuf) + 3;
3355 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3356 END_PROFILE(SMBsplwr);
3357 return(UNIXERROR(ERRDOS,ERRnoaccess));
3360 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3362 END_PROFILE(SMBsplwr);
3367 /****************************************************************************
3368 The guts of the mkdir command, split out so it may be called by the NT SMB
3370 ****************************************************************************/
3371 int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
3373 BOOL bad_path = False;
3374 SMB_STRUCT_STAT sbuf;
3377 unix_convert(directory,conn,0,&bad_path,&sbuf);
3379 if (check_name(directory, conn))
3380 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3384 if((errno == ENOENT) && bad_path)
3386 unix_ERR_class = ERRDOS;
3387 unix_ERR_code = ERRbadpath;
3389 return(UNIXERROR(ERRDOS,ERRnoaccess));
3395 /****************************************************************************
3397 ****************************************************************************/
3398 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3402 START_PROFILE(SMBmkdir);
3404 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3406 outsize=mkdir_internal(conn, inbuf, outbuf, directory);
3408 outsize = set_message(outbuf,0,0,True);
3410 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3412 END_PROFILE(SMBmkdir);
3416 /****************************************************************************
3417 Static function used by reply_rmdir to delete an entire directory
3419 ****************************************************************************/
3421 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3425 void *dirptr = OpenDir(NULL, directory, False);
3430 while((dname = ReadDirName(dirptr)))
3435 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3438 /* Construct the full name. */
3439 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3445 pstrcpy(fullname, directory);
3446 pstrcat(fullname, "/");
3447 pstrcat(fullname, dname);
3449 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3455 if(st.st_mode & S_IFDIR)
3457 if(recursive_rmdir(conn, fullname)!=0)
3462 if(vfs_rmdir(conn,fullname) != 0)
3468 else if(vfs_unlink(conn,fullname) != 0)
3478 /****************************************************************************
3479 The internals of the rmdir code - called elsewhere.
3480 ****************************************************************************/
3482 BOOL rmdir_internals(connection_struct *conn, char *directory)
3486 ok = (vfs_rmdir(conn,directory) == 0);
3487 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3490 * Check to see if the only thing in this directory are
3491 * vetoed files/directories. If so then delete them and
3492 * retry. If we fail to delete any of them (and we *don't*
3493 * do a recursive delete) then fail the rmdir.
3495 BOOL all_veto_files = True;
3497 void *dirptr = OpenDir(conn, directory, False);
3501 int dirpos = TellDir(dirptr);
3502 while ((dname = ReadDirName(dirptr)))
3504 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3506 if(!IS_VETO_PATH(conn, dname))
3508 all_veto_files = False;
3514 SeekDir(dirptr,dirpos);
3515 while ((dname = ReadDirName(dirptr)))
3520 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3523 /* Construct the full name. */
3524 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3529 pstrcpy(fullname, directory);
3530 pstrcat(fullname, "/");
3531 pstrcat(fullname, dname);
3533 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3535 if(st.st_mode & S_IFDIR)
3537 if(lp_recursive_veto_delete(SNUM(conn)))
3539 if(recursive_rmdir(conn, fullname) != 0)
3542 if(vfs_rmdir(conn,fullname) != 0)
3545 else if(vfs_unlink(conn,fullname) != 0)
3549 /* Retry the rmdir */
3550 ok = (vfs_rmdir(conn,directory) == 0);
3560 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3561 directory,strerror(errno)));
3566 /****************************************************************************
3568 ****************************************************************************/
3570 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3575 BOOL bad_path = False;
3576 SMB_STRUCT_STAT sbuf;
3577 START_PROFILE(SMBrmdir);
3579 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3581 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3583 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3585 if (check_name(directory,conn))
3587 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3588 ok = rmdir_internals(conn, directory);
3593 if((errno == ENOENT) && bad_path)
3595 unix_ERR_class = ERRDOS;
3596 unix_ERR_code = ERRbadpath;
3598 END_PROFILE(SMBrmdir);
3599 return(UNIXERROR(ERRDOS,ERRbadpath));
3602 outsize = set_message(outbuf,0,0,True);
3604 DEBUG( 3, ( "rmdir %s\n", directory ) );
3606 END_PROFILE(SMBrmdir);
3611 /*******************************************************************
3612 resolve wildcards in a filename rename
3613 ********************************************************************/
3614 static BOOL resolve_wildcards(char *name1,char *name2)
3616 fstring root1,root2;
3620 name1 = strrchr_m(name1,'/');
3621 name2 = strrchr_m(name2,'/');
3623 if (!name1 || !name2) return(False);
3625 fstrcpy(root1,name1);
3626 fstrcpy(root2,name2);
3627 p = strrchr_m(root1,'.');
3634 p = strrchr_m(root2,'.');
3666 pstrcpy(name2,root2);
3669 pstrcat(name2,ext2);
3675 /*******************************************************************
3676 check if a user is allowed to rename a file
3677 ********************************************************************/
3678 static BOOL can_rename(char *fname,connection_struct *conn)
3680 SMB_STRUCT_STAT sbuf;
3682 if (!CAN_WRITE(conn)) return(False);
3684 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
3685 if (!check_file_sharing(conn,fname,True)) return(False);
3689 /****************************************************************************
3690 The guts of the rename command, split out so it may be called by the NT SMB
3692 ****************************************************************************/
3693 int rename_internals(connection_struct *conn,
3694 char *inbuf, char *outbuf, char *name,
3695 char *newname, BOOL replace_if_exists)
3699 pstring newname_last_component;
3702 BOOL bad_path1 = False;
3703 BOOL bad_path2 = False;
3705 int error = ERRnoaccess;
3708 SMB_STRUCT_STAT sbuf1, sbuf2;
3710 *directory = *mask = 0;
3712 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3713 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3716 * Split the old name into directory and last component
3717 * strings. Note that unix_convert may have stripped off a
3718 * leading ./ from both name and newname if the rename is
3719 * at the root of the share. We need to make sure either both
3720 * name and newname contain a / character or neither of them do
3721 * as this is checked in resolve_wildcards().
3724 p = strrchr_m(name,'/');
3726 pstrcpy(directory,".");
3730 pstrcpy(directory,name);
3732 *p = '/'; /* Replace needed for exceptional test below. */
3736 * We should only check the mangled cache
3737 * here if unix_convert failed. This means
3738 * that the path in 'mask' doesn't exist
3739 * on the file system and so we need to look
3740 * for a possible mangle. This patch from
3741 * Tine Smukavec <valentin.smukavec@hermes.si>.
3744 if (!rc && is_mangled(mask))
3745 check_mangled_cache( mask );
3747 has_wild = ms_has_wild(mask);
3751 * No wildcards - just process the one file.
3753 BOOL is_short_name = is_8_3(name, True);
3755 /* Add a terminating '/' to the directory name. */
3756 pstrcat(directory,"/");
3757 pstrcat(directory,mask);
3759 /* Ensure newname contains a '/' also */
3760 if(strrchr_m(newname,'/') == 0) {
3763 pstrcpy(tmpstr, "./");
3764 pstrcat(tmpstr, newname);
3765 pstrcpy(newname, tmpstr);
3768 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",
3769 case_sensitive, case_preserve, short_case_preserve, directory,
3770 newname, newname_last_component, is_short_name));
3773 * Check for special case with case preserving and not
3774 * case sensitive, if directory and newname are identical,
3775 * and the old last component differs from the original
3776 * last component only by case, then we should allow
3777 * the rename (user is trying to change the case of the
3780 if((case_sensitive == False) &&
3781 (((case_preserve == True) &&
3782 (is_short_name == False)) ||
3783 ((short_case_preserve == True) &&
3784 (is_short_name == True))) &&
3785 strcsequal(directory, newname)) {
3786 pstring newname_modified_last_component;
3789 * Get the last component of the modified name.
3790 * Note that we guarantee that newname contains a '/'
3793 p = strrchr_m(newname,'/');
3794 pstrcpy(newname_modified_last_component,p+1);
3796 if(strcsequal(newname_modified_last_component,
3797 newname_last_component) == False) {
3799 * Replace the modified last component with
3802 pstrcpy(p+1, newname_last_component);
3806 if(replace_if_exists) {
3808 * NT SMB specific flag - rename can overwrite
3809 * file with the same name so don't check for
3813 if(resolve_wildcards(directory,newname) &&
3814 can_rename(directory,conn) &&
3815 !conn->vfs_ops.rename(conn,directory,newname))
3818 if (resolve_wildcards(directory,newname) &&
3819 can_rename(directory,conn) &&
3820 !vfs_file_exist(conn,newname,NULL) &&
3821 !conn->vfs_ops.rename(conn,directory,newname))
3825 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3826 directory,newname));
3828 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3829 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3835 * Wildcards - process each file that matches.
3837 void *dirptr = NULL;
3841 if (check_name(directory,conn))
3842 dirptr = OpenDir(conn, directory, True);
3847 if (strequal(mask,"????????.???"))
3850 while ((dname = ReadDirName(dirptr))) {
3853 pstrcpy(fname,dname);
3855 if(!mask_match(fname, mask, case_sensitive))
3858 error = ERRnoaccess;
3859 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3860 if (!can_rename(fname,conn)) {
3861 DEBUG(6,("rename %s refused\n", fname));
3864 pstrcpy(destname,newname);
3866 if (!resolve_wildcards(fname,destname)) {
3867 DEBUG(6,("resolve_wildcards %s %s failed\n",
3872 if (!replace_if_exists &&
3873 vfs_file_exist(conn,destname, NULL)) {
3874 DEBUG(6,("file_exist %s\n", destname));
3879 if (!conn->vfs_ops.rename(conn,fname,destname))
3881 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3889 return(ERROR(ERRDOS,error));
3891 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3892 unix_ERR_class = ERRDOS;
3893 unix_ERR_code = ERRbadpath;
3895 return(UNIXERROR(ERRDOS,error));
3902 /****************************************************************************
3904 ****************************************************************************/
3906 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3913 START_PROFILE(SMBmv);
3915 p = smb_buf(inbuf) + 1;
3916 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3918 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3920 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3921 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3923 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3925 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3929 * Win2k needs a changenotify request response before it will
3930 * update after a rename..
3933 process_pending_change_notify_queue((time_t)0);
3935 outsize = set_message(outbuf,0,0,True);
3942 /*******************************************************************
3943 copy a file as part of a reply_copy
3944 ******************************************************************/
3946 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3947 int count,BOOL target_is_directory, int *err_ret)
3950 SMB_STRUCT_STAT src_sbuf, sbuf2;
3952 files_struct *fsp1,*fsp2;
3957 pstrcpy(dest,dest1);
3958 if (target_is_directory) {
3959 char *p = strrchr_m(src,'/');
3968 if (!vfs_file_exist(conn,src,&src_sbuf))
3971 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3972 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3978 if (!target_is_directory && count)
3979 ofun = FILE_EXISTS_OPEN;
3981 vfs_stat(conn,dest,&sbuf2);
3982 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3983 ofun,src_sbuf.st_mode,0,&Access,&action);
3986 close_file(fsp1,False);
3990 if ((ofun&3) == 1) {
3991 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3992 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3995 * Stop the copy from occurring.
3998 src_sbuf.st_size = 0;
4002 if (src_sbuf.st_size)
4003 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
4005 close_file(fsp1,False);
4007 * As we are opening fsp1 read-only we only expect
4008 * an error on close on fsp2 if we are out of space.
4009 * Thus we don't look at the error return from the
4012 *err_ret = close_file(fsp2,False);
4014 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4019 /****************************************************************************
4020 reply to a file copy.
4021 ****************************************************************************/
4022 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4027 pstring mask,newname;
4030 int error = ERRnoaccess;
4034 int tid2 = SVAL(inbuf,smb_vwv0);
4035 int ofun = SVAL(inbuf,smb_vwv1);
4036 int flags = SVAL(inbuf,smb_vwv2);
4037 BOOL target_is_directory=False;
4038 BOOL bad_path1 = False;
4039 BOOL bad_path2 = False;
4041 SMB_STRUCT_STAT sbuf1, sbuf2;
4042 START_PROFILE(SMBcopy);
4044 *directory = *mask = 0;
4047 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
4048 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
4050 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4052 if (tid2 != conn->cnum) {
4053 /* can't currently handle inter share copies XXXX */
4054 DEBUG(3,("Rejecting inter-share copy\n"));
4055 END_PROFILE(SMBcopy);
4056 return(ERROR(ERRSRV,ERRinvdevice));
4059 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4060 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4062 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4063 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4065 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4067 if ((flags&1) && target_is_directory) {
4068 END_PROFILE(SMBcopy);
4069 return(ERROR(ERRDOS,ERRbadfile));
4072 if ((flags&2) && !target_is_directory) {
4073 END_PROFILE(SMBcopy);
4074 return(ERROR(ERRDOS,ERRbadpath));
4077 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4078 /* wants a tree copy! XXXX */
4079 DEBUG(3,("Rejecting tree copy\n"));
4080 END_PROFILE(SMBcopy);
4081 return(ERROR(ERRSRV,ERRerror));
4084 p = strrchr_m(name,'/');
4086 pstrcpy(directory,"./");
4090 pstrcpy(directory,name);
4095 * We should only check the mangled cache
4096 * here if unix_convert failed. This means
4097 * that the path in 'mask' doesn't exist
4098 * on the file system and so we need to look
4099 * for a possible mangle. This patch from
4100 * Tine Smukavec <valentin.smukavec@hermes.si>.
4103 if (!rc && is_mangled(mask))
4104 check_mangled_cache( mask );
4106 has_wild = ms_has_wild(mask);
4109 pstrcat(directory,"/");
4110 pstrcat(directory,mask);
4111 if (resolve_wildcards(directory,newname) &&
4112 copy_file(directory,newname,conn,ofun,
4113 count,target_is_directory,&err)) count++;
4116 END_PROFILE(SMBcopy);
4117 return(UNIXERROR(ERRHRD,ERRgeneral));
4119 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4121 void *dirptr = NULL;
4125 if (check_name(directory,conn))
4126 dirptr = OpenDir(conn, directory, True);
4131 if (strequal(mask,"????????.???"))
4134 while ((dname = ReadDirName(dirptr))) {
4136 pstrcpy(fname,dname);
4138 if(!mask_match(fname, mask, case_sensitive))
4141 error = ERRnoaccess;
4142 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4143 pstrcpy(destname,newname);
4144 if (resolve_wildcards(fname,destname) &&
4145 copy_file(fname,destname,conn,ofun,
4146 count,target_is_directory,&err)) count++;
4147 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4155 /* Error on close... */
4157 END_PROFILE(SMBcopy);
4158 return(UNIXERROR(ERRHRD,ERRgeneral));
4162 END_PROFILE(SMBcopy);
4163 return(ERROR(ERRDOS,error));
4166 if((errno == ENOENT) && (bad_path1 || bad_path2))
4168 unix_ERR_class = ERRDOS;
4169 unix_ERR_code = ERRbadpath;
4171 END_PROFILE(SMBcopy);
4172 return(UNIXERROR(ERRDOS,error));
4176 outsize = set_message(outbuf,1,0,True);
4177 SSVAL(outbuf,smb_vwv0,count);
4179 END_PROFILE(SMBcopy);
4183 /****************************************************************************
4185 ****************************************************************************/
4186 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4192 START_PROFILE(pathworks_setdir);
4195 if (!CAN_SETDIR(snum)) {
4196 END_PROFILE(pathworks_setdir);
4197 return(ERROR(ERRDOS,ERRnoaccess));
4200 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
4202 if (strlen(newdir) == 0) {
4205 ok = vfs_directory_exist(conn,newdir,NULL);
4207 string_set(&conn->connectpath,newdir);
4212 END_PROFILE(pathworks_setdir);
4213 return(ERROR(ERRDOS,ERRbadpath));
4216 outsize = set_message(outbuf,0,0,True);
4217 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4219 DEBUG(3,("setdir %s\n", newdir));
4221 END_PROFILE(pathworks_setdir);
4225 /****************************************************************************
4226 Get a lock pid, dealing with large count requests.
4227 ****************************************************************************/
4229 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4231 if(!large_file_format)
4232 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4234 return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
4237 /****************************************************************************
4238 Get a lock count, dealing with large count requests.
4239 ****************************************************************************/
4241 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4243 SMB_BIG_UINT count = 0;
4245 if(!large_file_format) {
4246 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4249 #if defined(HAVE_LONGLONG)
4250 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4251 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4252 #else /* HAVE_LONGLONG */
4255 * NT4.x seems to be broken in that it sends large file (64 bit)
4256 * lockingX calls even if the CAP_LARGE_FILES was *not*
4257 * negotiated. For boxes without large unsigned ints truncate the
4258 * lock count by dropping the top 32 bits.
4261 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4262 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4263 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4264 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4265 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4268 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4269 #endif /* HAVE_LONGLONG */
4275 /****************************************************************************
4276 Get a lock offset, dealing with large offset requests.
4277 ****************************************************************************/
4279 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4281 SMB_BIG_UINT offset = 0;
4285 if(!large_file_format) {
4286 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4289 #if defined(HAVE_LONGLONG)
4290 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4291 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4292 #else /* HAVE_LONGLONG */
4295 * NT4.x seems to be broken in that it sends large file (64 bit)
4296 * lockingX calls even if the CAP_LARGE_FILES was *not*
4297 * negotiated. For boxes without large unsigned ints mangle the
4298 * lock offset by mapping the top 32 bits onto the lower 32.
4301 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4302 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4303 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4306 if((new_low = map_lock_offset(high, low)) == 0) {
4308 return (SMB_BIG_UINT)-1;
4311 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4312 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4313 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4314 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4317 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4318 #endif /* HAVE_LONGLONG */
4324 /****************************************************************************
4325 reply to a lockingX request
4326 ****************************************************************************/
4328 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4330 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4331 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4332 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4333 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4334 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4335 SMB_BIG_UINT count = 0, offset = 0;
4337 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4340 uint32 ecode=0, dummy2;
4341 int eclass=0, dummy1;
4342 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4344 START_PROFILE(SMBlockingX);
4346 CHECK_FSP(fsp,conn);
4349 data = smb_buf(inbuf);
4351 /* Check if this is an oplock break on a file
4352 we have granted an oplock on.
4354 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4356 /* Client can insist on breaking to none. */
4357 BOOL break_to_none = (oplocklevel == 0);
4359 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4360 (unsigned int)oplocklevel, fsp->fnum ));
4363 * Make sure we have granted an exclusive or batch oplock on this file.
4366 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4368 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4369 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4371 /* if this is a pure oplock break request then don't send a reply */
4372 if (num_locks == 0 && num_ulocks == 0) {
4373 END_PROFILE(SMBlockingX);
4376 END_PROFILE(SMBlockingX);
4377 return ERROR(ERRDOS,ERRlock);
4381 if (remove_oplock(fsp, break_to_none) == False) {
4382 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4386 /* if this is a pure oplock break request then don't send a reply */
4387 if (num_locks == 0 && num_ulocks == 0)
4389 /* Sanity check - ensure a pure oplock break is not a
4391 if(CVAL(inbuf,smb_vwv0) != 0xff)
4392 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4393 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4394 END_PROFILE(SMBlockingX);
4400 * We do this check *after* we have checked this is not a oplock break
4401 * response message. JRA.
4404 release_level_2_oplocks_on_change(fsp);
4406 /* Data now points at the beginning of the list
4407 of smb_unlkrng structs */
4408 for(i = 0; i < (int)num_ulocks; i++) {
4409 lock_pid = get_lock_pid( data, i, large_file_format);
4410 count = get_lock_count( data, i, large_file_format);
4411 offset = get_lock_offset( data, i, large_file_format, &err);
4414 * There is no error code marked "stupid client bug".... :-).
4417 END_PROFILE(SMBlockingX);
4418 return ERROR(ERRDOS,ERRnoaccess);
4421 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4422 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4424 if(!do_unlock(fsp,conn,lock_pid,count,offset, &eclass, &ecode)) {
4425 END_PROFILE(SMBlockingX);
4426 return ERROR(eclass,ecode);
4430 /* Setup the timeout in seconds. */
4431 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4433 /* Now do any requested locks */
4434 data += ((large_file_format ? 20 : 10)*num_ulocks);
4436 /* Data now points at the beginning of the list
4437 of smb_lkrng structs */
4439 for(i = 0; i < (int)num_locks; i++) {
4440 lock_pid = get_lock_pid( data, i, large_file_format);
4441 count = get_lock_count( data, i, large_file_format);
4442 offset = get_lock_offset( data, i, large_file_format, &err);
4445 * There is no error code marked "stupid client bug".... :-).
4448 END_PROFILE(SMBlockingX);
4449 return ERROR(ERRDOS,ERRnoaccess);
4452 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
4453 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4455 if(!do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4457 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4459 * A blocking lock was requested. Package up
4460 * this smb into a queued request and push it
4461 * onto the blocking lock queue.
4463 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4464 END_PROFILE(SMBlockingX);
4472 /* If any of the above locks failed, then we must unlock
4473 all of the previous locks (X/Open spec). */
4474 if(i != num_locks && num_locks != 0) {
4476 * Ensure we don't do a remove on the lock that just failed,
4477 * as under POSIX rules, if we have a lock already there, we
4478 * will delete it (and we shouldn't) .....
4480 for(i--; i >= 0; i--) {
4481 lock_pid = get_lock_pid( data, i, large_file_format);
4482 count = get_lock_count( data, i, large_file_format);
4483 offset = get_lock_offset( data, i, large_file_format, &err);
4486 * There is no error code marked "stupid client bug".... :-).
4489 END_PROFILE(SMBlockingX);
4490 return ERROR(ERRDOS,ERRnoaccess);
4493 do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2);
4495 END_PROFILE(SMBlockingX);
4496 return ERROR(eclass,ecode);
4499 set_message(outbuf,2,0,True);
4501 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4502 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4504 END_PROFILE(SMBlockingX);
4505 return chain_reply(inbuf,outbuf,length,bufsize);
4509 /****************************************************************************
4510 reply to a SMBreadbmpx (read block multiplex) request
4511 ****************************************************************************/
4512 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4523 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4524 START_PROFILE(SMBreadBmpx);
4526 /* this function doesn't seem to work - disable by default */
4527 if (!lp_readbmpx()) {
4528 END_PROFILE(SMBreadBmpx);
4529 return(ERROR(ERRSRV,ERRuseSTD));
4532 outsize = set_message(outbuf,8,0,True);
4534 CHECK_FSP(fsp,conn);
4538 startpos = IVAL(inbuf,smb_vwv1);
4539 maxcount = SVAL(inbuf,smb_vwv3);
4541 data = smb_buf(outbuf);
4542 pad = ((long)data)%4;
4543 if (pad) pad = 4 - pad;
4546 max_per_packet = bufsize-(outsize+pad);
4550 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4551 END_PROFILE(SMBreadBmpx);
4552 return(ERROR(ERRDOS,ERRlock));
4557 size_t N = MIN(max_per_packet,tcount-total_read);
4559 nread = read_file(fsp,data,startpos,N);
4561 if (nread <= 0) nread = 0;
4563 if (nread < (ssize_t)N)
4564 tcount = total_read + nread;
4566 set_message(outbuf,8,nread,False);
4567 SIVAL(outbuf,smb_vwv0,startpos);
4568 SSVAL(outbuf,smb_vwv2,tcount);
4569 SSVAL(outbuf,smb_vwv6,nread);
4570 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4572 if (!send_smb(smbd_server_fd(),outbuf))
4573 exit_server("reply_readbmpx: send_smb failed.\n");
4575 total_read += nread;
4578 while (total_read < (ssize_t)tcount);
4580 END_PROFILE(SMBreadBmpx);
4584 /****************************************************************************
4585 reply to a SMBwritebmpx (write block multiplex primary) request
4586 ****************************************************************************/
4588 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4591 ssize_t nwritten = -1;
4598 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4599 START_PROFILE(SMBwriteBmpx);
4601 CHECK_FSP(fsp,conn);
4605 tcount = SVAL(inbuf,smb_vwv1);
4606 startpos = IVAL(inbuf,smb_vwv3);
4607 write_through = BITSETW(inbuf+smb_vwv7,0);
4608 numtowrite = SVAL(inbuf,smb_vwv10);
4609 smb_doff = SVAL(inbuf,smb_vwv11);
4611 data = smb_base(inbuf) + smb_doff;
4613 /* If this fails we need to send an SMBwriteC response,
4614 not an SMBwritebmpx - set this up now so we don't forget */
4615 CVAL(outbuf,smb_com) = SMBwritec;
4617 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4618 END_PROFILE(SMBwriteBmpx);
4619 return(ERROR(ERRDOS,ERRlock));
4622 nwritten = write_file(fsp,data,startpos,numtowrite);
4624 if(lp_syncalways(SNUM(conn)) || write_through)
4625 sync_file(conn,fsp);
4627 if(nwritten < (ssize_t)numtowrite) {
4628 END_PROFILE(SMBwriteBmpx);
4629 return(UNIXERROR(ERRHRD,ERRdiskfull));
4632 /* If the maximum to be written to this file
4633 is greater than what we just wrote then set
4634 up a secondary struct to be attached to this
4635 fd, we will use this to cache error messages etc. */
4636 if((ssize_t)tcount > nwritten)
4638 write_bmpx_struct *wbms;
4639 if(fsp->wbmpx_ptr != NULL)
4640 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4642 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4645 DEBUG(0,("Out of memory in reply_readmpx\n"));
4646 END_PROFILE(SMBwriteBmpx);
4647 return(ERROR(ERRSRV,ERRnoresource));
4649 wbms->wr_mode = write_through;
4650 wbms->wr_discard = False; /* No errors yet */
4651 wbms->wr_total_written = nwritten;
4652 wbms->wr_errclass = 0;
4654 fsp->wbmpx_ptr = wbms;
4657 /* We are returning successfully, set the message type back to
4659 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4661 outsize = set_message(outbuf,1,0,True);
4663 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4665 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4666 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4668 if (write_through && tcount==nwritten) {
4669 /* we need to send both a primary and a secondary response */
4670 smb_setlen(outbuf,outsize - 4);
4671 if (!send_smb(smbd_server_fd(),outbuf))
4672 exit_server("reply_writebmpx: send_smb failed.\n");
4674 /* now the secondary */
4675 outsize = set_message(outbuf,1,0,True);
4676 CVAL(outbuf,smb_com) = SMBwritec;
4677 SSVAL(outbuf,smb_vwv0,nwritten);
4680 END_PROFILE(SMBwriteBmpx);
4685 /****************************************************************************
4686 reply to a SMBwritebs (write block multiplex secondary) request
4687 ****************************************************************************/
4688 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4691 ssize_t nwritten = -1;
4698 write_bmpx_struct *wbms;
4699 BOOL send_response = False;
4700 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4701 START_PROFILE(SMBwriteBs);
4703 CHECK_FSP(fsp,conn);
4706 tcount = SVAL(inbuf,smb_vwv1);
4707 startpos = IVAL(inbuf,smb_vwv2);
4708 numtowrite = SVAL(inbuf,smb_vwv6);
4709 smb_doff = SVAL(inbuf,smb_vwv7);
4711 data = smb_base(inbuf) + smb_doff;
4713 /* We need to send an SMBwriteC response, not an SMBwritebs */
4714 CVAL(outbuf,smb_com) = SMBwritec;
4716 /* This fd should have an auxiliary struct attached,
4717 check that it does */
4718 wbms = fsp->wbmpx_ptr;
4720 END_PROFILE(SMBwriteBs);
4724 /* If write through is set we can return errors, else we must
4726 write_through = wbms->wr_mode;
4728 /* Check for an earlier error */
4729 if(wbms->wr_discard) {
4730 END_PROFILE(SMBwriteBs);
4731 return -1; /* Just discard the packet */
4734 nwritten = write_file(fsp,data,startpos,numtowrite);
4736 if(lp_syncalways(SNUM(conn)) || write_through)
4737 sync_file(conn,fsp);
4739 if (nwritten < (ssize_t)numtowrite)
4743 /* We are returning an error - we can delete the aux struct */
4744 if (wbms) free((char *)wbms);
4745 fsp->wbmpx_ptr = NULL;
4746 END_PROFILE(SMBwriteBs);
4747 return(ERROR(ERRHRD,ERRdiskfull));
4749 END_PROFILE(SMBwriteBs);
4750 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4753 /* Increment the total written, if this matches tcount
4754 we can discard the auxiliary struct (hurrah !) and return a writeC */
4755 wbms->wr_total_written += nwritten;
4756 if(wbms->wr_total_written >= tcount)
4760 outsize = set_message(outbuf,1,0,True);
4761 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4762 send_response = True;
4766 fsp->wbmpx_ptr = NULL;
4770 END_PROFILE(SMBwriteBs);
4774 END_PROFILE(SMBwriteBs);
4779 /****************************************************************************
4780 reply to a SMBsetattrE
4781 ****************************************************************************/
4783 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4785 struct utimbuf unix_times;
4787 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4788 START_PROFILE(SMBsetattrE);
4790 outsize = set_message(outbuf,0,0,True);
4792 CHECK_FSP(fsp,conn);
4795 /* Convert the DOS times into unix times. Ignore create
4796 time as UNIX can't set this.
4798 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4799 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4802 * Patch from Ray Frush <frush@engr.colostate.edu>
4803 * Sometimes times are sent as zero - ignore them.
4806 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4808 /* Ignore request */
4811 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4812 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4814 END_PROFILE(SMBsetattrE);
4817 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4819 /* set modify time = to access time if modify time was 0 */
4820 unix_times.modtime = unix_times.actime;
4823 /* Set the date on this file */
4824 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4825 END_PROFILE(SMBsetattrE);
4826 return(ERROR(ERRDOS,ERRnoaccess));
4829 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4830 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4832 END_PROFILE(SMBsetattrE);
4837 /****************************************************************************
4838 reply to a SMBgetattrE
4839 ****************************************************************************/
4841 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4843 SMB_STRUCT_STAT sbuf;
4846 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4847 START_PROFILE(SMBgetattrE);
4849 outsize = set_message(outbuf,11,0,True);
4851 CHECK_FSP(fsp,conn);
4854 /* Do an fstat on this file */
4855 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4856 END_PROFILE(SMBgetattrE);
4857 return(UNIXERROR(ERRDOS,ERRnoaccess));
4860 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4862 /* Convert the times into dos times. Set create
4863 date to be last modify date as UNIX doesn't save
4865 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4866 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4867 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4870 SIVAL(outbuf,smb_vwv6,0);
4871 SIVAL(outbuf,smb_vwv8,0);
4875 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4876 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4878 SSVAL(outbuf,smb_vwv10, mode);
4880 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4882 END_PROFILE(SMBgetattrE);