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(service,'%');
207 p = strrchr(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(path+2,'\\');
293 END_PROFILE(SMBtconX);
294 return(ERROR(ERRDOS,ERRnosuchshare));
296 fstrcpy(service,q+1);
297 q = strchr(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 */
840 alpha_strcpy(user, user, ". _-", sizeof(user));
841 if (strstr(user, "..")) {
842 return bad_password_error(inbuf, outbuf);
845 /* don't allow for weird usernames */
846 alpha_strcpy(user, user, ". _-", sizeof(user));
847 if (strstr(user, "..")) {
848 return bad_password_error(inbuf, outbuf);
851 DEBUG(3,("sesssetupX:name=[%s]\n",user));
853 /* If name ends in $ then I think it's asking about whether a */
854 /* computer with that name (minus the $) has access. For now */
855 /* say yes to everything ending in $. */
857 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
858 END_PROFILE(SMBsesssetupX);
859 return session_trust_account(conn, inbuf, outbuf, user,
860 smb_apasswd, smb_apasslen,
861 smb_ntpasswd, smb_ntpasslen);
864 if (done_sesssetup && lp_restrict_anonymous()) {
865 /* tests show that even if browsing is done over already validated connections
866 * without a username and password the domain is still provided, which it
867 * wouldn't be if it was a purely anonymous connection. So, in order to
868 * restrict anonymous, we only deny connections that have no session
869 * information. If a domain has been provided, then it's not a purely
870 * anonymous connection. AAB
872 if (!*user && !*smb_apasswd && !*domain) {
873 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
874 END_PROFILE(SMBsesssetupX);
875 return(ERROR(ERRDOS,ERRnoaccess));
879 /* If no username is sent use the guest account */
881 pstrcpy(user,lp_guestaccount(-1));
882 /* If no user and no password then set guest flag. */
883 if( *smb_apasswd == 0)
887 pstrcpy(current_user_info.smb_name,user);
889 reload_services(True);
892 * Save the username before mapping. We will use
893 * the original username sent to us for security=server
894 * and security=domain checking.
897 pstrcpy( orig_user, user);
900 * Always try the "DOMAIN\user" lookup first, as this is the most
901 * specific case. If this fails then try the simple "user" lookup.
907 /* Work out who's who */
909 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
910 domain, lp_winbind_separator(), user);
912 if (sys_getpwnam(dom_user) != NULL) {
913 pstrcpy(user, dom_user);
914 DEBUG(3,("Using unix username %s\n", dom_user));
919 * Pass the user through the NT -> unix user mapping
923 (void)map_username(user);
926 * Do any UNIX username case mangling.
928 smb_getpwnam(user, True);
930 add_session_user(user);
933 * Check if the given username was the guest user with no password.
936 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
940 * Check with orig_user for security=server and
944 if (!guest && !check_server_security(orig_user, domain, user,
945 smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
946 !check_domain_security(orig_user, domain, user, smb_apasswd,
947 smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
948 !check_hosts_equiv(user))
952 * If we get here then the user wasn't guest and the remote
953 * authentication methods failed. Check the authentication
954 * methods on this local server.
956 * If an NT password was supplied try and validate with that
957 * first. This is superior as the passwords are mixed case
958 * 128 length unicode.
963 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
964 DEBUG(2,("NT Password did not match for user '%s'!\n", user));
966 valid_nt_password = True;
970 /* check the LanMan password only if necessary and if allowed
971 by lp_lanman_auth() */
972 if (!valid_nt_password && lp_lanman_auth())
974 DEBUG(2,("Defaulting to Lanman password for %s\n", user));
975 valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen,NULL);
979 /* The true branch will be executed if
980 (1) the NT password failed (or was not tried), and
981 (2) LanMan authentication failed (or was disabled)
983 if (!valid_nt_password && !valid_lm_password)
985 if (lp_security() >= SEC_USER)
987 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
989 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
990 END_PROFILE(SMBsesssetupX);
991 return bad_password_error(inbuf,outbuf);
994 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
996 if (smb_getpwnam(user,True))
998 DEBUG(1,("Rejecting user '%s': bad password\n", user));
999 END_PROFILE(SMBsesssetupX);
1000 return bad_password_error(inbuf,outbuf);
1005 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
1006 * Then always map to guest account - as done below.
1010 if (*smb_apasswd || !smb_getpwnam(user,True))
1011 pstrcpy(user,lp_guestaccount(-1));
1012 DEBUG(3,("Registered username %s for guest access\n",user));
1017 if (!smb_getpwnam(user,True)) {
1018 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
1019 pstrcpy(user,lp_guestaccount(-1));
1023 if (!strequal(user,lp_guestaccount(-1)) &&
1024 lp_servicenumber(user) < 0)
1026 add_home_service(user,get_user_home_dir(user));
1030 /* it's ok - setup a reply */
1031 if (Protocol < PROTOCOL_NT1) {
1032 set_message(outbuf,3,0,True);
1035 set_message(outbuf,3,0,True);
1036 p = smb_buf(outbuf);
1037 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
1038 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
1039 p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE);
1040 set_message_end(outbuf,p);
1041 /* perhaps grab OS version here?? */
1044 /* Set the correct uid in the outgoing and incoming packets
1045 We will use this on future requests to determine which
1046 user we should become.
1049 const struct passwd *pw = smb_getpwnam(user,False);
1051 DEBUG(1,("Username %s is invalid on this system\n",user));
1052 END_PROFILE(SMBsesssetupX);
1053 return bad_password_error(inbuf,outbuf);
1060 SSVAL(outbuf,smb_vwv2,1);
1062 /* register the name and uid as being validated, so further connections
1063 to a uid can get through without a password, on the same VC */
1065 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest);
1067 if (sess_vuid == -1) {
1068 return(ERROR(ERRDOS,ERRnoaccess));
1072 SSVAL(outbuf,smb_uid,sess_vuid);
1073 SSVAL(inbuf,smb_uid,sess_vuid);
1075 if (!done_sesssetup)
1076 max_send = MIN(max_send,smb_bufsize);
1078 DEBUG(6,("Client requested max send size of %d\n", max_send));
1080 done_sesssetup = True;
1082 END_PROFILE(SMBsesssetupX);
1083 return chain_reply(inbuf,outbuf,length,bufsize);
1086 /****************************************************************************
1088 ****************************************************************************/
1089 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1095 BOOL bad_path = False;
1096 SMB_STRUCT_STAT sbuf;
1097 START_PROFILE(SMBchkpth);
1099 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1101 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1103 unix_convert(name,conn,0,&bad_path,&sbuf);
1105 mode = SVAL(inbuf,smb_vwv0);
1107 if (check_name(name,conn)) {
1108 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
1109 ok = S_ISDIR(sbuf.st_mode);
1114 /* We special case this - as when a Windows machine
1115 is parsing a path is steps through the components
1116 one at a time - if a component fails it expects
1117 ERRbadpath, not ERRbadfile.
1121 unix_ERR_class = ERRDOS;
1122 unix_ERR_code = ERRbadpath;
1126 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1127 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1128 (get_remote_arch() == RA_WINNT))
1130 unix_ERR_class = ERRDOS;
1131 unix_ERR_code = ERRbaddirectory;
1135 return(UNIXERROR(ERRDOS,ERRbadpath));
1138 outsize = set_message(outbuf,0,0,True);
1140 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1142 END_PROFILE(SMBchkpth);
1147 /****************************************************************************
1149 ****************************************************************************/
1150 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1154 SMB_STRUCT_STAT sbuf;
1159 BOOL bad_path = False;
1161 START_PROFILE(SMBgetatr);
1163 p = smb_buf(inbuf) + 1;
1164 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1166 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1168 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1169 under WfWg - weird! */
1172 mode = aHIDDEN | aDIR;
1173 if (!CAN_WRITE(conn)) mode |= aRONLY;
1180 unix_convert(fname,conn,0,&bad_path,&sbuf);
1181 if (check_name(fname,conn))
1183 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1185 mode = dos_mode(conn,fname,&sbuf);
1186 size = sbuf.st_size;
1187 mtime = sbuf.st_mtime;
1193 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1199 if((errno == ENOENT) && bad_path)
1201 unix_ERR_class = ERRDOS;
1202 unix_ERR_code = ERRbadpath;
1205 END_PROFILE(SMBgetatr);
1206 return(UNIXERROR(ERRDOS,ERRbadfile));
1209 outsize = set_message(outbuf,10,0,True);
1211 SSVAL(outbuf,smb_vwv0,mode);
1212 if(lp_dos_filetime_resolution(SNUM(conn)) )
1213 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1215 put_dos_date3(outbuf,smb_vwv1,mtime);
1216 SIVAL(outbuf,smb_vwv3,(uint32)size);
1218 if (Protocol >= PROTOCOL_NT1) {
1219 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1222 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1224 END_PROFILE(SMBgetatr);
1229 /****************************************************************************
1231 ****************************************************************************/
1232 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1239 SMB_STRUCT_STAT sbuf;
1240 BOOL bad_path = False;
1243 START_PROFILE(SMBsetatr);
1245 p = smb_buf(inbuf) + 1;
1246 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1247 unix_convert(fname,conn,0,&bad_path,&sbuf);
1249 mode = SVAL(inbuf,smb_vwv0);
1250 mtime = make_unix_date3(inbuf+smb_vwv1);
1252 if (VALID_STAT_OF_DIR(sbuf))
1254 if (check_name(fname,conn))
1255 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1257 ok = set_filetime(conn,fname,mtime);
1261 if((errno == ENOENT) && bad_path)
1263 unix_ERR_class = ERRDOS;
1264 unix_ERR_code = ERRbadpath;
1267 END_PROFILE(SMBsetatr);
1268 return(UNIXERROR(ERRDOS,ERRnoaccess));
1271 outsize = set_message(outbuf,0,0,True);
1273 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1275 END_PROFILE(SMBsetatr);
1280 /****************************************************************************
1282 ****************************************************************************/
1283 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1286 SMB_BIG_UINT dfree,dsize,bsize;
1287 START_PROFILE(SMBdskattr);
1289 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1291 outsize = set_message(outbuf,5,0,True);
1293 SSVAL(outbuf,smb_vwv0,dsize);
1294 SSVAL(outbuf,smb_vwv1,bsize/512);
1295 SSVAL(outbuf,smb_vwv2,512);
1296 SSVAL(outbuf,smb_vwv3,dfree);
1298 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1300 END_PROFILE(SMBdskattr);
1305 /****************************************************************************
1307 Can be called from SMBsearch, SMBffirst or SMBfunique.
1308 ****************************************************************************/
1309 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1320 BOOL finished = False;
1329 BOOL check_descend = False;
1330 BOOL expect_close = False;
1331 BOOL can_open = True;
1332 BOOL bad_path = False;
1333 START_PROFILE(SMBsearch);
1335 *mask = *directory = *fname = 0;
1337 /* If we were called as SMBffirst then we must expect close. */
1338 if(CVAL(inbuf,smb_com) == SMBffirst)
1339 expect_close = True;
1341 outsize = set_message(outbuf,1,3,True);
1342 maxentries = SVAL(inbuf,smb_vwv0);
1343 dirtype = SVAL(inbuf,smb_vwv1);
1344 p = smb_buf(inbuf) + 1;
1345 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1347 status_len = SVAL(p, 0);
1350 /* dirtype &= ~aDIR; */
1352 if (status_len == 0)
1354 SMB_STRUCT_STAT sbuf;
1357 pstrcpy(directory,path);
1359 unix_convert(directory,conn,0,&bad_path,&sbuf);
1362 if (!check_name(directory,conn))
1365 p = strrchr(dir2,'/');
1377 p = strrchr(directory,'/');
1383 if (strlen(directory) == 0)
1384 pstrcpy(directory,"./");
1385 memset((char *)status,'\0',21);
1386 CVAL(status,0) = dirtype;
1390 memcpy(status,p,21);
1391 dirtype = CVAL(status,0) & 0x1F;
1392 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1395 string_set(&conn->dirpath,dptr_path(dptr_num));
1396 fstrcpy(mask, dptr_wcard(dptr_num));
1401 p = smb_buf(outbuf) + 3;
1405 if (status_len == 0)
1407 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1412 if((errno == ENOENT) && bad_path)
1414 unix_ERR_class = ERRDOS;
1415 unix_ERR_code = ERRbadpath;
1417 END_PROFILE(SMBsearch);
1418 return (UNIXERROR(ERRDOS,ERRnofids));
1420 END_PROFILE(SMBsearch);
1421 return(ERROR(ERRDOS,ERRnofids));
1423 dptr_set_wcard(dptr_num, strdup(mask));
1426 DEBUG(4,("dptr_num is %d\n",dptr_num));
1430 if ((dirtype&0x1F) == aVOLID)
1432 memcpy(p,status,21);
1433 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1434 dptr_fill(p+12,dptr_num);
1435 if (dptr_zero(p+12) && (status_len==0))
1439 p += DIR_STRUCT_SIZE;
1443 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1444 conn->dirpath,lp_dontdescend(SNUM(conn))));
1445 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1446 check_descend = True;
1448 for (i=numentries;(i<maxentries) && !finished;i++)
1451 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1454 memcpy(p,status,21);
1455 make_dir_struct(p,mask,fname,size,mode,date);
1456 dptr_fill(p+12,dptr_num);
1459 p += DIR_STRUCT_SIZE;
1468 if (numentries == 0 || !ok)
1470 CVAL(outbuf,smb_rcls) = ERRDOS;
1471 SSVAL(outbuf,smb_err,ERRnofiles);
1472 dptr_close(&dptr_num);
1475 /* If we were called as SMBffirst with smb_search_id == NULL
1476 and no entries were found then return error and close dirptr
1479 if(ok && expect_close && numentries == 0 && status_len == 0)
1481 CVAL(outbuf,smb_rcls) = ERRDOS;
1482 SSVAL(outbuf,smb_err,ERRnofiles);
1483 /* Also close the dptr - we know it's gone */
1484 dptr_close(&dptr_num);
1487 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1488 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1489 dptr_close(&dptr_num);
1491 SSVAL(outbuf,smb_vwv0,numentries);
1492 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1493 CVAL(smb_buf(outbuf),0) = 5;
1494 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1496 if (Protocol >= PROTOCOL_NT1) {
1497 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1500 outsize += DIR_STRUCT_SIZE*numentries;
1501 smb_setlen(outbuf,outsize - 4);
1503 if ((! *directory) && dptr_path(dptr_num))
1504 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1506 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1507 smb_fn_name(CVAL(inbuf,smb_com)),
1508 mask, directory, dirtype, numentries, maxentries ) );
1510 END_PROFILE(SMBsearch);
1515 /****************************************************************************
1516 reply to a fclose (stop directory search)
1517 ****************************************************************************/
1518 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1527 START_PROFILE(SMBfclose);
1529 outsize = set_message(outbuf,1,0,True);
1530 p = smb_buf(inbuf) + 1;
1531 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1533 status_len = SVAL(p,0);
1536 if (status_len == 0) {
1537 END_PROFILE(SMBfclose);
1538 return(ERROR(ERRSRV,ERRsrverror));
1541 memcpy(status,p,21);
1543 if(dptr_fetch(status+12,&dptr_num)) {
1544 /* Close the dptr - we know it's gone */
1545 dptr_close(&dptr_num);
1548 SSVAL(outbuf,smb_vwv0,0);
1550 DEBUG(3,("search close\n"));
1552 END_PROFILE(SMBfclose);
1557 /****************************************************************************
1559 ****************************************************************************/
1561 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1571 SMB_STRUCT_STAT sbuf;
1572 BOOL bad_path = False;
1574 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1575 START_PROFILE(SMBopen);
1577 share_mode = SVAL(inbuf,smb_vwv0);
1579 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1581 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1583 unix_convert(fname,conn,0,&bad_path,&sbuf);
1585 unixmode = unix_mode(conn,aARCH,fname);
1587 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1588 unixmode, oplock_request,&rmode,NULL);
1592 if((errno == ENOENT) && bad_path)
1594 unix_ERR_class = ERRDOS;
1595 unix_ERR_code = ERRbadpath;
1597 END_PROFILE(SMBopen);
1598 return(UNIXERROR(ERRDOS,ERRnoaccess));
1601 size = sbuf.st_size;
1602 fmode = dos_mode(conn,fname,&sbuf);
1603 mtime = sbuf.st_mtime;
1606 DEBUG(3,("attempt to open a directory %s\n",fname));
1607 close_file(fsp,False);
1608 END_PROFILE(SMBopen);
1609 return(ERROR(ERRDOS,ERRnoaccess));
1612 outsize = set_message(outbuf,7,0,True);
1613 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1614 SSVAL(outbuf,smb_vwv1,fmode);
1615 if(lp_dos_filetime_resolution(SNUM(conn)) )
1616 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1618 put_dos_date3(outbuf,smb_vwv2,mtime);
1619 SIVAL(outbuf,smb_vwv4,(uint32)size);
1620 SSVAL(outbuf,smb_vwv6,rmode);
1622 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1623 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1626 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1627 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1628 END_PROFILE(SMBopen);
1633 /****************************************************************************
1634 reply to an open and X
1635 ****************************************************************************/
1636 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1639 int smb_mode = SVAL(inbuf,smb_vwv3);
1640 int smb_attr = SVAL(inbuf,smb_vwv5);
1641 /* Breakout the oplock request bits so we can set the
1642 reply bits separately. */
1643 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1644 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1645 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1647 int open_flags = SVAL(inbuf,smb_vwv2);
1648 int smb_sattr = SVAL(inbuf,smb_vwv4);
1649 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1651 int smb_ofun = SVAL(inbuf,smb_vwv8);
1654 int fmode=0,mtime=0,rmode=0;
1655 SMB_STRUCT_STAT sbuf;
1657 BOOL bad_path = False;
1659 START_PROFILE(SMBopenX);
1661 /* If it's an IPC, pass off the pipe handler. */
1663 if (lp_nt_pipe_support()) {
1664 END_PROFILE(SMBopenX);
1665 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1667 END_PROFILE(SMBopenX);
1668 return (ERROR(ERRSRV,ERRaccess));
1672 /* XXXX we need to handle passed times, sattr and flags */
1673 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1675 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1677 unix_convert(fname,conn,0,&bad_path,&sbuf);
1679 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1681 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1682 oplock_request, &rmode,&smb_action);
1686 if((errno == ENOENT) && bad_path)
1688 unix_ERR_class = ERRDOS;
1689 unix_ERR_code = ERRbadpath;
1691 END_PROFILE(SMBopenX);
1692 return(UNIXERROR(ERRDOS,ERRnoaccess));
1695 size = sbuf.st_size;
1696 fmode = dos_mode(conn,fname,&sbuf);
1697 mtime = sbuf.st_mtime;
1699 close_file(fsp,False);
1700 END_PROFILE(SMBopenX);
1701 return(ERROR(ERRDOS,ERRnoaccess));
1704 /* If the caller set the extended oplock request bit
1705 and we granted one (by whatever means) - set the
1706 correct bit for extended oplock reply.
1709 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1710 smb_action |= EXTENDED_OPLOCK_GRANTED;
1713 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1714 smb_action |= EXTENDED_OPLOCK_GRANTED;
1717 /* If the caller set the core oplock request bit
1718 and we granted one (by whatever means) - set the
1719 correct bit for core oplock reply.
1722 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1723 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1726 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1727 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1730 set_message(outbuf,15,0,True);
1731 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1732 SSVAL(outbuf,smb_vwv3,fmode);
1733 if(lp_dos_filetime_resolution(SNUM(conn)) )
1734 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1736 put_dos_date3(outbuf,smb_vwv4,mtime);
1737 SIVAL(outbuf,smb_vwv6,(uint32)size);
1738 SSVAL(outbuf,smb_vwv8,rmode);
1739 SSVAL(outbuf,smb_vwv11,smb_action);
1741 END_PROFILE(SMBopenX);
1742 return chain_reply(inbuf,outbuf,length,bufsize);
1746 /****************************************************************************
1747 reply to a SMBulogoffX
1748 ****************************************************************************/
1749 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1751 uint16 vuid = SVAL(inbuf,smb_uid);
1752 user_struct *vuser = get_valid_user_struct(vuid);
1753 START_PROFILE(SMBulogoffX);
1756 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1759 /* in user level security we are supposed to close any files
1760 open by this user */
1761 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1762 file_close_user(vuid);
1765 invalidate_vuid(vuid);
1767 set_message(outbuf,2,0,True);
1769 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1771 END_PROFILE(SMBulogoffX);
1772 return chain_reply(inbuf,outbuf,length,bufsize);
1776 /****************************************************************************
1777 reply to a mknew or a create
1778 ****************************************************************************/
1779 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1787 BOOL bad_path = False;
1789 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1790 SMB_STRUCT_STAT sbuf;
1791 START_PROFILE(SMBcreate);
1793 com = SVAL(inbuf,smb_com);
1795 createmode = SVAL(inbuf,smb_vwv0);
1796 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1798 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1800 unix_convert(fname,conn,0,&bad_path,&sbuf);
1802 if (createmode & aVOLID) {
1803 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1806 unixmode = unix_mode(conn,createmode,fname);
1810 /* We should fail if file exists. */
1811 ofun = FILE_CREATE_IF_NOT_EXIST;
1815 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1816 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1819 /* Open file in dos compatibility share mode. */
1820 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1821 ofun, unixmode, oplock_request, NULL, NULL);
1825 if((errno == ENOENT) && bad_path)
1827 unix_ERR_class = ERRDOS;
1828 unix_ERR_code = ERRbadpath;
1830 END_PROFILE(SMBcreate);
1831 return(UNIXERROR(ERRDOS,ERRnoaccess));
1834 outsize = set_message(outbuf,1,0,True);
1835 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1837 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1838 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1841 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1842 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1844 DEBUG( 2, ( "new file %s\n", fname ) );
1845 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1846 fname, fsp->fd, createmode, (int)unixmode ) );
1848 END_PROFILE(SMBcreate);
1853 /****************************************************************************
1854 reply to a create temporary file
1855 ****************************************************************************/
1856 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1863 BOOL bad_path = False;
1865 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1867 SMB_STRUCT_STAT sbuf;
1870 START_PROFILE(SMBctemp);
1872 createmode = SVAL(inbuf,smb_vwv0);
1873 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1874 pstrcat(fname,"/TMXXXXXX");
1876 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1878 unix_convert(fname,conn,0,&bad_path,&sbuf);
1880 unixmode = unix_mode(conn,createmode,fname);
1882 tmpfd = smb_mkstemp(fname);
1884 END_PROFILE(SMBctemp);
1885 return(UNIXERROR(ERRDOS,ERRnoaccess));
1888 vfs_stat(conn,fname2,&sbuf);
1890 /* Open file in dos compatibility share mode. */
1891 /* We should fail if file does not exist. */
1892 fsp = open_file_shared(conn,fname,&sbuf,
1893 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1894 FILE_FAIL_IF_NOT_EXIST,
1895 unixmode, oplock_request, NULL, NULL);
1897 /* close fd from smb_mkstemp() */
1902 if((errno == ENOENT) && bad_path)
1904 unix_ERR_class = ERRDOS;
1905 unix_ERR_code = ERRbadpath;
1907 END_PROFILE(SMBctemp);
1908 return(UNIXERROR(ERRDOS,ERRnoaccess));
1911 outsize = set_message(outbuf,1,0,True);
1912 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1913 CVAL(smb_buf(outbuf),0) = 4;
1914 p = smb_buf(outbuf) + 1;
1915 p += srvstr_push(outbuf, p, fname2, -1, STR_TERMINATE);
1916 set_message_end(outbuf, p);
1918 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1919 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1922 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1923 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1925 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1926 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1927 fname2, fsp->fd, createmode, (int)unixmode ) );
1929 END_PROFILE(SMBctemp);
1934 /*******************************************************************
1935 check if a user is allowed to delete a file
1936 ********************************************************************/
1937 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1939 SMB_STRUCT_STAT sbuf;
1942 if (!CAN_WRITE(conn)) return(False);
1944 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
1945 fmode = dos_mode(conn,fname,&sbuf);
1946 if (fmode & aDIR) return(False);
1947 if (!lp_delete_readonly(SNUM(conn))) {
1948 if (fmode & aRONLY) return(False);
1950 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1952 if (!check_file_sharing(conn,fname,False)) return(False);
1956 /****************************************************************************
1957 The guts of the unlink command, split out so it may be called by the NT SMB
1959 ****************************************************************************/
1961 int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
1962 int dirtype, char *name)
1968 int error = ERRnoaccess;
1971 BOOL bad_path = False;
1973 SMB_STRUCT_STAT sbuf;
1975 *directory = *mask = 0;
1977 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1979 p = strrchr(name,'/');
1981 pstrcpy(directory,"./");
1985 pstrcpy(directory,name);
1990 * We should only check the mangled cache
1991 * here if unix_convert failed. This means
1992 * that the path in 'mask' doesn't exist
1993 * on the file system and so we need to look
1994 * for a possible mangle. This patch from
1995 * Tine Smukavec <valentin.smukavec@hermes.si>.
1998 if (!rc && is_mangled(mask))
1999 check_mangled_cache( mask );
2001 has_wild = ms_has_wild(mask);
2004 pstrcat(directory,"/");
2005 pstrcat(directory,mask);
2006 if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory))
2009 exists = vfs_file_exist(conn,directory,&sbuf);
2011 void *dirptr = NULL;
2014 if (check_name(directory,conn))
2015 dirptr = OpenDir(conn, directory, True);
2017 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2018 the pattern matches against the long name, otherwise the short name
2019 We don't implement this yet XXXX
2026 if (strequal(mask,"????????.???"))
2029 while ((dname = ReadDirName(dirptr)))
2032 pstrcpy(fname,dname);
2034 if(!mask_match(fname, mask, case_sensitive)) continue;
2036 error = ERRnoaccess;
2037 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2038 if (!can_delete(fname,conn,dirtype)) continue;
2039 if (!vfs_unlink(conn,fname)) count++;
2040 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2048 return(ERROR(ERRDOS,error));
2050 if((errno == ENOENT) && bad_path) {
2051 unix_ERR_class = ERRDOS;
2052 unix_ERR_code = ERRbadpath;
2054 return(UNIXERROR(ERRDOS,error));
2061 /****************************************************************************
2063 ****************************************************************************/
2065 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2070 START_PROFILE(SMBunlink);
2072 dirtype = SVAL(inbuf,smb_vwv0);
2074 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
2076 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
2078 DEBUG(3,("reply_unlink : %s\n",name));
2080 outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
2084 * Win2k needs a changenotify request response before it will
2085 * update after a rename..
2088 process_pending_change_notify_queue((time_t)0);
2090 outsize = set_message(outbuf,0,0,True);
2093 END_PROFILE(SMBunlink);
2098 /****************************************************************************
2099 reply to a readbraw (core+ protocol)
2100 ****************************************************************************/
2102 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2104 size_t maxcount,mincount;
2107 char *header = outbuf;
2110 START_PROFILE(SMBreadbraw);
2113 * Special check if an oplock break has been issued
2114 * and the readraw request croses on the wire, we must
2115 * return a zero length response here.
2118 if(global_oplock_break)
2120 _smb_setlen(header,0);
2121 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2122 DEBUG(5,("readbraw - oplock break finished\n"));
2123 END_PROFILE(SMBreadbraw);
2127 fsp = file_fsp(inbuf,smb_vwv0);
2129 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2131 * fsp could be NULL here so use the value from the packet. JRA.
2133 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2134 _smb_setlen(header,0);
2135 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2136 END_PROFILE(SMBreadbraw);
2140 CHECK_FSP(fsp,conn);
2142 flush_write_cache(fsp, READRAW_FLUSH);
2144 startpos = IVAL(inbuf,smb_vwv1);
2145 if(CVAL(inbuf,smb_wct) == 10) {
2147 * This is a large offset (64 bit) read.
2149 #ifdef LARGE_SMB_OFF_T
2151 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2153 #else /* !LARGE_SMB_OFF_T */
2156 * Ensure we haven't been sent a >32 bit offset.
2159 if(IVAL(inbuf,smb_vwv8) != 0) {
2160 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2161 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2162 _smb_setlen(header,0);
2163 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2164 END_PROFILE(SMBreadbraw);
2168 #endif /* LARGE_SMB_OFF_T */
2171 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2172 (double)startpos ));
2173 _smb_setlen(header,0);
2174 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2175 END_PROFILE(SMBreadbraw);
2179 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2180 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2182 /* ensure we don't overrun the packet size */
2183 maxcount = MIN(65535,maxcount);
2184 maxcount = MAX(mincount,maxcount);
2186 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False))
2188 SMB_OFF_T size = fsp->size;
2189 SMB_OFF_T sizeneeded = startpos + maxcount;
2191 if (size < sizeneeded)
2194 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2196 if (!fsp->can_write)
2200 nread = MIN(maxcount,(size - startpos));
2203 if (nread < mincount)
2206 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2207 fsp->fnum, (double)startpos,
2208 (int)maxcount, (int)mincount, (int)nread ) );
2212 BOOL seek_fail = False;
2214 _smb_setlen(header,nread);
2216 if ((nread-predict) > 0) {
2217 if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
2218 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2225 ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
2226 (SMB_OFF_T)(nread-predict),header,4+predict,
2231 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2232 fsp->fsp_name,startpos,nread,ret));
2234 #else /* UNSAFE_READRAW */
2235 ret = read_file(fsp,header+4,startpos,nread);
2236 if (ret < mincount) ret = 0;
2238 _smb_setlen(header,ret);
2239 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2240 #endif /* UNSAFE_READRAW */
2242 DEBUG(5,("readbraw finished\n"));
2243 END_PROFILE(SMBreadbraw);
2248 /****************************************************************************
2249 reply to a lockread (core+ protocol)
2250 ****************************************************************************/
2251 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2260 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2261 START_PROFILE(SMBlockread);
2263 CHECK_FSP(fsp,conn);
2267 release_level_2_oplocks_on_change(fsp);
2269 numtoread = SVAL(inbuf,smb_vwv1);
2270 startpos = IVAL(inbuf,smb_vwv2);
2272 outsize = set_message(outbuf,5,3,True);
2273 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2274 data = smb_buf(outbuf) + 3;
2277 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2278 * protocol request that predates the read/write lock concept.
2279 * Thus instead of asking for a read lock here we need to ask
2280 * for a write lock. JRA.
2283 if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2284 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2286 * A blocking lock was requested. Package up
2287 * this smb into a queued request and push it
2288 * onto the blocking lock queue.
2290 if(push_blocking_lock_request(inbuf, length, -1, 0))
2291 END_PROFILE(SMBlockread);
2294 END_PROFILE(SMBlockread);
2295 return (ERROR(eclass,ecode));
2298 nread = read_file(fsp,data,startpos,numtoread);
2301 END_PROFILE(SMBlockread);
2302 return(UNIXERROR(ERRDOS,ERRnoaccess));
2306 SSVAL(outbuf,smb_vwv0,nread);
2307 SSVAL(outbuf,smb_vwv5,nread+3);
2308 SSVAL(smb_buf(outbuf),1,nread);
2310 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2311 fsp->fnum, (int)numtoread, (int)nread ) );
2313 END_PROFILE(SMBlockread);
2318 /****************************************************************************
2320 ****************************************************************************/
2322 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2329 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2330 START_PROFILE(SMBread);
2332 CHECK_FSP(fsp,conn);
2336 numtoread = SVAL(inbuf,smb_vwv1);
2337 startpos = IVAL(inbuf,smb_vwv2);
2339 outsize = set_message(outbuf,5,3,True);
2340 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2341 data = smb_buf(outbuf) + 3;
2343 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2344 END_PROFILE(SMBread);
2345 return(ERROR(ERRDOS,ERRlock));
2349 nread = read_file(fsp,data,startpos,numtoread);
2352 END_PROFILE(SMBread);
2353 return(UNIXERROR(ERRDOS,ERRnoaccess));
2357 SSVAL(outbuf,smb_vwv0,nread);
2358 SSVAL(outbuf,smb_vwv5,nread+3);
2359 CVAL(smb_buf(outbuf),0) = 1;
2360 SSVAL(smb_buf(outbuf),1,nread);
2362 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2363 fsp->fnum, (int)numtoread, (int)nread ) );
2365 END_PROFILE(SMBread);
2370 /****************************************************************************
2371 reply to a read and X
2372 ****************************************************************************/
2373 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2375 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2376 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2377 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2378 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2381 START_PROFILE(SMBreadX);
2383 /* If it's an IPC, pass off the pipe handler. */
2385 END_PROFILE(SMBreadX);
2386 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2389 CHECK_FSP(fsp,conn);
2393 set_message(outbuf,12,0,True);
2394 data = smb_buf(outbuf);
2396 if(CVAL(inbuf,smb_wct) == 12) {
2397 #ifdef LARGE_SMB_OFF_T
2399 * This is a large offset (64 bit) read.
2401 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2403 #else /* !LARGE_SMB_OFF_T */
2406 * Ensure we haven't been sent a >32 bit offset.
2409 if(IVAL(inbuf,smb_vwv10) != 0) {
2410 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2411 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2412 END_PROFILE(SMBreadX);
2413 return(ERROR(ERRDOS,ERRbadaccess));
2416 #endif /* LARGE_SMB_OFF_T */
2420 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2421 END_PROFILE(SMBreadX);
2422 return(ERROR(ERRDOS,ERRlock));
2424 nread = read_file(fsp,data,startpos,smb_maxcnt);
2427 END_PROFILE(SMBreadX);
2428 return(UNIXERROR(ERRDOS,ERRnoaccess));
2431 SSVAL(outbuf,smb_vwv5,nread);
2432 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2433 SSVAL(smb_buf(outbuf),-2,nread);
2435 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2436 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2438 END_PROFILE(SMBreadX);
2439 return chain_reply(inbuf,outbuf,length,bufsize);
2442 /****************************************************************************
2443 reply to a writebraw (core+ or LANMAN1.0 protocol)
2444 ****************************************************************************/
2446 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2449 ssize_t total_written=0;
2450 size_t numtowrite=0;
2455 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2457 START_PROFILE(SMBwritebraw);
2459 CHECK_FSP(fsp,conn);
2463 tcount = IVAL(inbuf,smb_vwv1);
2464 startpos = IVAL(inbuf,smb_vwv3);
2465 write_through = BITSETW(inbuf+smb_vwv7,0);
2467 /* We have to deal with slightly different formats depending
2468 on whether we are using the core+ or lanman1.0 protocol */
2469 if(Protocol <= PROTOCOL_COREPLUS) {
2470 numtowrite = SVAL(smb_buf(inbuf),-2);
2471 data = smb_buf(inbuf);
2473 numtowrite = SVAL(inbuf,smb_vwv10);
2474 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2477 /* force the error type */
2478 CVAL(inbuf,smb_com) = SMBwritec;
2479 CVAL(outbuf,smb_com) = SMBwritec;
2481 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2482 END_PROFILE(SMBwritebraw);
2483 return(ERROR(ERRDOS,ERRlock));
2487 nwritten = write_file(fsp,data,startpos,numtowrite);
2489 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2490 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2492 if (nwritten < numtowrite) {
2493 END_PROFILE(SMBwritebraw);
2494 return(UNIXERROR(ERRHRD,ERRdiskfull));
2497 total_written = nwritten;
2499 /* Return a message to the redirector to tell it
2500 to send more bytes */
2501 CVAL(outbuf,smb_com) = SMBwritebraw;
2502 SSVALS(outbuf,smb_vwv0,-1);
2503 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2504 if (!send_smb(smbd_server_fd(),outbuf))
2505 exit_server("reply_writebraw: send_smb failed.\n");
2507 /* Now read the raw data into the buffer and write it */
2508 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2509 exit_server("secondary writebraw failed");
2512 /* Even though this is not an smb message, smb_len
2513 returns the generic length of an smb message */
2514 numtowrite = smb_len(inbuf);
2516 if (tcount > nwritten+numtowrite) {
2517 DEBUG(3,("Client overestimated the write %d %d %d\n",
2518 (int)tcount,(int)nwritten,(int)numtowrite));
2521 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2522 (SMB_OFF_T)numtowrite,NULL,0,
2524 total_written += nwritten;
2526 /* Set up outbuf to return the correct return */
2527 outsize = set_message(outbuf,1,0,True);
2528 CVAL(outbuf,smb_com) = SMBwritec;
2529 SSVAL(outbuf,smb_vwv0,total_written);
2531 if (nwritten < (ssize_t)numtowrite) {
2532 CVAL(outbuf,smb_rcls) = ERRHRD;
2533 SSVAL(outbuf,smb_err,ERRdiskfull);
2536 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2537 lp_strict_sync(SNUM(conn)))
2538 sync_file(conn,fsp);
2540 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2541 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2543 /* we won't return a status if write through is not selected - this
2544 follows what WfWg does */
2545 END_PROFILE(SMBwritebraw);
2546 if (!write_through && total_written==tcount) {
2553 /****************************************************************************
2554 reply to a writeunlock (core+)
2555 ****************************************************************************/
2557 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2559 ssize_t nwritten = -1;
2565 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2567 START_PROFILE(SMBwriteunlock);
2569 CHECK_FSP(fsp,conn);
2573 numtowrite = SVAL(inbuf,smb_vwv1);
2574 startpos = IVAL(inbuf,smb_vwv2);
2575 data = smb_buf(inbuf) + 3;
2577 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2578 END_PROFILE(SMBwriteunlock);
2579 return(ERROR(ERRDOS,ERRlock));
2582 /* The special X/Open SMB protocol handling of
2583 zero length writes is *NOT* done for
2588 nwritten = write_file(fsp,data,startpos,numtowrite);
2590 if (lp_syncalways(SNUM(conn)))
2591 sync_file(conn,fsp);
2593 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2594 END_PROFILE(SMBwriteunlock);
2595 return(UNIXERROR(ERRDOS,ERRnoaccess));
2598 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) {
2599 END_PROFILE(SMBwriteunlock);
2600 return(ERROR(eclass,ecode));
2603 outsize = set_message(outbuf,1,0,True);
2605 SSVAL(outbuf,smb_vwv0,nwritten);
2607 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2608 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2610 END_PROFILE(SMBwriteunlock);
2614 /****************************************************************************
2616 ****************************************************************************/
2617 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2620 ssize_t nwritten = -1;
2623 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2625 START_PROFILE(SMBwrite);
2627 /* If it's an IPC, pass off the pipe handler. */
2629 END_PROFILE(SMBwrite);
2630 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2633 CHECK_FSP(fsp,conn);
2637 numtowrite = SVAL(inbuf,smb_vwv1);
2638 startpos = IVAL(inbuf,smb_vwv2);
2639 data = smb_buf(inbuf) + 3;
2641 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2642 END_PROFILE(SMBwrite);
2643 return(ERROR(ERRDOS,ERRlock));
2646 /* X/Open SMB protocol says that if smb_vwv1 is
2647 zero then the file size should be extended or
2648 truncated to the size given in smb_vwv[2-3] */
2649 if(numtowrite == 0) {
2650 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2652 nwritten = write_file(fsp,data,startpos,numtowrite);
2654 if (lp_syncalways(SNUM(conn)))
2655 sync_file(conn,fsp);
2657 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2658 END_PROFILE(SMBwrite);
2659 return(UNIXERROR(ERRDOS,ERRnoaccess));
2662 outsize = set_message(outbuf,1,0,True);
2664 SSVAL(outbuf,smb_vwv0,nwritten);
2666 if (nwritten < (ssize_t)numtowrite) {
2667 CVAL(outbuf,smb_rcls) = ERRHRD;
2668 SSVAL(outbuf,smb_err,ERRdiskfull);
2671 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2672 fsp->fnum, (int)numtowrite, (int)nwritten));
2674 END_PROFILE(SMBwrite);
2679 /****************************************************************************
2680 reply to a write and X
2681 ****************************************************************************/
2682 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2684 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2685 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2686 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2687 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2688 ssize_t nwritten = -1;
2689 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2690 unsigned int smblen = smb_len(inbuf);
2692 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2693 START_PROFILE(SMBwriteX);
2695 /* If it's an IPC, pass off the pipe handler. */
2697 END_PROFILE(SMBwriteX);
2698 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2701 CHECK_FSP(fsp,conn);
2705 /* Deal with possible LARGE_WRITEX */
2707 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2709 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2710 END_PROFILE(SMBwriteX);
2711 return(ERROR(ERRDOS,ERRbadmem));
2714 data = smb_base(inbuf) + smb_doff;
2716 if(CVAL(inbuf,smb_wct) == 14) {
2717 #ifdef LARGE_SMB_OFF_T
2719 * This is a large offset (64 bit) write.
2721 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2723 #else /* !LARGE_SMB_OFF_T */
2726 * Ensure we haven't been sent a >32 bit offset.
2729 if(IVAL(inbuf,smb_vwv12) != 0) {
2730 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2731 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2732 END_PROFILE(SMBwriteX);
2733 return(ERROR(ERRDOS,ERRbadaccess));
2736 #endif /* LARGE_SMB_OFF_T */
2739 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2740 END_PROFILE(SMBwriteX);
2741 return(ERROR(ERRDOS,ERRlock));
2744 /* X/Open SMB protocol says that, unlike SMBwrite
2745 if the length is zero then NO truncation is
2746 done, just a write of zero. To truncate a file,
2751 nwritten = write_file(fsp,data,startpos,numtowrite);
2753 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2754 END_PROFILE(SMBwriteX);
2755 return(UNIXERROR(ERRDOS,ERRnoaccess));
2758 set_message(outbuf,6,0,True);
2760 SSVAL(outbuf,smb_vwv2,nwritten);
2762 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2764 if (nwritten < (ssize_t)numtowrite) {
2765 CVAL(outbuf,smb_rcls) = ERRHRD;
2766 SSVAL(outbuf,smb_err,ERRdiskfull);
2769 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2770 fsp->fnum, (int)numtowrite, (int)nwritten));
2772 if (lp_syncalways(SNUM(conn)) || write_through)
2773 sync_file(conn,fsp);
2775 END_PROFILE(SMBwriteX);
2776 return chain_reply(inbuf,outbuf,length,bufsize);
2780 /****************************************************************************
2782 ****************************************************************************/
2784 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2790 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2791 START_PROFILE(SMBlseek);
2793 CHECK_FSP(fsp,conn);
2796 flush_write_cache(fsp, SEEK_FLUSH);
2798 mode = SVAL(inbuf,smb_vwv1) & 3;
2799 startpos = IVALS(inbuf,smb_vwv2);
2802 case 0: umode = SEEK_SET; break;
2803 case 1: umode = SEEK_CUR; break;
2804 case 2: umode = SEEK_END; break;
2806 umode = SEEK_SET; break;
2809 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2811 * Check for the special case where a seek before the start
2812 * of the file sets the offset to zero. Added in the CIFS spec,
2816 if(errno == EINVAL) {
2817 SMB_OFF_T current_pos = startpos;
2819 if(umode == SEEK_CUR) {
2821 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2822 END_PROFILE(SMBlseek);
2823 return(UNIXERROR(ERRDOS,ERRnoaccess));
2826 current_pos += startpos;
2828 } else if (umode == SEEK_END) {
2830 SMB_STRUCT_STAT sbuf;
2832 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2833 END_PROFILE(SMBlseek);
2834 return(UNIXERROR(ERRDOS,ERRnoaccess));
2837 current_pos += sbuf.st_size;
2841 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2845 END_PROFILE(SMBlseek);
2846 return(UNIXERROR(ERRDOS,ERRnoaccess));
2852 outsize = set_message(outbuf,2,0,True);
2853 SIVAL(outbuf,smb_vwv0,res);
2855 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2856 fsp->fnum, (double)startpos, (double)res, mode));
2858 END_PROFILE(SMBlseek);
2862 /****************************************************************************
2864 ****************************************************************************/
2866 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2868 int outsize = set_message(outbuf,0,0,True);
2869 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2870 START_PROFILE(SMBflush);
2873 CHECK_FSP(fsp,conn);
2878 file_sync_all(conn);
2880 sync_file(conn,fsp);
2883 DEBUG(3,("flush\n"));
2884 END_PROFILE(SMBflush);
2889 /****************************************************************************
2891 ****************************************************************************/
2892 int reply_exit(connection_struct *conn,
2893 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2896 START_PROFILE(SMBexit);
2897 outsize = set_message(outbuf,0,0,True);
2899 DEBUG(3,("exit\n"));
2901 END_PROFILE(SMBexit);
2906 /****************************************************************************
2907 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2908 ****************************************************************************/
2909 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2914 int32 eclass = 0, err = 0;
2915 files_struct *fsp = NULL;
2916 START_PROFILE(SMBclose);
2918 outsize = set_message(outbuf,0,0,True);
2920 /* If it's an IPC, pass off to the pipe handler. */
2922 END_PROFILE(SMBclose);
2923 return reply_pipe_close(conn, inbuf,outbuf);
2926 fsp = file_fsp(inbuf,smb_vwv0);
2929 * We can only use CHECK_FSP if we know it's not a directory.
2932 if(!fsp || (fsp->conn != conn)) {
2933 END_PROFILE(SMBclose);
2934 return(ERROR(ERRDOS,ERRbadfid));
2937 if(HAS_CACHED_ERROR(fsp)) {
2938 eclass = fsp->wbmpx_ptr->wr_errclass;
2939 err = fsp->wbmpx_ptr->wr_error;
2942 if(fsp->is_directory || fsp->stat_open) {
2944 * Special case - close NT SMB directory or stat file
2947 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2948 close_file(fsp,True);
2951 * Close ordinary file.
2956 * If there was a modify time outstanding,
2957 * try and set it here.
2959 if(fsp->pending_modtime)
2960 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2963 * Now take care of any time sent in the close.
2965 mtime = make_unix_date3(inbuf+smb_vwv1);
2967 /* try and set the date */
2968 set_filetime(conn, fsp->fsp_name,mtime);
2970 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2972 conn->num_files_open));
2975 * close_file() returns the unix errno if an error
2976 * was detected on close - normally this is due to
2977 * a disk full error. If not then it was probably an I/O error.
2980 if((close_err = close_file(fsp,True)) != 0) {
2982 END_PROFILE(SMBclose);
2983 return (UNIXERROR(ERRHRD,ERRgeneral));
2987 /* We have a cached error */
2989 END_PROFILE(SMBclose);
2990 return(ERROR(eclass,err));
2993 END_PROFILE(SMBclose);
2998 /****************************************************************************
2999 reply to a writeclose (Core+ protocol)
3000 ****************************************************************************/
3002 int reply_writeclose(connection_struct *conn,
3003 char *inbuf,char *outbuf, int size, int dum_buffsize)
3006 ssize_t nwritten = -1;
3012 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3013 START_PROFILE(SMBwriteclose);
3015 CHECK_FSP(fsp,conn);
3019 numtowrite = SVAL(inbuf,smb_vwv1);
3020 startpos = IVAL(inbuf,smb_vwv2);
3021 mtime = make_unix_date3(inbuf+smb_vwv4);
3022 data = smb_buf(inbuf) + 1;
3024 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
3025 END_PROFILE(SMBwriteclose);
3026 return(ERROR(ERRDOS,ERRlock));
3029 nwritten = write_file(fsp,data,startpos,numtowrite);
3031 set_filetime(conn, fsp->fsp_name,mtime);
3033 close_err = close_file(fsp,True);
3035 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3036 fsp->fnum, (int)numtowrite, (int)nwritten,
3037 conn->num_files_open));
3039 if (nwritten <= 0) {
3040 END_PROFILE(SMBwriteclose);
3041 return(UNIXERROR(ERRDOS,ERRnoaccess));
3044 if(close_err != 0) {
3046 END_PROFILE(SMBwriteclose);
3047 return(UNIXERROR(ERRHRD,ERRgeneral));
3050 outsize = set_message(outbuf,1,0,True);
3052 SSVAL(outbuf,smb_vwv0,nwritten);
3053 END_PROFILE(SMBwriteclose);
3058 /****************************************************************************
3060 ****************************************************************************/
3061 int reply_lock(connection_struct *conn,
3062 char *inbuf,char *outbuf, int length, int dum_buffsize)
3064 int outsize = set_message(outbuf,0,0,True);
3065 SMB_BIG_UINT count,offset;
3068 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3069 START_PROFILE(SMBlock);
3071 CHECK_FSP(fsp,conn);
3074 release_level_2_oplocks_on_change(fsp);
3076 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3077 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3079 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3080 fsp->fd, fsp->fnum, (double)offset, (double)count));
3082 if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &eclass, &ecode)) {
3083 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
3085 * A blocking lock was requested. Package up
3086 * this smb into a queued request and push it
3087 * onto the blocking lock queue.
3089 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
3090 END_PROFILE(SMBlock);
3094 END_PROFILE(SMBlock);
3095 return (ERROR(eclass,ecode));
3098 END_PROFILE(SMBlock);
3103 /****************************************************************************
3105 ****************************************************************************/
3106 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3108 int outsize = set_message(outbuf,0,0,True);
3109 SMB_BIG_UINT count,offset;
3112 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3113 START_PROFILE(SMBunlock);
3115 CHECK_FSP(fsp,conn);
3118 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3119 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3121 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, &eclass, &ecode)) {
3122 END_PROFILE(SMBunlock);
3123 return (ERROR(eclass,ecode));
3126 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3127 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3129 END_PROFILE(SMBunlock);
3134 /****************************************************************************
3136 ****************************************************************************/
3137 int reply_tdis(connection_struct *conn,
3138 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3140 int outsize = set_message(outbuf,0,0,True);
3142 START_PROFILE(SMBtdis);
3144 vuid = SVAL(inbuf,smb_uid);
3147 DEBUG(4,("Invalid connection in tdis\n"));
3148 END_PROFILE(SMBtdis);
3149 return(ERROR(ERRSRV,ERRinvnid));
3154 close_cnum(conn,vuid);
3156 END_PROFILE(SMBtdis);
3162 /****************************************************************************
3164 ****************************************************************************/
3165 int reply_echo(connection_struct *conn,
3166 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3168 int smb_reverb = SVAL(inbuf,smb_vwv0);
3170 unsigned int data_len = smb_buflen(inbuf);
3171 int outsize = set_message(outbuf,1,data_len,True);
3172 START_PROFILE(SMBecho);
3174 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3176 /* copy any incoming data back out */
3178 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3180 if (smb_reverb > 100) {
3181 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3185 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3186 SSVAL(outbuf,smb_vwv0,seq_num);
3188 smb_setlen(outbuf,outsize - 4);
3190 if (!send_smb(smbd_server_fd(),outbuf))
3191 exit_server("reply_echo: send_smb failed.\n");
3194 DEBUG(3,("echo %d times\n", smb_reverb));
3198 END_PROFILE(SMBecho);
3203 /****************************************************************************
3204 reply to a printopen
3205 ****************************************************************************/
3206 int reply_printopen(connection_struct *conn,
3207 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3211 START_PROFILE(SMBsplopen);
3213 if (!CAN_PRINT(conn)) {
3214 END_PROFILE(SMBsplopen);
3215 return(ERROR(ERRDOS,ERRnoaccess));
3218 /* Open for exclusive use, write only. */
3219 fsp = print_fsp_open(conn);
3222 END_PROFILE(SMBsplopen);
3223 return(UNIXERROR(ERRDOS,ERRnoaccess));
3226 outsize = set_message(outbuf,1,0,True);
3227 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3229 DEBUG(3,("openprint fd=%d fnum=%d\n",
3230 fsp->fd, fsp->fnum));
3232 END_PROFILE(SMBsplopen);
3237 /****************************************************************************
3238 reply to a printclose
3239 ****************************************************************************/
3240 int reply_printclose(connection_struct *conn,
3241 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3243 int outsize = set_message(outbuf,0,0,True);
3244 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3246 START_PROFILE(SMBsplclose);
3248 CHECK_FSP(fsp,conn);
3251 if (!CAN_PRINT(conn)) {
3252 END_PROFILE(SMBsplclose);
3253 return(ERROR(ERRDOS,ERRnoaccess));
3256 DEBUG(3,("printclose fd=%d fnum=%d\n",
3257 fsp->fd,fsp->fnum));
3259 close_err = close_file(fsp,True);
3261 if(close_err != 0) {
3263 END_PROFILE(SMBsplclose);
3264 return(UNIXERROR(ERRHRD,ERRgeneral));
3267 END_PROFILE(SMBsplclose);
3272 /****************************************************************************
3273 reply to a printqueue
3274 ****************************************************************************/
3275 int reply_printqueue(connection_struct *conn,
3276 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3278 int outsize = set_message(outbuf,2,3,True);
3279 int max_count = SVAL(inbuf,smb_vwv0);
3280 int start_index = SVAL(inbuf,smb_vwv1);
3281 START_PROFILE(SMBsplretq);
3283 /* we used to allow the client to get the cnum wrong, but that
3284 is really quite gross and only worked when there was only
3285 one printer - I think we should now only accept it if they
3286 get it right (tridge) */
3287 if (!CAN_PRINT(conn)) {
3288 END_PROFILE(SMBsplretq);
3289 return(ERROR(ERRDOS,ERRnoaccess));
3292 SSVAL(outbuf,smb_vwv0,0);
3293 SSVAL(outbuf,smb_vwv1,0);
3294 CVAL(smb_buf(outbuf),0) = 1;
3295 SSVAL(smb_buf(outbuf),1,0);
3297 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3298 start_index, max_count));
3301 print_queue_struct *queue = NULL;
3302 char *p = smb_buf(outbuf) + 3;
3303 int count = print_queue_status(SNUM(conn), &queue,NULL);
3304 int num_to_get = ABS(max_count);
3305 int first = (max_count>0?start_index:start_index+max_count+1);
3311 num_to_get = MIN(num_to_get,count-first);
3314 for (i=first;i<first+num_to_get;i++) {
3315 put_dos_date2(p,0,queue[i].time);
3316 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3317 SSVAL(p,5, queue[i].job);
3318 SIVAL(p,7,queue[i].size);
3320 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII);
3325 outsize = set_message(outbuf,2,28*count+3,False);
3326 SSVAL(outbuf,smb_vwv0,count);
3327 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3328 CVAL(smb_buf(outbuf),0) = 1;
3329 SSVAL(smb_buf(outbuf),1,28*count);
3332 if (queue) free(queue);
3334 DEBUG(3,("%d entries returned in queue\n",count));
3337 END_PROFILE(SMBsplretq);
3342 /****************************************************************************
3343 reply to a printwrite
3344 ****************************************************************************/
3345 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3348 int outsize = set_message(outbuf,0,0,True);
3350 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3351 START_PROFILE(SMBsplwr);
3353 if (!CAN_PRINT(conn)) {
3354 END_PROFILE(SMBsplwr);
3355 return(ERROR(ERRDOS,ERRnoaccess));
3358 CHECK_FSP(fsp,conn);
3362 numtowrite = SVAL(smb_buf(inbuf),1);
3363 data = smb_buf(inbuf) + 3;
3365 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3366 END_PROFILE(SMBsplwr);
3367 return(UNIXERROR(ERRDOS,ERRnoaccess));
3370 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3372 END_PROFILE(SMBsplwr);
3377 /****************************************************************************
3378 The guts of the mkdir command, split out so it may be called by the NT SMB
3380 ****************************************************************************/
3381 int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
3383 BOOL bad_path = False;
3384 SMB_STRUCT_STAT sbuf;
3387 unix_convert(directory,conn,0,&bad_path,&sbuf);
3389 if (check_name(directory, conn))
3390 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3394 if((errno == ENOENT) && bad_path)
3396 unix_ERR_class = ERRDOS;
3397 unix_ERR_code = ERRbadpath;
3399 return(UNIXERROR(ERRDOS,ERRnoaccess));
3405 /****************************************************************************
3407 ****************************************************************************/
3408 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3412 START_PROFILE(SMBmkdir);
3414 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3416 outsize=mkdir_internal(conn, inbuf, outbuf, directory);
3418 outsize = set_message(outbuf,0,0,True);
3420 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3422 END_PROFILE(SMBmkdir);
3426 /****************************************************************************
3427 Static function used by reply_rmdir to delete an entire directory
3429 ****************************************************************************/
3431 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3435 void *dirptr = OpenDir(NULL, directory, False);
3440 while((dname = ReadDirName(dirptr)))
3445 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3448 /* Construct the full name. */
3449 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3455 pstrcpy(fullname, directory);
3456 pstrcat(fullname, "/");
3457 pstrcat(fullname, dname);
3459 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3465 if(st.st_mode & S_IFDIR)
3467 if(recursive_rmdir(conn, fullname)!=0)
3472 if(vfs_rmdir(conn,fullname) != 0)
3478 else if(vfs_unlink(conn,fullname) != 0)
3488 /****************************************************************************
3489 The internals of the rmdir code - called elsewhere.
3490 ****************************************************************************/
3492 BOOL rmdir_internals(connection_struct *conn, char *directory)
3496 ok = (vfs_rmdir(conn,directory) == 0);
3497 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3500 * Check to see if the only thing in this directory are
3501 * vetoed files/directories. If so then delete them and
3502 * retry. If we fail to delete any of them (and we *don't*
3503 * do a recursive delete) then fail the rmdir.
3505 BOOL all_veto_files = True;
3507 void *dirptr = OpenDir(conn, directory, False);
3511 int dirpos = TellDir(dirptr);
3512 while ((dname = ReadDirName(dirptr)))
3514 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3516 if(!IS_VETO_PATH(conn, dname))
3518 all_veto_files = False;
3524 SeekDir(dirptr,dirpos);
3525 while ((dname = ReadDirName(dirptr)))
3530 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3533 /* Construct the full name. */
3534 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3539 pstrcpy(fullname, directory);
3540 pstrcat(fullname, "/");
3541 pstrcat(fullname, dname);
3543 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3545 if(st.st_mode & S_IFDIR)
3547 if(lp_recursive_veto_delete(SNUM(conn)))
3549 if(recursive_rmdir(conn, fullname) != 0)
3552 if(vfs_rmdir(conn,fullname) != 0)
3555 else if(vfs_unlink(conn,fullname) != 0)
3559 /* Retry the rmdir */
3560 ok = (vfs_rmdir(conn,directory) == 0);
3570 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3571 directory,strerror(errno)));
3576 /****************************************************************************
3578 ****************************************************************************/
3580 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3585 BOOL bad_path = False;
3586 SMB_STRUCT_STAT sbuf;
3587 START_PROFILE(SMBrmdir);
3589 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3591 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3593 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3595 if (check_name(directory,conn))
3597 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3598 ok = rmdir_internals(conn, directory);
3603 if((errno == ENOENT) && bad_path)
3605 unix_ERR_class = ERRDOS;
3606 unix_ERR_code = ERRbadpath;
3608 END_PROFILE(SMBrmdir);
3609 return(UNIXERROR(ERRDOS,ERRbadpath));
3612 outsize = set_message(outbuf,0,0,True);
3614 DEBUG( 3, ( "rmdir %s\n", directory ) );
3616 END_PROFILE(SMBrmdir);
3621 /*******************************************************************
3622 resolve wildcards in a filename rename
3623 ********************************************************************/
3624 static BOOL resolve_wildcards(char *name1,char *name2)
3626 fstring root1,root2;
3630 name1 = strrchr(name1,'/');
3631 name2 = strrchr(name2,'/');
3633 if (!name1 || !name2) return(False);
3635 fstrcpy(root1,name1);
3636 fstrcpy(root2,name2);
3637 p = strrchr(root1,'.');
3644 p = strrchr(root2,'.');
3676 pstrcpy(name2,root2);
3679 pstrcat(name2,ext2);
3685 /*******************************************************************
3686 check if a user is allowed to rename a file
3687 ********************************************************************/
3688 static BOOL can_rename(char *fname,connection_struct *conn)
3690 SMB_STRUCT_STAT sbuf;
3692 if (!CAN_WRITE(conn)) return(False);
3694 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
3695 if (!check_file_sharing(conn,fname,True)) return(False);
3699 /****************************************************************************
3700 The guts of the rename command, split out so it may be called by the NT SMB
3702 ****************************************************************************/
3703 int rename_internals(connection_struct *conn,
3704 char *inbuf, char *outbuf, char *name,
3705 char *newname, BOOL replace_if_exists)
3709 pstring newname_last_component;
3712 BOOL bad_path1 = False;
3713 BOOL bad_path2 = False;
3715 int error = ERRnoaccess;
3718 SMB_STRUCT_STAT sbuf1, sbuf2;
3720 *directory = *mask = 0;
3722 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3723 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3726 * Split the old name into directory and last component
3727 * strings. Note that unix_convert may have stripped off a
3728 * leading ./ from both name and newname if the rename is
3729 * at the root of the share. We need to make sure either both
3730 * name and newname contain a / character or neither of them do
3731 * as this is checked in resolve_wildcards().
3734 p = strrchr(name,'/');
3736 pstrcpy(directory,".");
3740 pstrcpy(directory,name);
3742 *p = '/'; /* Replace needed for exceptional test below. */
3746 * We should only check the mangled cache
3747 * here if unix_convert failed. This means
3748 * that the path in 'mask' doesn't exist
3749 * on the file system and so we need to look
3750 * for a possible mangle. This patch from
3751 * Tine Smukavec <valentin.smukavec@hermes.si>.
3754 if (!rc && is_mangled(mask))
3755 check_mangled_cache( mask );
3757 has_wild = ms_has_wild(mask);
3761 * No wildcards - just process the one file.
3763 BOOL is_short_name = is_8_3(name, True);
3765 /* Add a terminating '/' to the directory name. */
3766 pstrcat(directory,"/");
3767 pstrcat(directory,mask);
3769 /* Ensure newname contains a '/' also */
3770 if(strrchr(newname,'/') == 0) {
3773 pstrcpy(tmpstr, "./");
3774 pstrcat(tmpstr, newname);
3775 pstrcpy(newname, tmpstr);
3778 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",
3779 case_sensitive, case_preserve, short_case_preserve, directory,
3780 newname, newname_last_component, is_short_name));
3783 * Check for special case with case preserving and not
3784 * case sensitive, if directory and newname are identical,
3785 * and the old last component differs from the original
3786 * last component only by case, then we should allow
3787 * the rename (user is trying to change the case of the
3790 if((case_sensitive == False) &&
3791 (((case_preserve == True) &&
3792 (is_short_name == False)) ||
3793 ((short_case_preserve == True) &&
3794 (is_short_name == True))) &&
3795 strcsequal(directory, newname)) {
3796 pstring newname_modified_last_component;
3799 * Get the last component of the modified name.
3800 * Note that we guarantee that newname contains a '/'
3803 p = strrchr(newname,'/');
3804 pstrcpy(newname_modified_last_component,p+1);
3806 if(strcsequal(newname_modified_last_component,
3807 newname_last_component) == False) {
3809 * Replace the modified last component with
3812 pstrcpy(p+1, newname_last_component);
3816 if(replace_if_exists) {
3818 * NT SMB specific flag - rename can overwrite
3819 * file with the same name so don't check for
3823 if(resolve_wildcards(directory,newname) &&
3824 can_rename(directory,conn) &&
3825 !conn->vfs_ops.rename(conn,directory,newname))
3828 if (resolve_wildcards(directory,newname) &&
3829 can_rename(directory,conn) &&
3830 !vfs_file_exist(conn,newname,NULL) &&
3831 !conn->vfs_ops.rename(conn,directory,newname))
3835 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3836 directory,newname));
3838 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3839 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3845 * Wildcards - process each file that matches.
3847 void *dirptr = NULL;
3851 if (check_name(directory,conn))
3852 dirptr = OpenDir(conn, directory, True);
3857 if (strequal(mask,"????????.???"))
3860 while ((dname = ReadDirName(dirptr))) {
3863 pstrcpy(fname,dname);
3865 if(!mask_match(fname, mask, case_sensitive))
3868 error = ERRnoaccess;
3869 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3870 if (!can_rename(fname,conn)) {
3871 DEBUG(6,("rename %s refused\n", fname));
3874 pstrcpy(destname,newname);
3876 if (!resolve_wildcards(fname,destname)) {
3877 DEBUG(6,("resolve_wildcards %s %s failed\n",
3882 if (!replace_if_exists &&
3883 vfs_file_exist(conn,destname, NULL)) {
3884 DEBUG(6,("file_exist %s\n", destname));
3889 if (!conn->vfs_ops.rename(conn,fname,destname))
3891 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3899 return(ERROR(ERRDOS,error));
3901 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3902 unix_ERR_class = ERRDOS;
3903 unix_ERR_code = ERRbadpath;
3905 return(UNIXERROR(ERRDOS,error));
3912 /****************************************************************************
3914 ****************************************************************************/
3916 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3923 START_PROFILE(SMBmv);
3925 p = smb_buf(inbuf) + 1;
3926 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3928 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3930 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3931 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3933 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3935 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3939 * Win2k needs a changenotify request response before it will
3940 * update after a rename..
3943 process_pending_change_notify_queue((time_t)0);
3945 outsize = set_message(outbuf,0,0,True);
3952 /*******************************************************************
3953 copy a file as part of a reply_copy
3954 ******************************************************************/
3956 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3957 int count,BOOL target_is_directory, int *err_ret)
3960 SMB_STRUCT_STAT src_sbuf, sbuf2;
3962 files_struct *fsp1,*fsp2;
3967 pstrcpy(dest,dest1);
3968 if (target_is_directory) {
3969 char *p = strrchr(src,'/');
3978 if (!vfs_file_exist(conn,src,&src_sbuf))
3981 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3982 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3988 if (!target_is_directory && count)
3989 ofun = FILE_EXISTS_OPEN;
3991 vfs_stat(conn,dest,&sbuf2);
3992 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3993 ofun,src_sbuf.st_mode,0,&Access,&action);
3996 close_file(fsp1,False);
4000 if ((ofun&3) == 1) {
4001 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4002 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
4005 * Stop the copy from occurring.
4008 src_sbuf.st_size = 0;
4012 if (src_sbuf.st_size)
4013 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
4015 close_file(fsp1,False);
4017 * As we are opening fsp1 read-only we only expect
4018 * an error on close on fsp2 if we are out of space.
4019 * Thus we don't look at the error return from the
4022 *err_ret = close_file(fsp2,False);
4024 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4029 /****************************************************************************
4030 reply to a file copy.
4031 ****************************************************************************/
4032 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4037 pstring mask,newname;
4040 int error = ERRnoaccess;
4044 int tid2 = SVAL(inbuf,smb_vwv0);
4045 int ofun = SVAL(inbuf,smb_vwv1);
4046 int flags = SVAL(inbuf,smb_vwv2);
4047 BOOL target_is_directory=False;
4048 BOOL bad_path1 = False;
4049 BOOL bad_path2 = False;
4051 SMB_STRUCT_STAT sbuf1, sbuf2;
4052 START_PROFILE(SMBcopy);
4054 *directory = *mask = 0;
4057 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
4058 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
4060 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4062 if (tid2 != conn->cnum) {
4063 /* can't currently handle inter share copies XXXX */
4064 DEBUG(3,("Rejecting inter-share copy\n"));
4065 END_PROFILE(SMBcopy);
4066 return(ERROR(ERRSRV,ERRinvdevice));
4069 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4070 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4072 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4073 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4075 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4077 if ((flags&1) && target_is_directory) {
4078 END_PROFILE(SMBcopy);
4079 return(ERROR(ERRDOS,ERRbadfile));
4082 if ((flags&2) && !target_is_directory) {
4083 END_PROFILE(SMBcopy);
4084 return(ERROR(ERRDOS,ERRbadpath));
4087 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4088 /* wants a tree copy! XXXX */
4089 DEBUG(3,("Rejecting tree copy\n"));
4090 END_PROFILE(SMBcopy);
4091 return(ERROR(ERRSRV,ERRerror));
4094 p = strrchr(name,'/');
4096 pstrcpy(directory,"./");
4100 pstrcpy(directory,name);
4105 * We should only check the mangled cache
4106 * here if unix_convert failed. This means
4107 * that the path in 'mask' doesn't exist
4108 * on the file system and so we need to look
4109 * for a possible mangle. This patch from
4110 * Tine Smukavec <valentin.smukavec@hermes.si>.
4113 if (!rc && is_mangled(mask))
4114 check_mangled_cache( mask );
4116 has_wild = ms_has_wild(mask);
4119 pstrcat(directory,"/");
4120 pstrcat(directory,mask);
4121 if (resolve_wildcards(directory,newname) &&
4122 copy_file(directory,newname,conn,ofun,
4123 count,target_is_directory,&err)) count++;
4126 END_PROFILE(SMBcopy);
4127 return(UNIXERROR(ERRHRD,ERRgeneral));
4129 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4131 void *dirptr = NULL;
4135 if (check_name(directory,conn))
4136 dirptr = OpenDir(conn, directory, True);
4141 if (strequal(mask,"????????.???"))
4144 while ((dname = ReadDirName(dirptr))) {
4146 pstrcpy(fname,dname);
4148 if(!mask_match(fname, mask, case_sensitive))
4151 error = ERRnoaccess;
4152 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4153 pstrcpy(destname,newname);
4154 if (resolve_wildcards(fname,destname) &&
4155 copy_file(fname,destname,conn,ofun,
4156 count,target_is_directory,&err)) count++;
4157 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4165 /* Error on close... */
4167 END_PROFILE(SMBcopy);
4168 return(UNIXERROR(ERRHRD,ERRgeneral));
4172 END_PROFILE(SMBcopy);
4173 return(ERROR(ERRDOS,error));
4176 if((errno == ENOENT) && (bad_path1 || bad_path2))
4178 unix_ERR_class = ERRDOS;
4179 unix_ERR_code = ERRbadpath;
4181 END_PROFILE(SMBcopy);
4182 return(UNIXERROR(ERRDOS,error));
4186 outsize = set_message(outbuf,1,0,True);
4187 SSVAL(outbuf,smb_vwv0,count);
4189 END_PROFILE(SMBcopy);
4193 /****************************************************************************
4195 ****************************************************************************/
4196 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4202 START_PROFILE(pathworks_setdir);
4205 if (!CAN_SETDIR(snum)) {
4206 END_PROFILE(pathworks_setdir);
4207 return(ERROR(ERRDOS,ERRnoaccess));
4210 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
4212 if (strlen(newdir) == 0) {
4215 ok = vfs_directory_exist(conn,newdir,NULL);
4217 string_set(&conn->connectpath,newdir);
4222 END_PROFILE(pathworks_setdir);
4223 return(ERROR(ERRDOS,ERRbadpath));
4226 outsize = set_message(outbuf,0,0,True);
4227 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4229 DEBUG(3,("setdir %s\n", newdir));
4231 END_PROFILE(pathworks_setdir);
4235 /****************************************************************************
4236 Get a lock pid, dealing with large count requests.
4237 ****************************************************************************/
4239 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4241 if(!large_file_format)
4242 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4244 return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
4247 /****************************************************************************
4248 Get a lock count, dealing with large count requests.
4249 ****************************************************************************/
4251 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4253 SMB_BIG_UINT count = 0;
4255 if(!large_file_format) {
4256 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4259 #if defined(HAVE_LONGLONG)
4260 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4261 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4262 #else /* HAVE_LONGLONG */
4265 * NT4.x seems to be broken in that it sends large file (64 bit)
4266 * lockingX calls even if the CAP_LARGE_FILES was *not*
4267 * negotiated. For boxes without large unsigned ints truncate the
4268 * lock count by dropping the top 32 bits.
4271 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4272 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4273 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4274 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4275 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4278 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4279 #endif /* HAVE_LONGLONG */
4285 /****************************************************************************
4286 Get a lock offset, dealing with large offset requests.
4287 ****************************************************************************/
4289 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4291 SMB_BIG_UINT offset = 0;
4295 if(!large_file_format) {
4296 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4299 #if defined(HAVE_LONGLONG)
4300 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4301 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4302 #else /* HAVE_LONGLONG */
4305 * NT4.x seems to be broken in that it sends large file (64 bit)
4306 * lockingX calls even if the CAP_LARGE_FILES was *not*
4307 * negotiated. For boxes without large unsigned ints mangle the
4308 * lock offset by mapping the top 32 bits onto the lower 32.
4311 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4312 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4313 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4316 if((new_low = map_lock_offset(high, low)) == 0) {
4318 return (SMB_BIG_UINT)-1;
4321 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4322 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4323 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4324 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4327 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4328 #endif /* HAVE_LONGLONG */
4334 /****************************************************************************
4335 reply to a lockingX request
4336 ****************************************************************************/
4338 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4340 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4341 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4342 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4343 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4344 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4345 SMB_BIG_UINT count = 0, offset = 0;
4347 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4350 uint32 ecode=0, dummy2;
4351 int eclass=0, dummy1;
4352 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4354 START_PROFILE(SMBlockingX);
4356 CHECK_FSP(fsp,conn);
4359 data = smb_buf(inbuf);
4361 /* Check if this is an oplock break on a file
4362 we have granted an oplock on.
4364 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4366 /* Client can insist on breaking to none. */
4367 BOOL break_to_none = (oplocklevel == 0);
4369 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4370 (unsigned int)oplocklevel, fsp->fnum ));
4373 * Make sure we have granted an exclusive or batch oplock on this file.
4376 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4378 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4379 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4381 /* if this is a pure oplock break request then don't send a reply */
4382 if (num_locks == 0 && num_ulocks == 0) {
4383 END_PROFILE(SMBlockingX);
4386 END_PROFILE(SMBlockingX);
4387 return ERROR(ERRDOS,ERRlock);
4391 if (remove_oplock(fsp, break_to_none) == False) {
4392 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4396 /* if this is a pure oplock break request then don't send a reply */
4397 if (num_locks == 0 && num_ulocks == 0)
4399 /* Sanity check - ensure a pure oplock break is not a
4401 if(CVAL(inbuf,smb_vwv0) != 0xff)
4402 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4403 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4404 END_PROFILE(SMBlockingX);
4410 * We do this check *after* we have checked this is not a oplock break
4411 * response message. JRA.
4414 release_level_2_oplocks_on_change(fsp);
4416 /* Data now points at the beginning of the list
4417 of smb_unlkrng structs */
4418 for(i = 0; i < (int)num_ulocks; i++) {
4419 lock_pid = get_lock_pid( data, i, large_file_format);
4420 count = get_lock_count( data, i, large_file_format);
4421 offset = get_lock_offset( data, i, large_file_format, &err);
4424 * There is no error code marked "stupid client bug".... :-).
4427 END_PROFILE(SMBlockingX);
4428 return ERROR(ERRDOS,ERRnoaccess);
4431 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4432 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4434 if(!do_unlock(fsp,conn,lock_pid,count,offset, &eclass, &ecode)) {
4435 END_PROFILE(SMBlockingX);
4436 return ERROR(eclass,ecode);
4440 /* Setup the timeout in seconds. */
4441 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4443 /* Now do any requested locks */
4444 data += ((large_file_format ? 20 : 10)*num_ulocks);
4446 /* Data now points at the beginning of the list
4447 of smb_lkrng structs */
4449 for(i = 0; i < (int)num_locks; i++) {
4450 lock_pid = get_lock_pid( data, i, large_file_format);
4451 count = get_lock_count( data, i, large_file_format);
4452 offset = get_lock_offset( data, i, large_file_format, &err);
4455 * There is no error code marked "stupid client bug".... :-).
4458 END_PROFILE(SMBlockingX);
4459 return ERROR(ERRDOS,ERRnoaccess);
4462 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
4463 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4465 if(!do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4467 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4469 * A blocking lock was requested. Package up
4470 * this smb into a queued request and push it
4471 * onto the blocking lock queue.
4473 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4474 END_PROFILE(SMBlockingX);
4482 /* If any of the above locks failed, then we must unlock
4483 all of the previous locks (X/Open spec). */
4484 if(i != num_locks && num_locks != 0) {
4486 * Ensure we don't do a remove on the lock that just failed,
4487 * as under POSIX rules, if we have a lock already there, we
4488 * will delete it (and we shouldn't) .....
4490 for(i--; i >= 0; i--) {
4491 lock_pid = get_lock_pid( data, i, large_file_format);
4492 count = get_lock_count( data, i, large_file_format);
4493 offset = get_lock_offset( data, i, large_file_format, &err);
4496 * There is no error code marked "stupid client bug".... :-).
4499 END_PROFILE(SMBlockingX);
4500 return ERROR(ERRDOS,ERRnoaccess);
4503 do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2);
4505 END_PROFILE(SMBlockingX);
4506 return ERROR(eclass,ecode);
4509 set_message(outbuf,2,0,True);
4511 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4512 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4514 END_PROFILE(SMBlockingX);
4515 return chain_reply(inbuf,outbuf,length,bufsize);
4519 /****************************************************************************
4520 reply to a SMBreadbmpx (read block multiplex) request
4521 ****************************************************************************/
4522 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4533 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4534 START_PROFILE(SMBreadBmpx);
4536 /* this function doesn't seem to work - disable by default */
4537 if (!lp_readbmpx()) {
4538 END_PROFILE(SMBreadBmpx);
4539 return(ERROR(ERRSRV,ERRuseSTD));
4542 outsize = set_message(outbuf,8,0,True);
4544 CHECK_FSP(fsp,conn);
4548 startpos = IVAL(inbuf,smb_vwv1);
4549 maxcount = SVAL(inbuf,smb_vwv3);
4551 data = smb_buf(outbuf);
4552 pad = ((long)data)%4;
4553 if (pad) pad = 4 - pad;
4556 max_per_packet = bufsize-(outsize+pad);
4560 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4561 END_PROFILE(SMBreadBmpx);
4562 return(ERROR(ERRDOS,ERRlock));
4567 size_t N = MIN(max_per_packet,tcount-total_read);
4569 nread = read_file(fsp,data,startpos,N);
4571 if (nread <= 0) nread = 0;
4573 if (nread < (ssize_t)N)
4574 tcount = total_read + nread;
4576 set_message(outbuf,8,nread,False);
4577 SIVAL(outbuf,smb_vwv0,startpos);
4578 SSVAL(outbuf,smb_vwv2,tcount);
4579 SSVAL(outbuf,smb_vwv6,nread);
4580 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4582 if (!send_smb(smbd_server_fd(),outbuf))
4583 exit_server("reply_readbmpx: send_smb failed.\n");
4585 total_read += nread;
4588 while (total_read < (ssize_t)tcount);
4590 END_PROFILE(SMBreadBmpx);
4594 /****************************************************************************
4595 reply to a SMBwritebmpx (write block multiplex primary) request
4596 ****************************************************************************/
4598 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4601 ssize_t nwritten = -1;
4608 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4609 START_PROFILE(SMBwriteBmpx);
4611 CHECK_FSP(fsp,conn);
4615 tcount = SVAL(inbuf,smb_vwv1);
4616 startpos = IVAL(inbuf,smb_vwv3);
4617 write_through = BITSETW(inbuf+smb_vwv7,0);
4618 numtowrite = SVAL(inbuf,smb_vwv10);
4619 smb_doff = SVAL(inbuf,smb_vwv11);
4621 data = smb_base(inbuf) + smb_doff;
4623 /* If this fails we need to send an SMBwriteC response,
4624 not an SMBwritebmpx - set this up now so we don't forget */
4625 CVAL(outbuf,smb_com) = SMBwritec;
4627 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4628 END_PROFILE(SMBwriteBmpx);
4629 return(ERROR(ERRDOS,ERRlock));
4632 nwritten = write_file(fsp,data,startpos,numtowrite);
4634 if(lp_syncalways(SNUM(conn)) || write_through)
4635 sync_file(conn,fsp);
4637 if(nwritten < (ssize_t)numtowrite) {
4638 END_PROFILE(SMBwriteBmpx);
4639 return(UNIXERROR(ERRHRD,ERRdiskfull));
4642 /* If the maximum to be written to this file
4643 is greater than what we just wrote then set
4644 up a secondary struct to be attached to this
4645 fd, we will use this to cache error messages etc. */
4646 if((ssize_t)tcount > nwritten)
4648 write_bmpx_struct *wbms;
4649 if(fsp->wbmpx_ptr != NULL)
4650 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4652 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4655 DEBUG(0,("Out of memory in reply_readmpx\n"));
4656 END_PROFILE(SMBwriteBmpx);
4657 return(ERROR(ERRSRV,ERRnoresource));
4659 wbms->wr_mode = write_through;
4660 wbms->wr_discard = False; /* No errors yet */
4661 wbms->wr_total_written = nwritten;
4662 wbms->wr_errclass = 0;
4664 fsp->wbmpx_ptr = wbms;
4667 /* We are returning successfully, set the message type back to
4669 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4671 outsize = set_message(outbuf,1,0,True);
4673 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4675 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4676 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4678 if (write_through && tcount==nwritten) {
4679 /* we need to send both a primary and a secondary response */
4680 smb_setlen(outbuf,outsize - 4);
4681 if (!send_smb(smbd_server_fd(),outbuf))
4682 exit_server("reply_writebmpx: send_smb failed.\n");
4684 /* now the secondary */
4685 outsize = set_message(outbuf,1,0,True);
4686 CVAL(outbuf,smb_com) = SMBwritec;
4687 SSVAL(outbuf,smb_vwv0,nwritten);
4690 END_PROFILE(SMBwriteBmpx);
4695 /****************************************************************************
4696 reply to a SMBwritebs (write block multiplex secondary) request
4697 ****************************************************************************/
4698 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4701 ssize_t nwritten = -1;
4708 write_bmpx_struct *wbms;
4709 BOOL send_response = False;
4710 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4711 START_PROFILE(SMBwriteBs);
4713 CHECK_FSP(fsp,conn);
4716 tcount = SVAL(inbuf,smb_vwv1);
4717 startpos = IVAL(inbuf,smb_vwv2);
4718 numtowrite = SVAL(inbuf,smb_vwv6);
4719 smb_doff = SVAL(inbuf,smb_vwv7);
4721 data = smb_base(inbuf) + smb_doff;
4723 /* We need to send an SMBwriteC response, not an SMBwritebs */
4724 CVAL(outbuf,smb_com) = SMBwritec;
4726 /* This fd should have an auxiliary struct attached,
4727 check that it does */
4728 wbms = fsp->wbmpx_ptr;
4730 END_PROFILE(SMBwriteBs);
4734 /* If write through is set we can return errors, else we must
4736 write_through = wbms->wr_mode;
4738 /* Check for an earlier error */
4739 if(wbms->wr_discard) {
4740 END_PROFILE(SMBwriteBs);
4741 return -1; /* Just discard the packet */
4744 nwritten = write_file(fsp,data,startpos,numtowrite);
4746 if(lp_syncalways(SNUM(conn)) || write_through)
4747 sync_file(conn,fsp);
4749 if (nwritten < (ssize_t)numtowrite)
4753 /* We are returning an error - we can delete the aux struct */
4754 if (wbms) free((char *)wbms);
4755 fsp->wbmpx_ptr = NULL;
4756 END_PROFILE(SMBwriteBs);
4757 return(ERROR(ERRHRD,ERRdiskfull));
4759 END_PROFILE(SMBwriteBs);
4760 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4763 /* Increment the total written, if this matches tcount
4764 we can discard the auxiliary struct (hurrah !) and return a writeC */
4765 wbms->wr_total_written += nwritten;
4766 if(wbms->wr_total_written >= tcount)
4770 outsize = set_message(outbuf,1,0,True);
4771 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4772 send_response = True;
4776 fsp->wbmpx_ptr = NULL;
4780 END_PROFILE(SMBwriteBs);
4784 END_PROFILE(SMBwriteBs);
4789 /****************************************************************************
4790 reply to a SMBsetattrE
4791 ****************************************************************************/
4793 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4795 struct utimbuf unix_times;
4797 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4798 START_PROFILE(SMBsetattrE);
4800 outsize = set_message(outbuf,0,0,True);
4802 CHECK_FSP(fsp,conn);
4805 /* Convert the DOS times into unix times. Ignore create
4806 time as UNIX can't set this.
4808 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4809 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4812 * Patch from Ray Frush <frush@engr.colostate.edu>
4813 * Sometimes times are sent as zero - ignore them.
4816 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4818 /* Ignore request */
4821 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4822 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4824 END_PROFILE(SMBsetattrE);
4827 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4829 /* set modify time = to access time if modify time was 0 */
4830 unix_times.modtime = unix_times.actime;
4833 /* Set the date on this file */
4834 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4835 END_PROFILE(SMBsetattrE);
4836 return(ERROR(ERRDOS,ERRnoaccess));
4839 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4840 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4842 END_PROFILE(SMBsetattrE);
4847 /****************************************************************************
4848 reply to a SMBgetattrE
4849 ****************************************************************************/
4851 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4853 SMB_STRUCT_STAT sbuf;
4856 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4857 START_PROFILE(SMBgetattrE);
4859 outsize = set_message(outbuf,11,0,True);
4861 CHECK_FSP(fsp,conn);
4864 /* Do an fstat on this file */
4865 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4866 END_PROFILE(SMBgetattrE);
4867 return(UNIXERROR(ERRDOS,ERRnoaccess));
4870 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4872 /* Convert the times into dos times. Set create
4873 date to be last modify date as UNIX doesn't save
4875 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4876 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4877 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4880 SIVAL(outbuf,smb_vwv6,0);
4881 SIVAL(outbuf,smb_vwv8,0);
4885 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4886 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4888 SSVAL(outbuf,smb_vwv10, mode);
4890 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4892 END_PROFILE(SMBgetattrE);