get_md4pw was called with 2 params, one never used. mach_name and
[Samba.git] / source / smbd / reply.c
blob3199be8c6c756aa41266d4f6b599888da51cea18
1 #define OLD_NTDOMAIN 1
2 /*
3 Unix SMB/Netbios implementation.
4 Version 1.9.
5 Main SMB reply routines
6 Copyright (C) Andrew Tridgell 1992-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "includes.h"
30 /* look in server.c for some explanation of these variables */
31 extern int Protocol;
32 extern int DEBUGLEVEL;
33 extern int max_send;
34 extern int max_recv;
35 extern char magic_char;
36 extern BOOL case_sensitive;
37 extern BOOL case_preserve;
38 extern BOOL short_case_preserve;
39 extern userdom_struct current_user_info;
40 extern pstring global_myname;
41 extern fstring global_myworkgroup;
42 extern int global_oplock_break;
43 uint32 global_client_caps = 0;
44 unsigned int smb_echo_count = 0;
46 /****************************************************************************
47 report a possible attack via the password buffer overflow bug
48 ****************************************************************************/
50 static void overflow_attack(int len)
52 if( DEBUGLVL( 0 ) ) {
53 dbgtext( "ERROR: Invalid password length %d.\n", len );
54 dbgtext( "Your machine may be under attack by someone " );
55 dbgtext( "attempting to exploit an old bug.\n" );
56 dbgtext( "Attack was from IP = %s.\n", client_addr() );
58 exit_server("possible attack");
62 /****************************************************************************
63 reply to an special message
64 ****************************************************************************/
66 int reply_special(char *inbuf,char *outbuf)
68 int outsize = 4;
69 int msg_type = CVAL(inbuf,0);
70 int msg_flags = CVAL(inbuf,1);
71 pstring name1,name2;
72 extern fstring remote_machine;
73 extern fstring local_machine;
74 int len;
75 char name_type = 0;
77 *name1 = *name2 = 0;
79 memset(outbuf,'\0',smb_size);
81 smb_setlen(outbuf,0);
83 switch (msg_type) {
84 case 0x81: /* session request */
85 CVAL(outbuf,0) = 0x82;
86 CVAL(outbuf,3) = 0;
87 if (name_len(inbuf+4) > 50 ||
88 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
89 DEBUG(0,("Invalid name length in session request\n"));
90 return(0);
92 name_extract(inbuf,4,name1);
93 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
94 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
95 name1,name2));
97 fstrcpy(remote_machine,name2);
98 remote_machine[15] = 0;
99 trim_string(remote_machine," "," ");
100 strlower(remote_machine);
102 fstrcpy(local_machine,name1);
103 len = strlen(local_machine);
104 if (len == 16) {
105 name_type = local_machine[15];
106 local_machine[15] = 0;
108 trim_string(local_machine," "," ");
109 strlower(local_machine);
111 if (name_type == 'R') {
112 /* We are being asked for a pathworks session ---
113 no thanks! */
114 CVAL(outbuf, 0) = 0x83;
115 break;
118 /* add it as a possible user name if we
119 are in share mode security */
120 if (lp_security() == SEC_SHARE) {
121 add_session_user(remote_machine);
124 reload_services(True);
125 reopen_logs();
127 if (lp_status(-1)) {
128 claim_connection(NULL,"",MAXSTATUS,True);
131 break;
133 case 0x89: /* session keepalive request
134 (some old clients produce this?) */
135 CVAL(outbuf,0) = 0x85;
136 CVAL(outbuf,3) = 0;
137 break;
139 case 0x82: /* positive session response */
140 case 0x83: /* negative session response */
141 case 0x84: /* retarget session response */
142 DEBUG(0,("Unexpected session response\n"));
143 break;
145 case 0x85: /* session keepalive */
146 default:
147 return(0);
150 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
151 msg_type, msg_flags));
153 return(outsize);
157 /*******************************************************************
158 work out what error to give to a failed connection
159 ********************************************************************/
161 static int connection_error(char *inbuf,char *outbuf,int ecode)
163 if (ecode == ERRnoipc || ecode == ERRnosuchshare)
164 return(ERROR(ERRDOS,ecode));
166 return(ERROR(ERRSRV,ecode));
171 /****************************************************************************
172 parse a share descriptor string
173 ****************************************************************************/
174 static void parse_connect(char *p,char *service,char *user,
175 char *password,int *pwlen,char *dev)
177 char *p2;
179 DEBUG(4,("parsing connect string %s\n",p));
181 p2 = strrchr(p,'\\');
182 if (p2 == NULL)
183 fstrcpy(service,p);
184 else
185 fstrcpy(service,p2+1);
187 p += strlen(p) + 2;
189 fstrcpy(password,p);
190 *pwlen = strlen(password);
192 p += strlen(p) + 2;
194 fstrcpy(dev,p);
196 *user = 0;
197 p = strchr(service,'%');
198 if (p != NULL)
200 *p = 0;
201 fstrcpy(user,p+1);
205 /****************************************************************************
206 Reply to a tcon.
207 ****************************************************************************/
209 int reply_tcon(connection_struct *conn,
210 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
212 BOOL doencrypt = SMBENCRYPT();
213 pstring service;
214 pstring user;
215 pstring password;
216 pstring dev;
217 int outsize = 0;
218 uint16 vuid = SVAL(inbuf,smb_uid);
219 int pwlen=0;
220 int ecode = -1;
221 START_PROFILE(SMBtcon);
223 *service = *user = *password = *dev = 0;
225 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
228 * Ensure the user and password names are in UNIX codepage format.
231 dos_to_unix(user,True);
232 if (!doencrypt)
233 dos_to_unix(password,True);
236 * Pass the user through the NT -> unix user mapping
237 * function.
240 (void)map_username(user);
243 * Do any UNIX username case mangling.
245 (void)Get_Pwnam( user, True);
247 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
249 if (!conn) {
250 END_PROFILE(SMBtcon);
251 return(connection_error(inbuf,outbuf,ecode));
254 outsize = set_message(outbuf,2,0,True);
255 SSVAL(outbuf,smb_vwv0,max_recv);
256 SSVAL(outbuf,smb_vwv1,conn->cnum);
257 SSVAL(outbuf,smb_tid,conn->cnum);
259 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
260 service, user, conn->cnum));
262 END_PROFILE(SMBtcon);
263 return(outsize);
266 /****************************************************************************
267 Reply to a tcon and X.
268 ****************************************************************************/
269 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
271 fstring service;
272 pstring user;
273 pstring password;
274 pstring devicename;
275 BOOL doencrypt = SMBENCRYPT();
276 int ecode = -1;
277 uint16 vuid = SVAL(inbuf,smb_uid);
278 int passlen = SVAL(inbuf,smb_vwv3);
279 char *path;
280 char *p;
281 START_PROFILE(SMBtconX);
283 *service = *user = *password = *devicename = 0;
285 /* we might have to close an old one */
286 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
287 close_cnum(conn,vuid);
290 if (passlen > MAX_PASS_LEN) {
291 overflow_attack(passlen);
294 memcpy(password,smb_buf(inbuf),passlen);
295 password[passlen]=0;
296 path = smb_buf(inbuf) + passlen;
298 if (passlen != 24) {
299 if (strequal(password," "))
300 *password = 0;
301 passlen = strlen(password);
304 p = strchr(path+2,'\\');
305 if (!p) {
306 END_PROFILE(SMBtconX);
307 return(ERROR(ERRDOS,ERRnosuchshare));
309 fstrcpy(service,p+1);
310 p = strchr(service,'%');
311 if (p) {
312 *p++ = 0;
313 fstrcpy(user,p);
315 StrnCpy(devicename,path + strlen(path) + 1,6);
316 DEBUG(4,("Got device type %s\n",devicename));
319 * Ensure the user and password names are in UNIX codepage format.
322 dos_to_unix(user,True);
323 if (!doencrypt)
324 dos_to_unix(password,True);
327 * Pass the user through the NT -> unix user mapping
328 * function.
331 (void)map_username(user);
334 * Do any UNIX username case mangling.
336 (void)Get_Pwnam(user, True);
338 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
340 if (!conn) {
341 END_PROFILE(SMBtconX);
342 return(connection_error(inbuf,outbuf,ecode));
345 if (Protocol < PROTOCOL_NT1) {
346 set_message(outbuf,2,strlen(devicename)+1,True);
347 pstrcpy(smb_buf(outbuf),devicename);
348 } else {
349 char *fsname = lp_fstype(SNUM(conn));
351 set_message(outbuf,3,3,True);
353 p = smb_buf(outbuf);
354 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
355 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
357 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
359 /* what does setting this bit do? It is set by NT4 and
360 may affect the ability to autorun mounted cdroms */
361 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
363 init_dfsroot(conn, inbuf, outbuf);
367 DEBUG(3,("tconX service=%s user=%s\n",
368 service, user));
370 /* set the incoming and outgoing tid to the just created one */
371 SSVAL(inbuf,smb_tid,conn->cnum);
372 SSVAL(outbuf,smb_tid,conn->cnum);
374 END_PROFILE(SMBtconX);
375 return chain_reply(inbuf,outbuf,length,bufsize);
379 /****************************************************************************
380 reply to an unknown type
381 ****************************************************************************/
382 int reply_unknown(char *inbuf,char *outbuf)
384 int type;
385 type = CVAL(inbuf,smb_com);
387 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
388 smb_fn_name(type), type, type));
390 return(ERROR(ERRSRV,ERRunknownsmb));
394 /****************************************************************************
395 reply to an ioctl
396 ****************************************************************************/
397 int reply_ioctl(connection_struct *conn,
398 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
400 uint16 device = SVAL(inbuf,smb_vwv1);
401 uint16 function = SVAL(inbuf,smb_vwv2);
402 uint32 ioctl_code = (device << 16) + function;
403 int replysize, outsize;
404 char *p;
405 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
406 START_PROFILE(SMBioctl);
408 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
410 switch (ioctl_code)
412 case IOCTL_QUERY_JOB_INFO:
413 replysize = 32;
414 break;
415 default:
416 END_PROFILE(SMBioctl);
417 return(ERROR(ERRSRV,ERRnosupport));
420 outsize = set_message(outbuf,8,replysize+1,True);
421 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
422 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
423 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
424 p = smb_buf(outbuf) + 1; /* Allow for alignment */
426 switch (ioctl_code)
428 case IOCTL_QUERY_JOB_INFO:
429 SSVAL(p,0,fsp->print_jobid); /* Job number */
430 StrnCpy(p+2, global_myname, 15); /* Our NetBIOS name */
431 StrnCpy(p+18, lp_servicename(SNUM(conn)), 13); /* Service name */
432 break;
435 END_PROFILE(SMBioctl);
436 return outsize;
439 /****************************************************************************
440 always return an error: it's just a matter of which one...
441 ****************************************************************************/
442 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
443 char *smb_passwd, int smb_passlen,
444 char *smb_nt_passwd, int smb_nt_passlen)
446 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
447 if (lp_security() == SEC_USER) {
448 smb_trust_acct = getsmbpwnam(user);
449 } else {
450 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
451 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
452 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
455 if (smb_trust_acct == NULL) {
456 /* lkclXXXX: workstation entry doesn't exist */
457 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
458 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
459 return(ERROR(0, NT_STATUS_NO_SUCH_USER));
460 } else {
461 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
462 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
463 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
464 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
467 if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) {
468 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
469 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
470 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
473 if (smb_trust_acct->acct_ctrl & ACB_DOMTRUST) {
474 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
475 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
476 return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
479 if (smb_trust_acct->acct_ctrl & ACB_SVRTRUST) {
480 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
481 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
482 return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
485 if (smb_trust_acct->acct_ctrl & ACB_WSTRUST) {
486 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
487 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
488 return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
492 /* don't know what to do: indicate logon failure */
493 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
494 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
497 /****************************************************************************
498 Create a UNIX user on demand.
499 ****************************************************************************/
501 int smb_create_user(char *unix_user, char *homedir)
503 pstring add_script;
504 int ret;
506 pstrcpy(add_script, lp_adduser_script());
507 if (! *add_script) return -1;
508 all_string_sub(add_script, "%u", unix_user, sizeof(pstring));
509 if (homedir)
510 all_string_sub(add_script, "%H", homedir, sizeof(pstring));
511 ret = smbrun(add_script,NULL,False);
512 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
513 return ret;
516 /****************************************************************************
517 Delete a UNIX user on demand.
518 ****************************************************************************/
520 static int smb_delete_user(char *unix_user)
522 pstring del_script;
523 int ret;
525 pstrcpy(del_script, lp_deluser_script());
526 if (! *del_script) return -1;
527 all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
528 ret = smbrun(del_script,NULL,False);
529 DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
530 return ret;
533 /****************************************************************************
534 Check user is in correct domain if required
535 ****************************************************************************/
537 static BOOL check_domain_match(char *user, char *domain)
540 * If we aren't serving to trusted domains, we must make sure that
541 * the validation request comes from an account in the same domain
542 * as the Samba server
545 if (!lp_allow_trusted_domains() &&
546 !strequal(lp_workgroup(), domain) ) {
547 DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
548 return False;
549 } else {
550 return True;
554 /****************************************************************************
555 Check for a valid username and password in security=server mode.
556 ****************************************************************************/
558 static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
559 char *smb_apasswd, int smb_apasslen,
560 char *smb_ntpasswd, int smb_ntpasslen)
562 BOOL ret = False;
564 if(lp_security() != SEC_SERVER)
565 return False;
567 if (!check_domain_match(orig_user, domain))
568 return False;
570 ret = server_validate(orig_user, domain,
571 smb_apasswd, smb_apasslen,
572 smb_ntpasswd, smb_ntpasslen);
573 if(ret) {
574 struct passwd *pwd;
577 * User validated ok against Domain controller.
578 * If the admin wants us to try and create a UNIX
579 * user on the fly, do so.
580 * Note that we can never delete users when in server
581 * level security as we never know if it was a failure
582 * due to a bad password, or the user really doesn't exist.
584 if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
585 smb_create_user(unix_user, NULL);
588 if(lp_adduser_script() && pwd) {
589 SMB_STRUCT_STAT st;
592 * Also call smb_create_user if the users home directory
593 * doesn't exist. Used with winbindd to allow the script to
594 * create the home directory for a user mapped with winbindd.
597 if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
598 smb_create_user(unix_user, pwd->pw_dir);
602 return ret;
605 /****************************************************************************
606 Check for a valid username and password in security=domain mode.
607 ****************************************************************************/
609 static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
610 char *smb_apasswd, int smb_apasslen,
611 char *smb_ntpasswd, int smb_ntpasslen)
613 BOOL ret = False;
614 BOOL user_exists = True;
615 struct passwd *pwd;
617 if(lp_security() != SEC_DOMAIN)
618 return False;
620 if (!check_domain_match(orig_user, domain))
621 return False;
623 ret = domain_client_validate(orig_user, domain,
624 smb_apasswd, smb_apasslen,
625 smb_ntpasswd, smb_ntpasslen,
626 &user_exists);
628 if(ret) {
630 * User validated ok against Domain controller.
631 * If the admin wants us to try and create a UNIX
632 * user on the fly, do so.
634 if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
635 smb_create_user(unix_user, NULL);
638 if(lp_adduser_script() && pwd) {
639 SMB_STRUCT_STAT st;
642 * Also call smb_create_user if the users home directory
643 * doesn't exist. Used with winbindd to allow the script to
644 * create the home directory for a user mapped with winbindd.
647 if (pwd->pw_shell && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
648 smb_create_user(unix_user, pwd->pw_dir);
651 } else {
653 * User failed to validate ok against Domain controller.
654 * If the failure was "user doesn't exist" and admin
655 * wants us to try and delete that UNIX user on the fly,
656 * do so.
658 if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) {
659 smb_delete_user(unix_user);
663 return ret;
666 /****************************************************************************
667 Return a bad password error configured for the correct client type.
668 ****************************************************************************/
670 static int bad_password_error(char *inbuf,char *outbuf)
672 enum remote_arch_types ra_type = get_remote_arch();
674 if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
675 (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
676 SSVAL(outbuf,smb_flg2,FLAGS2_32_BIT_ERROR_CODES);
677 return(ERROR(0,NT_STATUS_LOGON_FAILURE));
680 return(ERROR(ERRSRV,ERRbadpw));
683 /****************************************************************************
684 reply to a session setup command
685 ****************************************************************************/
687 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
689 uint16 sess_vuid;
690 gid_t gid;
691 uid_t uid;
692 int smb_bufsize;
693 int smb_apasslen = 0;
694 pstring smb_apasswd;
695 int smb_ntpasslen = 0;
696 pstring smb_ntpasswd;
697 BOOL valid_nt_password = False;
698 pstring user;
699 pstring orig_user;
700 BOOL guest=False;
701 static BOOL done_sesssetup = False;
702 BOOL doencrypt = SMBENCRYPT();
703 char *domain = "";
704 START_PROFILE(SMBsesssetupX);
706 *smb_apasswd = 0;
707 *smb_ntpasswd = 0;
709 smb_bufsize = SVAL(inbuf,smb_vwv2);
711 if (Protocol < PROTOCOL_NT1) {
712 smb_apasslen = SVAL(inbuf,smb_vwv7);
713 if (smb_apasslen > MAX_PASS_LEN)
714 overflow_attack(smb_apasslen);
716 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
717 smb_apasswd[smb_apasslen] = 0;
718 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
720 * Incoming user is in DOS codepage format. Convert
721 * to UNIX.
723 dos_to_unix(user,True);
725 if (!doencrypt && (lp_security() != SEC_SERVER)) {
726 smb_apasslen = strlen(smb_apasswd);
728 } else {
729 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
730 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
731 enum remote_arch_types ra_type = get_remote_arch();
732 char *p = smb_buf(inbuf);
734 if(global_client_caps == 0)
735 global_client_caps = IVAL(inbuf,smb_vwv11);
737 /* client_caps is used as final determination if client is NT or Win95.
738 This is needed to return the correct error codes in some
739 circumstances.
742 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
743 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
744 set_remote_arch( RA_WIN95);
748 if (passlen1 != 24 && passlen2 != 24)
749 doencrypt = False;
751 if (passlen1 > MAX_PASS_LEN) {
752 overflow_attack(passlen1);
755 passlen1 = MIN(passlen1, MAX_PASS_LEN);
756 passlen2 = MIN(passlen2, MAX_PASS_LEN);
758 if(!doencrypt) {
759 /* both Win95 and WinNT stuff up the password lengths for
760 non-encrypting systems. Uggh.
762 if passlen1==24 its a win95 system, and its setting the
763 password length incorrectly. Luckily it still works with the
764 default code because Win95 will null terminate the password
765 anyway
767 if passlen1>0 and passlen2>0 then maybe its a NT box and its
768 setting passlen2 to some random value which really stuffs
769 things up. we need to fix that one. */
771 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
772 passlen2 = 0;
775 if (lp_restrict_anonymous()) {
776 /* there seems to be no reason behind the differences in MS clients formatting
777 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
778 * in particular seems to have an extra null byte between the username and the
779 * domain, or the password length calculation is wrong, which throws off the
780 * string extraction routines below. This makes the value of domain be the
781 * empty string, which fails the restrict anonymous check further down.
782 * This compensates for that, and allows browsing to work in mixed NT and
783 * win95 environments even when restrict anonymous is true. AAB
785 dump_data(100, p, 0x70);
786 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
787 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
788 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
789 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
790 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
791 passlen1 = 1;
795 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
796 /* Save the lanman2 password and the NT md4 password. */
797 smb_apasslen = passlen1;
798 memcpy(smb_apasswd,p,smb_apasslen);
799 smb_apasswd[smb_apasslen] = 0;
800 smb_ntpasslen = passlen2;
801 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
802 smb_ntpasswd[smb_ntpasslen] = 0;
805 * Ensure the plaintext passwords are in UNIX format.
807 if(!doencrypt) {
808 dos_to_unix(smb_apasswd,True);
809 dos_to_unix(smb_ntpasswd,True);
812 } else {
813 /* we use the first password that they gave */
814 smb_apasslen = passlen1;
815 StrnCpy(smb_apasswd,p,smb_apasslen);
817 * Ensure the plaintext password is in UNIX format.
819 dos_to_unix(smb_apasswd,True);
821 /* trim the password */
822 smb_apasslen = strlen(smb_apasswd);
824 /* wfwg sometimes uses a space instead of a null */
825 if (strequal(smb_apasswd," ")) {
826 smb_apasslen = 0;
827 *smb_apasswd = 0;
831 p += passlen1 + passlen2;
832 fstrcpy(user,p);
833 p = skip_string(p,1);
835 * Incoming user is in DOS codepage format. Convert
836 * to UNIX.
838 dos_to_unix(user,True);
839 domain = p;
841 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
842 domain,skip_string(p,1),skip_string(p,2)));
846 DEBUG(3,("sesssetupX:name=[%s]\n",user));
848 /* If name ends in $ then I think it's asking about whether a */
849 /* computer with that name (minus the $) has access. For now */
850 /* say yes to everything ending in $. */
852 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
853 END_PROFILE(SMBsesssetupX);
854 return session_trust_account(conn, inbuf, outbuf, user,
855 smb_apasswd, smb_apasslen,
856 smb_ntpasswd, smb_ntpasslen);
859 if (done_sesssetup && lp_restrict_anonymous()) {
860 /* tests show that even if browsing is done over already validated connections
861 * without a username and password the domain is still provided, which it
862 * wouldn't be if it was a purely anonymous connection. So, in order to
863 * restrict anonymous, we only deny connections that have no session
864 * information. If a domain has been provided, then it's not a purely
865 * anonymous connection. AAB
867 if (!*user && !*smb_apasswd && !*domain) {
868 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
869 END_PROFILE(SMBsesssetupX);
870 return(ERROR(ERRDOS,ERRnoaccess));
874 /* If no username is sent use the guest account */
875 if (!*user) {
876 pstrcpy(user,lp_guestaccount(-1));
877 /* If no user and no password then set guest flag. */
878 if( *smb_apasswd == 0)
879 guest = True;
882 pstrcpy(current_user_info.smb_name,user);
884 reload_services(True);
887 * Save the username before mapping. We will use
888 * the original username sent to us for security=server
889 * and security=domain checking.
892 pstrcpy( orig_user, user);
894 /* if the username exists as a domain/username pair on the unix system then use
895 that */
896 if (!getpwnam(user)) {
897 pstring user2;
898 slprintf(user2,sizeof(user2),"%s%s%s", dos_to_unix(domain,False), lp_winbind_separator(), user);
899 if (getpwnam(user2)) {
900 DEBUG(3,("Using unix username %s\n", user2));
901 pstrcpy(user, user2);
906 * Pass the user through the NT -> unix user mapping
907 * function.
910 (void)map_username(user);
913 * Do any UNIX username case mangling.
915 smb_getpwnam(user, True);
917 add_session_user(user);
920 * Check if the given username was the guest user with no password.
923 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
924 guest = True;
927 * Check with orig_user for security=server and
928 * security=domain.
931 if (!guest &&
932 !check_server_security(orig_user, domain, user,
933 smb_apasswd, smb_apasslen,
934 smb_ntpasswd, smb_ntpasslen) &&
935 !check_domain_security(orig_user, domain, user,
936 smb_apasswd, smb_apasslen,
937 smb_ntpasswd, smb_ntpasslen) &&
938 !check_hosts_equiv(user)
943 * If we get here then the user wasn't guest and the remote
944 * authentication methods failed. Check the authentication
945 * methods on this local server.
947 * If an NT password was supplied try and validate with that
948 * first. This is superior as the passwords are mixed case
949 * 128 length unicode.
952 if(smb_ntpasslen)
954 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
955 DEBUG(2,("NT Password did not match for user '%s' ! Defaulting to Lanman\n", user));
956 else
957 valid_nt_password = True;
960 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL))
962 if (lp_security() >= SEC_USER)
964 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
966 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
967 END_PROFILE(SMBsesssetupX);
968 return bad_password_error(inbuf,outbuf);
971 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
973 if (smb_getpwnam(user,True))
975 DEBUG(1,("Rejecting user '%s': bad password\n", user));
976 END_PROFILE(SMBsesssetupX);
977 return bad_password_error(inbuf,outbuf);
982 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
983 * Then always map to guest account - as done below.
987 if (*smb_apasswd || !smb_getpwnam(user,True))
988 pstrcpy(user,lp_guestaccount(-1));
989 DEBUG(3,("Registered username %s for guest access\n",user));
990 guest = True;
994 if (!smb_getpwnam(user,True)) {
995 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
996 pstrcpy(user,lp_guestaccount(-1));
997 guest = True;
1000 if (!strequal(user,lp_guestaccount(-1)) &&
1001 lp_servicenumber(user) < 0)
1003 add_home_service(user,get_user_home_dir(user));
1007 /* it's ok - setup a reply */
1008 if (Protocol < PROTOCOL_NT1) {
1009 set_message(outbuf,3,0,True);
1010 } else {
1011 char *p;
1012 set_message(outbuf,3,3,True);
1013 p = smb_buf(outbuf);
1014 pstrcpy(p,"Unix"); p = skip_string(p,1);
1015 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
1016 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
1017 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
1018 /* perhaps grab OS version here?? */
1021 /* Set the correct uid in the outgoing and incoming packets
1022 We will use this on future requests to determine which
1023 user we should become.
1026 const struct passwd *pw = smb_getpwnam(user,False);
1027 if (!pw) {
1028 DEBUG(1,("Username %s is invalid on this system\n",user));
1029 END_PROFILE(SMBsesssetupX);
1030 return bad_password_error(inbuf,outbuf);
1032 gid = pw->pw_gid;
1033 uid = pw->pw_uid;
1036 if (guest)
1037 SSVAL(outbuf,smb_vwv2,1);
1039 /* register the name and uid as being validated, so further connections
1040 to a uid can get through without a password, on the same VC */
1042 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest);
1044 SSVAL(outbuf,smb_uid,sess_vuid);
1045 SSVAL(inbuf,smb_uid,sess_vuid);
1047 if (!done_sesssetup)
1048 max_send = MIN(max_send,smb_bufsize);
1050 DEBUG(6,("Client requested max send size of %d\n", max_send));
1052 done_sesssetup = True;
1054 END_PROFILE(SMBsesssetupX);
1055 return chain_reply(inbuf,outbuf,length,bufsize);
1059 /****************************************************************************
1060 reply to a chkpth
1061 ****************************************************************************/
1062 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1064 int outsize = 0;
1065 int mode;
1066 pstring name;
1067 BOOL ok = False;
1068 BOOL bad_path = False;
1069 SMB_STRUCT_STAT sbuf;
1070 START_PROFILE(SMBchkpth);
1072 pstrcpy(name,smb_buf(inbuf) + 1);
1074 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1076 unix_convert(name,conn,0,&bad_path,&sbuf);
1078 mode = SVAL(inbuf,smb_vwv0);
1080 if (check_name(name,conn)) {
1081 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
1082 ok = S_ISDIR(sbuf.st_mode);
1085 if (!ok)
1087 /* We special case this - as when a Windows machine
1088 is parsing a path is steps through the components
1089 one at a time - if a component fails it expects
1090 ERRbadpath, not ERRbadfile.
1092 if(errno == ENOENT)
1094 unix_ERR_class = ERRDOS;
1095 unix_ERR_code = ERRbadpath;
1098 #if 0
1099 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
1100 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
1101 (get_remote_arch() == RA_WINNT))
1103 unix_ERR_class = ERRDOS;
1104 unix_ERR_code = ERRbaddirectory;
1106 #endif
1108 return(UNIXERROR(ERRDOS,ERRbadpath));
1111 outsize = set_message(outbuf,0,0,True);
1113 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
1115 END_PROFILE(SMBchkpth);
1116 return(outsize);
1120 /****************************************************************************
1121 reply to a getatr
1122 ****************************************************************************/
1123 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1125 pstring fname;
1126 int outsize = 0;
1127 SMB_STRUCT_STAT sbuf;
1128 BOOL ok = False;
1129 int mode=0;
1130 SMB_OFF_T size=0;
1131 time_t mtime=0;
1132 BOOL bad_path = False;
1133 START_PROFILE(SMBgetatr);
1135 pstrcpy(fname,smb_buf(inbuf) + 1);
1137 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1139 /* if((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && dfs_redirect(fname,conn)) return(dfs_path_error(inbuf,outbuf));
1141 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1142 under WfWg - weird! */
1143 if (! (*fname))
1145 mode = aHIDDEN | aDIR;
1146 if (!CAN_WRITE(conn)) mode |= aRONLY;
1147 size = 0;
1148 mtime = 0;
1149 ok = True;
1151 else
1153 unix_convert(fname,conn,0,&bad_path,&sbuf);
1154 if (check_name(fname,conn))
1156 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1158 mode = dos_mode(conn,fname,&sbuf);
1159 size = sbuf.st_size;
1160 mtime = sbuf.st_mtime;
1161 if (mode & aDIR)
1162 size = 0;
1163 ok = True;
1165 else
1166 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1170 if (!ok)
1172 if((errno == ENOENT) && bad_path)
1174 unix_ERR_class = ERRDOS;
1175 unix_ERR_code = ERRbadpath;
1178 END_PROFILE(SMBgetatr);
1179 return(UNIXERROR(ERRDOS,ERRbadfile));
1182 outsize = set_message(outbuf,10,0,True);
1184 SSVAL(outbuf,smb_vwv0,mode);
1185 if(lp_dos_filetime_resolution(SNUM(conn)) )
1186 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1187 else
1188 put_dos_date3(outbuf,smb_vwv1,mtime);
1189 SIVAL(outbuf,smb_vwv3,(uint32)size);
1191 if (Protocol >= PROTOCOL_NT1) {
1192 char *p = strrchr(fname,'/');
1193 uint16 flg2 = SVAL(outbuf,smb_flg2);
1194 if (!p) p = fname;
1195 if (!is_8_3(fname, True))
1196 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1199 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1201 END_PROFILE(SMBgetatr);
1202 return(outsize);
1206 /****************************************************************************
1207 reply to a setatr
1208 ****************************************************************************/
1209 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1211 pstring fname;
1212 int outsize = 0;
1213 BOOL ok=False;
1214 int mode;
1215 time_t mtime;
1216 SMB_STRUCT_STAT sbuf;
1217 BOOL bad_path = False;
1218 START_PROFILE(SMBsetatr);
1220 pstrcpy(fname,smb_buf(inbuf) + 1);
1221 unix_convert(fname,conn,0,&bad_path,&sbuf);
1223 mode = SVAL(inbuf,smb_vwv0);
1224 mtime = make_unix_date3(inbuf+smb_vwv1);
1226 if (VALID_STAT_OF_DIR(sbuf))
1227 mode |= aDIR;
1228 if (check_name(fname,conn))
1229 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1230 if (ok)
1231 ok = set_filetime(conn,fname,mtime);
1233 if (!ok)
1235 if((errno == ENOENT) && bad_path)
1237 unix_ERR_class = ERRDOS;
1238 unix_ERR_code = ERRbadpath;
1241 END_PROFILE(SMBsetatr);
1242 return(UNIXERROR(ERRDOS,ERRnoaccess));
1245 outsize = set_message(outbuf,0,0,True);
1247 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1249 END_PROFILE(SMBsetatr);
1250 return(outsize);
1254 /****************************************************************************
1255 reply to a dskattr
1256 ****************************************************************************/
1257 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1259 int outsize = 0;
1260 SMB_BIG_UINT dfree,dsize,bsize;
1261 START_PROFILE(SMBdskattr);
1263 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1265 outsize = set_message(outbuf,5,0,True);
1267 SSVAL(outbuf,smb_vwv0,dsize);
1268 SSVAL(outbuf,smb_vwv1,bsize/512);
1269 SSVAL(outbuf,smb_vwv2,512);
1270 SSVAL(outbuf,smb_vwv3,dfree);
1272 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1274 END_PROFILE(SMBdskattr);
1275 return(outsize);
1279 /****************************************************************************
1280 reply to a search
1281 Can be called from SMBsearch, SMBffirst or SMBfunique.
1282 ****************************************************************************/
1283 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1285 pstring mask;
1286 pstring directory;
1287 pstring fname;
1288 SMB_OFF_T size;
1289 int mode;
1290 time_t date;
1291 int dirtype;
1292 int outsize = 0;
1293 int numentries = 0;
1294 BOOL finished = False;
1295 int maxentries;
1296 int i;
1297 char *p;
1298 BOOL ok = False;
1299 int status_len;
1300 char *path;
1301 char status[21];
1302 int dptr_num= -1;
1303 BOOL check_descend = False;
1304 BOOL expect_close = False;
1305 BOOL can_open = True;
1306 BOOL bad_path = False;
1307 START_PROFILE(SMBsearch);
1309 *mask = *directory = *fname = 0;
1311 /* If we were called as SMBffirst then we must expect close. */
1312 if(CVAL(inbuf,smb_com) == SMBffirst)
1313 expect_close = True;
1315 outsize = set_message(outbuf,1,3,True);
1316 maxentries = SVAL(inbuf,smb_vwv0);
1317 dirtype = SVAL(inbuf,smb_vwv1);
1318 path = smb_buf(inbuf) + 1;
1319 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1322 /* dirtype &= ~aDIR; */
1324 if (status_len == 0)
1326 SMB_STRUCT_STAT sbuf;
1327 pstring dir2;
1329 pstrcpy(directory,smb_buf(inbuf)+1);
1330 pstrcpy(dir2,smb_buf(inbuf)+1);
1331 unix_convert(directory,conn,0,&bad_path,&sbuf);
1332 unix_format(dir2);
1334 if (!check_name(directory,conn))
1335 can_open = False;
1337 p = strrchr(dir2,'/');
1338 if (p == NULL)
1340 pstrcpy(mask,dir2);
1341 *dir2 = 0;
1343 else
1345 *p = 0;
1346 pstrcpy(mask,p+1);
1349 p = strrchr(directory,'/');
1350 if (!p)
1351 *directory = 0;
1352 else
1353 *p = 0;
1355 if (strlen(directory) == 0)
1356 pstrcpy(directory,"./");
1357 memset((char *)status,'\0',21);
1358 CVAL(status,0) = dirtype;
1360 else
1362 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1363 dirtype = CVAL(status,0) & 0x1F;
1364 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1365 if (!conn->dirptr)
1366 goto SearchEmpty;
1367 string_set(&conn->dirpath,dptr_path(dptr_num));
1368 fstrcpy(mask, dptr_wcard(dptr_num));
1371 if (can_open)
1373 p = smb_buf(outbuf) + 3;
1375 ok = True;
1377 if (status_len == 0)
1379 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1380 if (dptr_num < 0)
1382 if(dptr_num == -2)
1384 if((errno == ENOENT) && bad_path)
1386 unix_ERR_class = ERRDOS;
1387 unix_ERR_code = ERRbadpath;
1389 END_PROFILE(SMBsearch);
1390 return (UNIXERROR(ERRDOS,ERRnofids));
1392 END_PROFILE(SMBsearch);
1393 return(ERROR(ERRDOS,ERRnofids));
1395 dptr_set_wcard(dptr_num, strdup(mask));
1398 DEBUG(4,("dptr_num is %d\n",dptr_num));
1400 if (ok)
1402 if ((dirtype&0x1F) == aVOLID)
1404 memcpy(p,status,21);
1405 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1406 dptr_fill(p+12,dptr_num);
1407 if (dptr_zero(p+12) && (status_len==0))
1408 numentries = 1;
1409 else
1410 numentries = 0;
1411 p += DIR_STRUCT_SIZE;
1413 else
1415 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1416 conn->dirpath,lp_dontdescend(SNUM(conn))));
1417 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1418 check_descend = True;
1420 for (i=numentries;(i<maxentries) && !finished;i++)
1422 finished =
1423 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1424 if (!finished)
1426 memcpy(p,status,21);
1427 make_dir_struct(p,mask,fname,size,mode,date);
1428 dptr_fill(p+12,dptr_num);
1429 numentries++;
1431 p += DIR_STRUCT_SIZE;
1434 } /* if (ok ) */
1438 SearchEmpty:
1440 if (numentries == 0 || !ok)
1442 CVAL(outbuf,smb_rcls) = ERRDOS;
1443 SSVAL(outbuf,smb_err,ERRnofiles);
1444 dptr_close(&dptr_num);
1447 /* If we were called as SMBffirst with smb_search_id == NULL
1448 and no entries were found then return error and close dirptr
1449 (X/Open spec) */
1451 if(ok && expect_close && numentries == 0 && status_len == 0)
1453 CVAL(outbuf,smb_rcls) = ERRDOS;
1454 SSVAL(outbuf,smb_err,ERRnofiles);
1455 /* Also close the dptr - we know it's gone */
1456 dptr_close(&dptr_num);
1459 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1460 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1461 dptr_close(&dptr_num);
1463 SSVAL(outbuf,smb_vwv0,numentries);
1464 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1465 CVAL(smb_buf(outbuf),0) = 5;
1466 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1468 if (Protocol >= PROTOCOL_NT1) {
1469 uint16 flg2 = SVAL(outbuf,smb_flg2);
1470 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1473 outsize += DIR_STRUCT_SIZE*numentries;
1474 smb_setlen(outbuf,outsize - 4);
1476 if ((! *directory) && dptr_path(dptr_num))
1477 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1479 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1480 smb_fn_name(CVAL(inbuf,smb_com)),
1481 mask, directory, dirtype, numentries, maxentries ) );
1483 END_PROFILE(SMBsearch);
1484 return(outsize);
1488 /****************************************************************************
1489 reply to a fclose (stop directory search)
1490 ****************************************************************************/
1491 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1493 int outsize = 0;
1494 int status_len;
1495 char *path;
1496 char status[21];
1497 int dptr_num= -2;
1498 START_PROFILE(SMBfclose);
1500 outsize = set_message(outbuf,1,0,True);
1501 path = smb_buf(inbuf) + 1;
1502 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1505 if (status_len == 0) {
1506 END_PROFILE(SMBfclose);
1507 return(ERROR(ERRSRV,ERRsrverror));
1510 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1512 if(dptr_fetch(status+12,&dptr_num)) {
1513 /* Close the dptr - we know it's gone */
1514 dptr_close(&dptr_num);
1517 SSVAL(outbuf,smb_vwv0,0);
1519 DEBUG(3,("search close\n"));
1521 END_PROFILE(SMBfclose);
1522 return(outsize);
1526 /****************************************************************************
1527 reply to an open
1528 ****************************************************************************/
1530 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1532 pstring fname;
1533 int outsize = 0;
1534 int fmode=0;
1535 int share_mode;
1536 SMB_OFF_T size = 0;
1537 time_t mtime=0;
1538 mode_t unixmode;
1539 int rmode=0;
1540 SMB_STRUCT_STAT sbuf;
1541 BOOL bad_path = False;
1542 files_struct *fsp;
1543 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1544 START_PROFILE(SMBopen);
1546 share_mode = SVAL(inbuf,smb_vwv0);
1548 pstrcpy(fname,smb_buf(inbuf)+1);
1550 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1552 unix_convert(fname,conn,0,&bad_path,&sbuf);
1554 unixmode = unix_mode(conn,aARCH,fname);
1556 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1557 unixmode, oplock_request,&rmode,NULL);
1559 if (!fsp)
1561 if((errno == ENOENT) && bad_path)
1563 unix_ERR_class = ERRDOS;
1564 unix_ERR_code = ERRbadpath;
1566 END_PROFILE(SMBopen);
1567 return(UNIXERROR(ERRDOS,ERRnoaccess));
1570 size = sbuf.st_size;
1571 fmode = dos_mode(conn,fname,&sbuf);
1572 mtime = sbuf.st_mtime;
1574 if (fmode & aDIR) {
1575 DEBUG(3,("attempt to open a directory %s\n",fname));
1576 close_file(fsp,False);
1577 END_PROFILE(SMBopen);
1578 return(ERROR(ERRDOS,ERRnoaccess));
1581 outsize = set_message(outbuf,7,0,True);
1582 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1583 SSVAL(outbuf,smb_vwv1,fmode);
1584 if(lp_dos_filetime_resolution(SNUM(conn)) )
1585 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1586 else
1587 put_dos_date3(outbuf,smb_vwv2,mtime);
1588 SIVAL(outbuf,smb_vwv4,(uint32)size);
1589 SSVAL(outbuf,smb_vwv6,rmode);
1591 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1592 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1595 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1596 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1597 END_PROFILE(SMBopen);
1598 return(outsize);
1602 /****************************************************************************
1603 reply to an open and X
1604 ****************************************************************************/
1605 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1607 pstring fname;
1608 int smb_mode = SVAL(inbuf,smb_vwv3);
1609 int smb_attr = SVAL(inbuf,smb_vwv5);
1610 /* Breakout the oplock request bits so we can set the
1611 reply bits separately. */
1612 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1613 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1614 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1615 #if 0
1616 int open_flags = SVAL(inbuf,smb_vwv2);
1617 int smb_sattr = SVAL(inbuf,smb_vwv4);
1618 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1619 #endif
1620 int smb_ofun = SVAL(inbuf,smb_vwv8);
1621 mode_t unixmode;
1622 SMB_OFF_T size=0;
1623 int fmode=0,mtime=0,rmode=0;
1624 SMB_STRUCT_STAT sbuf;
1625 int smb_action = 0;
1626 BOOL bad_path = False;
1627 files_struct *fsp;
1628 START_PROFILE(SMBopenX);
1630 /* If it's an IPC, pass off the pipe handler. */
1631 if (IS_IPC(conn)) {
1632 if (lp_nt_pipe_support()) {
1633 END_PROFILE(SMBopenX);
1634 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1635 } else {
1636 END_PROFILE(SMBopenX);
1637 return (ERROR(ERRSRV,ERRaccess));
1641 /* XXXX we need to handle passed times, sattr and flags */
1643 pstrcpy(fname,smb_buf(inbuf));
1645 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1647 unix_convert(fname,conn,0,&bad_path,&sbuf);
1649 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1651 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1652 oplock_request, &rmode,&smb_action);
1654 if (!fsp)
1656 if((errno == ENOENT) && bad_path)
1658 unix_ERR_class = ERRDOS;
1659 unix_ERR_code = ERRbadpath;
1661 END_PROFILE(SMBopenX);
1662 return(UNIXERROR(ERRDOS,ERRnoaccess));
1665 size = sbuf.st_size;
1666 fmode = dos_mode(conn,fname,&sbuf);
1667 mtime = sbuf.st_mtime;
1668 if (fmode & aDIR) {
1669 close_file(fsp,False);
1670 END_PROFILE(SMBopenX);
1671 return(ERROR(ERRDOS,ERRnoaccess));
1674 /* If the caller set the extended oplock request bit
1675 and we granted one (by whatever means) - set the
1676 correct bit for extended oplock reply.
1679 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1680 smb_action |= EXTENDED_OPLOCK_GRANTED;
1683 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1684 smb_action |= EXTENDED_OPLOCK_GRANTED;
1687 /* If the caller set the core oplock request bit
1688 and we granted one (by whatever means) - set the
1689 correct bit for core oplock reply.
1692 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1693 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1696 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1697 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1700 set_message(outbuf,15,0,True);
1701 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1702 SSVAL(outbuf,smb_vwv3,fmode);
1703 if(lp_dos_filetime_resolution(SNUM(conn)) )
1704 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1705 else
1706 put_dos_date3(outbuf,smb_vwv4,mtime);
1707 SIVAL(outbuf,smb_vwv6,(uint32)size);
1708 SSVAL(outbuf,smb_vwv8,rmode);
1709 SSVAL(outbuf,smb_vwv11,smb_action);
1711 END_PROFILE(SMBopenX);
1712 return chain_reply(inbuf,outbuf,length,bufsize);
1716 /****************************************************************************
1717 reply to a SMBulogoffX
1718 ****************************************************************************/
1719 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1721 uint16 vuid = SVAL(inbuf,smb_uid);
1722 user_struct *vuser = get_valid_user_struct(vuid);
1723 START_PROFILE(SMBulogoffX);
1725 if(vuser == 0) {
1726 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1729 /* in user level security we are supposed to close any files
1730 open by this user */
1731 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1732 file_close_user(vuid);
1735 invalidate_vuid(vuid);
1737 set_message(outbuf,2,0,True);
1739 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1741 END_PROFILE(SMBulogoffX);
1742 return chain_reply(inbuf,outbuf,length,bufsize);
1746 /****************************************************************************
1747 reply to a mknew or a create
1748 ****************************************************************************/
1749 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1751 pstring fname;
1752 int com;
1753 int outsize = 0;
1754 int createmode;
1755 mode_t unixmode;
1756 int ofun = 0;
1757 BOOL bad_path = False;
1758 files_struct *fsp;
1759 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1760 SMB_STRUCT_STAT sbuf;
1761 START_PROFILE(SMBcreate);
1763 com = SVAL(inbuf,smb_com);
1765 createmode = SVAL(inbuf,smb_vwv0);
1766 pstrcpy(fname,smb_buf(inbuf)+1);
1768 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1770 unix_convert(fname,conn,0,&bad_path,&sbuf);
1772 if (createmode & aVOLID) {
1773 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1776 unixmode = unix_mode(conn,createmode,fname);
1778 if(com == SMBmknew)
1780 /* We should fail if file exists. */
1781 ofun = FILE_CREATE_IF_NOT_EXIST;
1783 else
1785 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1786 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1789 /* Open file in dos compatibility share mode. */
1790 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1791 ofun, unixmode, oplock_request, NULL, NULL);
1793 if (!fsp)
1795 if((errno == ENOENT) && bad_path)
1797 unix_ERR_class = ERRDOS;
1798 unix_ERR_code = ERRbadpath;
1800 END_PROFILE(SMBcreate);
1801 return(UNIXERROR(ERRDOS,ERRnoaccess));
1804 outsize = set_message(outbuf,1,0,True);
1805 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1807 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1808 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1811 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1812 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1814 DEBUG( 2, ( "new file %s\n", fname ) );
1815 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1816 fname, fsp->fd, createmode, (int)unixmode ) );
1818 END_PROFILE(SMBcreate);
1819 return(outsize);
1823 /****************************************************************************
1824 reply to a create temporary file
1825 ****************************************************************************/
1826 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1828 pstring fname;
1829 pstring fname2;
1830 int outsize = 0;
1831 int createmode;
1832 mode_t unixmode;
1833 BOOL bad_path = False;
1834 files_struct *fsp;
1835 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1836 SMB_STRUCT_STAT sbuf;
1837 START_PROFILE(SMBctemp);
1839 createmode = SVAL(inbuf,smb_vwv0);
1840 pstrcpy(fname,smb_buf(inbuf)+1);
1841 pstrcat(fname,"/TMXXXXXX");
1843 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1845 unix_convert(fname,conn,0,&bad_path,&sbuf);
1847 unixmode = unix_mode(conn,createmode,fname);
1849 pstrcpy(fname2,(char *)smbd_mktemp(fname));
1850 /* This file should not exist. */
1851 ZERO_STRUCT(sbuf);
1852 vfs_stat(conn,fname2,&sbuf);
1854 /* Open file in dos compatibility share mode. */
1855 /* We should fail if file exists. */
1856 fsp = open_file_shared(conn,fname2,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1857 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1859 if (!fsp)
1861 if((errno == ENOENT) && bad_path)
1863 unix_ERR_class = ERRDOS;
1864 unix_ERR_code = ERRbadpath;
1866 END_PROFILE(SMBctemp);
1867 return(UNIXERROR(ERRDOS,ERRnoaccess));
1870 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1871 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1872 CVAL(smb_buf(outbuf),0) = 4;
1873 pstrcpy(smb_buf(outbuf) + 1,fname2);
1875 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1876 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1879 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1880 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1882 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1883 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1884 fname2, fsp->fd, createmode, (int)unixmode ) );
1886 END_PROFILE(SMBctemp);
1887 return(outsize);
1891 /*******************************************************************
1892 check if a user is allowed to delete a file
1893 ********************************************************************/
1894 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1896 SMB_STRUCT_STAT sbuf;
1897 int fmode;
1899 if (!CAN_WRITE(conn)) return(False);
1901 if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False);
1902 fmode = dos_mode(conn,fname,&sbuf);
1903 if (fmode & aDIR) return(False);
1904 if (!lp_delete_readonly(SNUM(conn))) {
1905 if (fmode & aRONLY) return(False);
1907 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1908 return(False);
1909 if (!check_file_sharing(conn,fname,False)) return(False);
1910 return(True);
1913 /****************************************************************************
1914 The guts of the unlink command, split out so it may be called by the NT SMB
1915 code.
1916 ****************************************************************************/
1918 int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
1919 int dirtype, char *name)
1921 pstring directory;
1922 pstring mask;
1923 char *p;
1924 int count=0;
1925 int error = ERRnoaccess;
1926 BOOL has_wild;
1927 BOOL exists=False;
1928 BOOL bad_path = False;
1929 BOOL rc = True;
1930 SMB_STRUCT_STAT sbuf;
1932 *directory = *mask = 0;
1934 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1936 p = strrchr(name,'/');
1937 if (!p) {
1938 pstrcpy(directory,"./");
1939 pstrcpy(mask,name);
1940 } else {
1941 *p = 0;
1942 pstrcpy(directory,name);
1943 pstrcpy(mask,p+1);
1947 * We should only check the mangled cache
1948 * here if unix_convert failed. This means
1949 * that the path in 'mask' doesn't exist
1950 * on the file system and so we need to look
1951 * for a possible mangle. This patch from
1952 * Tine Smukavec <valentin.smukavec@hermes.si>.
1955 if (!rc && is_mangled(mask))
1956 check_mangled_cache( mask );
1958 has_wild = ms_has_wild(mask);
1960 if (!has_wild) {
1961 pstrcat(directory,"/");
1962 pstrcat(directory,mask);
1963 if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory))
1964 count++;
1965 if (!count)
1966 exists = vfs_file_exist(conn,directory,&sbuf);
1967 } else {
1968 void *dirptr = NULL;
1969 char *dname;
1971 if (check_name(directory,conn))
1972 dirptr = OpenDir(conn, directory, True);
1974 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1975 the pattern matches against the long name, otherwise the short name
1976 We don't implement this yet XXXX
1979 if (dirptr)
1981 error = ERRbadfile;
1983 if (strequal(mask,"????????.???"))
1984 pstrcpy(mask,"*");
1986 while ((dname = ReadDirName(dirptr)))
1988 pstring fname;
1989 pstrcpy(fname,dname);
1991 if(!mask_match(fname, mask, case_sensitive)) continue;
1993 error = ERRnoaccess;
1994 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1995 if (!can_delete(fname,conn,dirtype)) continue;
1996 if (!vfs_unlink(conn,fname)) count++;
1997 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1999 CloseDir(dirptr);
2003 if (count == 0) {
2004 if (exists)
2005 return(ERROR(ERRDOS,error));
2006 else {
2007 if((errno == ENOENT) && bad_path) {
2008 unix_ERR_class = ERRDOS;
2009 unix_ERR_code = ERRbadpath;
2011 return(UNIXERROR(ERRDOS,error));
2015 return 0;
2018 /****************************************************************************
2019 Reply to a unlink
2020 ****************************************************************************/
2022 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2024 int outsize = 0;
2025 pstring name;
2026 int dirtype;
2027 START_PROFILE(SMBunlink);
2029 dirtype = SVAL(inbuf,smb_vwv0);
2031 pstrcpy(name,smb_buf(inbuf) + 1);
2033 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
2035 DEBUG(3,("reply_unlink : %s\n",name));
2037 outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
2038 if(outsize == 0) {
2041 * Win2k needs a changenotify request response before it will
2042 * update after a rename..
2045 process_pending_change_notify_queue((time_t)0);
2047 outsize = set_message(outbuf,0,0,True);
2050 END_PROFILE(SMBunlink);
2051 return(outsize);
2055 /****************************************************************************
2056 reply to a readbraw (core+ protocol)
2057 ****************************************************************************/
2059 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2061 size_t maxcount,mincount;
2062 size_t nread = 0;
2063 SMB_OFF_T startpos;
2064 char *header = outbuf;
2065 ssize_t ret=0;
2066 files_struct *fsp;
2067 START_PROFILE(SMBreadbraw);
2070 * Special check if an oplock break has been issued
2071 * and the readraw request croses on the wire, we must
2072 * return a zero length response here.
2075 if(global_oplock_break)
2077 _smb_setlen(header,0);
2078 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2079 DEBUG(5,("readbraw - oplock break finished\n"));
2080 END_PROFILE(SMBreadbraw);
2081 return -1;
2084 fsp = file_fsp(inbuf,smb_vwv0);
2086 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2088 * fsp could be NULL here so use the value from the packet. JRA.
2090 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2091 _smb_setlen(header,0);
2092 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2093 END_PROFILE(SMBreadbraw);
2094 return(-1);
2097 CHECK_FSP(fsp,conn);
2099 flush_write_cache(fsp, READRAW_FLUSH);
2101 startpos = IVAL(inbuf,smb_vwv1);
2102 if(CVAL(inbuf,smb_wct) == 10) {
2104 * This is a large offset (64 bit) read.
2106 #ifdef LARGE_SMB_OFF_T
2108 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2110 #else /* !LARGE_SMB_OFF_T */
2113 * Ensure we haven't been sent a >32 bit offset.
2116 if(IVAL(inbuf,smb_vwv8) != 0) {
2117 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2118 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2119 _smb_setlen(header,0);
2120 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2121 END_PROFILE(SMBreadbraw);
2122 return(-1);
2125 #endif /* LARGE_SMB_OFF_T */
2127 if(startpos < 0) {
2128 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2129 (double)startpos ));
2130 _smb_setlen(header,0);
2131 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2132 END_PROFILE(SMBreadbraw);
2133 return(-1);
2136 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2137 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2139 /* ensure we don't overrun the packet size */
2140 maxcount = MIN(65535,maxcount);
2141 maxcount = MAX(mincount,maxcount);
2143 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK))
2145 SMB_OFF_T size = fsp->size;
2146 SMB_OFF_T sizeneeded = startpos + maxcount;
2148 if (size < sizeneeded)
2150 SMB_STRUCT_STAT st;
2151 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2152 size = st.st_size;
2153 if (!fsp->can_write)
2154 fsp->size = size;
2157 nread = MIN(maxcount,(size - startpos));
2160 if (nread < mincount)
2161 nread = 0;
2163 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2164 fsp->fnum, (double)startpos,
2165 (int)maxcount, (int)mincount, (int)nread ) );
2167 #if UNSAFE_READRAW
2169 BOOL seek_fail = False;
2170 int predict=0;
2171 _smb_setlen(header,nread);
2173 if ((nread-predict) > 0) {
2174 if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
2175 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2176 ret = 0;
2177 seek_fail = True;
2181 if(!seek_fail)
2182 ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
2183 (SMB_OFF_T)(nread-predict),header,4+predict,
2184 startpos+predict);
2187 if (ret != nread+4)
2188 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2189 fsp->fsp_name,startpos,nread,ret));
2191 #else /* UNSAFE_READRAW */
2192 ret = read_file(fsp,header+4,startpos,nread);
2193 if (ret < mincount) ret = 0;
2195 _smb_setlen(header,ret);
2196 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2197 #endif /* UNSAFE_READRAW */
2199 DEBUG(5,("readbraw finished\n"));
2200 END_PROFILE(SMBreadbraw);
2201 return -1;
2205 /****************************************************************************
2206 reply to a lockread (core+ protocol)
2207 ****************************************************************************/
2208 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2210 ssize_t nread = -1;
2211 char *data;
2212 int outsize = 0;
2213 SMB_OFF_T startpos;
2214 size_t numtoread;
2215 int eclass;
2216 uint32 ecode;
2217 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2218 START_PROFILE(SMBlockread);
2220 CHECK_FSP(fsp,conn);
2221 CHECK_READ(fsp);
2222 CHECK_ERROR(fsp);
2224 release_level_2_oplocks_on_change(fsp);
2226 numtoread = SVAL(inbuf,smb_vwv1);
2227 startpos = IVAL(inbuf,smb_vwv2);
2229 outsize = set_message(outbuf,5,3,True);
2230 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2231 data = smb_buf(outbuf) + 3;
2234 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2235 * protocol request that predates the read/write lock concept.
2236 * Thus instead of asking for a read lock here we need to ask
2237 * for a write lock. JRA.
2240 if(!do_lock( fsp, conn, (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2241 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2243 * A blocking lock was requested. Package up
2244 * this smb into a queued request and push it
2245 * onto the blocking lock queue.
2247 if(push_blocking_lock_request(inbuf, length, -1, 0))
2248 END_PROFILE(SMBlockread);
2249 return -1;
2251 END_PROFILE(SMBlockread);
2252 return (ERROR(eclass,ecode));
2255 nread = read_file(fsp,data,startpos,numtoread);
2257 if (nread < 0) {
2258 END_PROFILE(SMBlockread);
2259 return(UNIXERROR(ERRDOS,ERRnoaccess));
2262 outsize += nread;
2263 SSVAL(outbuf,smb_vwv0,nread);
2264 SSVAL(outbuf,smb_vwv5,nread+3);
2265 SSVAL(smb_buf(outbuf),1,nread);
2267 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2268 fsp->fnum, (int)numtoread, (int)nread ) );
2270 END_PROFILE(SMBlockread);
2271 return(outsize);
2275 /****************************************************************************
2276 reply to a read
2277 ****************************************************************************/
2279 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2281 size_t numtoread;
2282 ssize_t nread = 0;
2283 char *data;
2284 SMB_OFF_T startpos;
2285 int outsize = 0;
2286 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2287 START_PROFILE(SMBread);
2289 CHECK_FSP(fsp,conn);
2290 CHECK_READ(fsp);
2291 CHECK_ERROR(fsp);
2293 numtoread = SVAL(inbuf,smb_vwv1);
2294 startpos = IVAL(inbuf,smb_vwv2);
2296 outsize = set_message(outbuf,5,3,True);
2297 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2298 data = smb_buf(outbuf) + 3;
2300 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2301 END_PROFILE(SMBread);
2302 return(ERROR(ERRDOS,ERRlock));
2305 if (numtoread > 0)
2306 nread = read_file(fsp,data,startpos,numtoread);
2308 if (nread < 0) {
2309 END_PROFILE(SMBread);
2310 return(UNIXERROR(ERRDOS,ERRnoaccess));
2313 outsize += nread;
2314 SSVAL(outbuf,smb_vwv0,nread);
2315 SSVAL(outbuf,smb_vwv5,nread+3);
2316 CVAL(smb_buf(outbuf),0) = 1;
2317 SSVAL(smb_buf(outbuf),1,nread);
2319 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2320 fsp->fnum, (int)numtoread, (int)nread ) );
2322 END_PROFILE(SMBread);
2323 return(outsize);
2327 /****************************************************************************
2328 reply to a read and X
2329 ****************************************************************************/
2330 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2332 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2333 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2334 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2335 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2336 ssize_t nread = -1;
2337 char *data;
2338 START_PROFILE(SMBreadX);
2340 /* If it's an IPC, pass off the pipe handler. */
2341 if (IS_IPC(conn)) {
2342 END_PROFILE(SMBreadX);
2343 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2346 CHECK_FSP(fsp,conn);
2347 CHECK_READ(fsp);
2348 CHECK_ERROR(fsp);
2350 set_message(outbuf,12,0,True);
2351 data = smb_buf(outbuf);
2353 if(CVAL(inbuf,smb_wct) == 12) {
2354 #ifdef LARGE_SMB_OFF_T
2356 * This is a large offset (64 bit) read.
2358 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2360 #else /* !LARGE_SMB_OFF_T */
2363 * Ensure we haven't been sent a >32 bit offset.
2366 if(IVAL(inbuf,smb_vwv10) != 0) {
2367 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2368 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2369 END_PROFILE(SMBreadX);
2370 return(ERROR(ERRDOS,ERRbadaccess));
2373 #endif /* LARGE_SMB_OFF_T */
2377 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2378 END_PROFILE(SMBreadX);
2379 return(ERROR(ERRDOS,ERRlock));
2381 nread = read_file(fsp,data,startpos,smb_maxcnt);
2383 if (nread < 0) {
2384 END_PROFILE(SMBreadX);
2385 return(UNIXERROR(ERRDOS,ERRnoaccess));
2388 SSVAL(outbuf,smb_vwv5,nread);
2389 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2390 SSVAL(smb_buf(outbuf),-2,nread);
2392 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2393 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2395 END_PROFILE(SMBreadX);
2396 return chain_reply(inbuf,outbuf,length,bufsize);
2399 /****************************************************************************
2400 reply to a writebraw (core+ or LANMAN1.0 protocol)
2401 ****************************************************************************/
2403 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2405 ssize_t nwritten=0;
2406 ssize_t total_written=0;
2407 size_t numtowrite=0;
2408 size_t tcount;
2409 SMB_OFF_T startpos;
2410 char *data=NULL;
2411 BOOL write_through;
2412 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2413 int outsize = 0;
2414 START_PROFILE(SMBwritebraw);
2416 CHECK_FSP(fsp,conn);
2417 CHECK_WRITE(fsp);
2418 CHECK_ERROR(fsp);
2420 tcount = IVAL(inbuf,smb_vwv1);
2421 startpos = IVAL(inbuf,smb_vwv3);
2422 write_through = BITSETW(inbuf+smb_vwv7,0);
2424 /* We have to deal with slightly different formats depending
2425 on whether we are using the core+ or lanman1.0 protocol */
2426 if(Protocol <= PROTOCOL_COREPLUS) {
2427 numtowrite = SVAL(smb_buf(inbuf),-2);
2428 data = smb_buf(inbuf);
2429 } else {
2430 numtowrite = SVAL(inbuf,smb_vwv10);
2431 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2434 /* force the error type */
2435 CVAL(inbuf,smb_com) = SMBwritec;
2436 CVAL(outbuf,smb_com) = SMBwritec;
2438 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2439 END_PROFILE(SMBwritebraw);
2440 return(ERROR(ERRDOS,ERRlock));
2443 if (numtowrite>0)
2444 nwritten = write_file(fsp,data,startpos,numtowrite);
2446 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2447 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2449 if (nwritten < numtowrite) {
2450 END_PROFILE(SMBwritebraw);
2451 return(UNIXERROR(ERRHRD,ERRdiskfull));
2454 total_written = nwritten;
2456 /* Return a message to the redirector to tell it
2457 to send more bytes */
2458 CVAL(outbuf,smb_com) = SMBwritebraw;
2459 SSVALS(outbuf,smb_vwv0,-1);
2460 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2461 send_smb(smbd_server_fd(),outbuf);
2463 /* Now read the raw data into the buffer and write it */
2464 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2465 exit_server("secondary writebraw failed");
2468 /* Even though this is not an smb message, smb_len
2469 returns the generic length of an smb message */
2470 numtowrite = smb_len(inbuf);
2472 if (tcount > nwritten+numtowrite) {
2473 DEBUG(3,("Client overestimated the write %d %d %d\n",
2474 (int)tcount,(int)nwritten,(int)numtowrite));
2477 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2478 (SMB_OFF_T)numtowrite,NULL,0,
2479 startpos+nwritten);
2480 total_written += nwritten;
2482 /* Set up outbuf to return the correct return */
2483 outsize = set_message(outbuf,1,0,True);
2484 CVAL(outbuf,smb_com) = SMBwritec;
2485 SSVAL(outbuf,smb_vwv0,total_written);
2487 if (nwritten < (ssize_t)numtowrite) {
2488 CVAL(outbuf,smb_rcls) = ERRHRD;
2489 SSVAL(outbuf,smb_err,ERRdiskfull);
2492 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2493 lp_strict_sync(SNUM(conn)))
2494 sync_file(conn,fsp);
2496 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2497 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2499 /* we won't return a status if write through is not selected - this
2500 follows what WfWg does */
2501 END_PROFILE(SMBwritebraw);
2502 if (!write_through && total_written==tcount) {
2503 return(-1);
2506 return(outsize);
2509 /****************************************************************************
2510 reply to a writeunlock (core+)
2511 ****************************************************************************/
2513 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2515 ssize_t nwritten = -1;
2516 size_t numtowrite;
2517 SMB_OFF_T startpos;
2518 char *data;
2519 int eclass;
2520 uint32 ecode;
2521 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2522 int outsize = 0;
2523 START_PROFILE(SMBwriteunlock);
2525 CHECK_FSP(fsp,conn);
2526 CHECK_WRITE(fsp);
2527 CHECK_ERROR(fsp);
2529 numtowrite = SVAL(inbuf,smb_vwv1);
2530 startpos = IVAL(inbuf,smb_vwv2);
2531 data = smb_buf(inbuf) + 3;
2533 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2534 END_PROFILE(SMBwriteunlock);
2535 return(ERROR(ERRDOS,ERRlock));
2538 /* The special X/Open SMB protocol handling of
2539 zero length writes is *NOT* done for
2540 this call */
2541 if(numtowrite == 0)
2542 nwritten = 0;
2543 else
2544 nwritten = write_file(fsp,data,startpos,numtowrite);
2546 if (lp_syncalways(SNUM(conn)))
2547 sync_file(conn,fsp);
2549 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2550 END_PROFILE(SMBwriteunlock);
2551 return(UNIXERROR(ERRDOS,ERRnoaccess));
2554 if(!do_unlock(fsp, conn, (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) {
2555 END_PROFILE(SMBwriteunlock);
2556 return(ERROR(eclass,ecode));
2559 outsize = set_message(outbuf,1,0,True);
2561 SSVAL(outbuf,smb_vwv0,nwritten);
2563 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2564 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2566 END_PROFILE(SMBwriteunlock);
2567 return(outsize);
2570 /****************************************************************************
2571 reply to a write
2572 ****************************************************************************/
2573 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2575 size_t numtowrite;
2576 ssize_t nwritten = -1;
2577 SMB_OFF_T startpos;
2578 char *data;
2579 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2580 int outsize = 0;
2581 START_PROFILE(SMBwrite);
2583 /* If it's an IPC, pass off the pipe handler. */
2584 if (IS_IPC(conn)) {
2585 END_PROFILE(SMBwrite);
2586 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2589 CHECK_FSP(fsp,conn);
2590 CHECK_WRITE(fsp);
2591 CHECK_ERROR(fsp);
2593 numtowrite = SVAL(inbuf,smb_vwv1);
2594 startpos = IVAL(inbuf,smb_vwv2);
2595 data = smb_buf(inbuf) + 3;
2597 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2598 END_PROFILE(SMBwrite);
2599 return(ERROR(ERRDOS,ERRlock));
2602 /* X/Open SMB protocol says that if smb_vwv1 is
2603 zero then the file size should be extended or
2604 truncated to the size given in smb_vwv[2-3] */
2605 if(numtowrite == 0) {
2606 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2607 } else
2608 nwritten = write_file(fsp,data,startpos,numtowrite);
2610 if (lp_syncalways(SNUM(conn)))
2611 sync_file(conn,fsp);
2613 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2614 END_PROFILE(SMBwrite);
2615 return(UNIXERROR(ERRDOS,ERRnoaccess));
2618 outsize = set_message(outbuf,1,0,True);
2620 SSVAL(outbuf,smb_vwv0,nwritten);
2622 if (nwritten < (ssize_t)numtowrite) {
2623 CVAL(outbuf,smb_rcls) = ERRHRD;
2624 SSVAL(outbuf,smb_err,ERRdiskfull);
2627 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2628 fsp->fnum, (int)numtowrite, (int)nwritten));
2630 END_PROFILE(SMBwrite);
2631 return(outsize);
2635 /****************************************************************************
2636 reply to a write and X
2637 ****************************************************************************/
2638 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2640 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2641 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2642 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2643 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2644 ssize_t nwritten = -1;
2645 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2646 char *data;
2647 START_PROFILE(SMBwriteX);
2649 /* If it's an IPC, pass off the pipe handler. */
2650 if (IS_IPC(conn)) {
2651 END_PROFILE(SMBwriteX);
2652 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2655 CHECK_FSP(fsp,conn);
2656 CHECK_WRITE(fsp);
2657 CHECK_ERROR(fsp);
2659 if(smb_doff > smb_len(inbuf)) {
2660 END_PROFILE(SMBwriteX);
2661 return(ERROR(ERRDOS,ERRbadmem));
2664 data = smb_base(inbuf) + smb_doff;
2666 if(CVAL(inbuf,smb_wct) == 14) {
2667 #ifdef LARGE_SMB_OFF_T
2669 * This is a large offset (64 bit) write.
2671 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2673 #else /* !LARGE_SMB_OFF_T */
2676 * Ensure we haven't been sent a >32 bit offset.
2679 if(IVAL(inbuf,smb_vwv12) != 0) {
2680 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2681 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2682 END_PROFILE(SMBwriteX);
2683 return(ERROR(ERRDOS,ERRbadaccess));
2686 #endif /* LARGE_SMB_OFF_T */
2689 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2690 END_PROFILE(SMBwriteX);
2691 return(ERROR(ERRDOS,ERRlock));
2694 /* X/Open SMB protocol says that, unlike SMBwrite
2695 if the length is zero then NO truncation is
2696 done, just a write of zero. To truncate a file,
2697 use SMBwrite. */
2698 if(numtowrite == 0)
2699 nwritten = 0;
2700 else
2701 nwritten = write_file(fsp,data,startpos,numtowrite);
2703 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2704 END_PROFILE(SMBwriteX);
2705 return(UNIXERROR(ERRDOS,ERRnoaccess));
2708 set_message(outbuf,6,0,True);
2710 SSVAL(outbuf,smb_vwv2,nwritten);
2712 if (nwritten < (ssize_t)numtowrite) {
2713 CVAL(outbuf,smb_rcls) = ERRHRD;
2714 SSVAL(outbuf,smb_err,ERRdiskfull);
2717 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2718 fsp->fnum, (int)numtowrite, (int)nwritten));
2720 if (lp_syncalways(SNUM(conn)) || write_through)
2721 sync_file(conn,fsp);
2723 END_PROFILE(SMBwriteX);
2724 return chain_reply(inbuf,outbuf,length,bufsize);
2728 /****************************************************************************
2729 reply to a lseek
2730 ****************************************************************************/
2732 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2734 SMB_OFF_T startpos;
2735 SMB_OFF_T res= -1;
2736 int mode,umode;
2737 int outsize = 0;
2738 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2739 START_PROFILE(SMBlseek);
2741 CHECK_FSP(fsp,conn);
2742 CHECK_ERROR(fsp);
2744 flush_write_cache(fsp, SEEK_FLUSH);
2746 mode = SVAL(inbuf,smb_vwv1) & 3;
2747 startpos = IVALS(inbuf,smb_vwv2);
2749 switch (mode) {
2750 case 0: umode = SEEK_SET; break;
2751 case 1: umode = SEEK_CUR; break;
2752 case 2: umode = SEEK_END; break;
2753 default:
2754 umode = SEEK_SET; break;
2757 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2759 * Check for the special case where a seek before the start
2760 * of the file sets the offset to zero. Added in the CIFS spec,
2761 * section 4.2.7.
2764 if(errno == EINVAL) {
2765 SMB_OFF_T current_pos = startpos;
2767 if(umode == SEEK_CUR) {
2769 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2770 END_PROFILE(SMBlseek);
2771 return(UNIXERROR(ERRDOS,ERRnoaccess));
2774 current_pos += startpos;
2776 } else if (umode == SEEK_END) {
2778 SMB_STRUCT_STAT sbuf;
2780 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2781 END_PROFILE(SMBlseek);
2782 return(UNIXERROR(ERRDOS,ERRnoaccess));
2785 current_pos += sbuf.st_size;
2788 if(current_pos < 0)
2789 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2792 if(res == -1) {
2793 END_PROFILE(SMBlseek);
2794 return(UNIXERROR(ERRDOS,ERRnoaccess));
2798 fsp->pos = res;
2800 outsize = set_message(outbuf,2,0,True);
2801 SIVAL(outbuf,smb_vwv0,res);
2803 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2804 fsp->fnum, (double)startpos, (double)res, mode));
2806 END_PROFILE(SMBlseek);
2807 return(outsize);
2810 /****************************************************************************
2811 reply to a flush
2812 ****************************************************************************/
2814 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2816 int outsize = set_message(outbuf,0,0,True);
2817 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2818 START_PROFILE(SMBflush);
2820 if (fsp) {
2821 CHECK_FSP(fsp,conn);
2822 CHECK_ERROR(fsp);
2825 if (!fsp) {
2826 file_sync_all(conn);
2827 } else {
2828 sync_file(conn,fsp);
2831 DEBUG(3,("flush\n"));
2832 END_PROFILE(SMBflush);
2833 return(outsize);
2837 /****************************************************************************
2838 reply to a exit
2839 ****************************************************************************/
2840 int reply_exit(connection_struct *conn,
2841 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2843 int outsize;
2844 START_PROFILE(SMBexit);
2845 outsize = set_message(outbuf,0,0,True);
2847 DEBUG(3,("exit\n"));
2849 END_PROFILE(SMBexit);
2850 return(outsize);
2854 /****************************************************************************
2855 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2856 ****************************************************************************/
2857 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2858 int dum_buffsize)
2860 int outsize = 0;
2861 time_t mtime;
2862 int32 eclass = 0, err = 0;
2863 files_struct *fsp = NULL;
2864 START_PROFILE(SMBclose);
2866 outsize = set_message(outbuf,0,0,True);
2868 /* If it's an IPC, pass off to the pipe handler. */
2869 if (IS_IPC(conn)) {
2870 END_PROFILE(SMBclose);
2871 return reply_pipe_close(conn, inbuf,outbuf);
2874 fsp = file_fsp(inbuf,smb_vwv0);
2877 * We can only use CHECK_FSP if we know it's not a directory.
2880 if(!fsp || (fsp->conn != conn)) {
2881 END_PROFILE(SMBclose);
2882 return(ERROR(ERRDOS,ERRbadfid));
2885 if(HAS_CACHED_ERROR(fsp)) {
2886 eclass = fsp->wbmpx_ptr->wr_errclass;
2887 err = fsp->wbmpx_ptr->wr_error;
2890 if(fsp->is_directory || fsp->stat_open) {
2892 * Special case - close NT SMB directory or stat file
2893 * handle.
2895 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2896 close_file(fsp,True);
2897 } else {
2899 * Close ordinary file.
2901 int close_err;
2904 * If there was a modify time outstanding,
2905 * try and set it here.
2907 if(fsp->pending_modtime)
2908 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2911 * Now take care of any time sent in the close.
2913 mtime = make_unix_date3(inbuf+smb_vwv1);
2915 /* try and set the date */
2916 set_filetime(conn, fsp->fsp_name,mtime);
2918 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2919 fsp->fd, fsp->fnum,
2920 conn->num_files_open));
2923 * close_file() returns the unix errno if an error
2924 * was detected on close - normally this is due to
2925 * a disk full error. If not then it was probably an I/O error.
2928 if((close_err = close_file(fsp,True)) != 0) {
2929 errno = close_err;
2930 END_PROFILE(SMBclose);
2931 return (UNIXERROR(ERRHRD,ERRgeneral));
2935 /* We have a cached error */
2936 if(eclass || err) {
2937 END_PROFILE(SMBclose);
2938 return(ERROR(eclass,err));
2941 END_PROFILE(SMBclose);
2942 return(outsize);
2946 /****************************************************************************
2947 reply to a writeclose (Core+ protocol)
2948 ****************************************************************************/
2950 int reply_writeclose(connection_struct *conn,
2951 char *inbuf,char *outbuf, int size, int dum_buffsize)
2953 size_t numtowrite;
2954 ssize_t nwritten = -1;
2955 int outsize = 0;
2956 int close_err = 0;
2957 SMB_OFF_T startpos;
2958 char *data;
2959 time_t mtime;
2960 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2961 START_PROFILE(SMBwriteclose);
2963 CHECK_FSP(fsp,conn);
2964 CHECK_WRITE(fsp);
2965 CHECK_ERROR(fsp);
2967 numtowrite = SVAL(inbuf,smb_vwv1);
2968 startpos = IVAL(inbuf,smb_vwv2);
2969 mtime = make_unix_date3(inbuf+smb_vwv4);
2970 data = smb_buf(inbuf) + 1;
2972 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2973 END_PROFILE(SMBwriteclose);
2974 return(ERROR(ERRDOS,ERRlock));
2977 nwritten = write_file(fsp,data,startpos,numtowrite);
2979 set_filetime(conn, fsp->fsp_name,mtime);
2981 close_err = close_file(fsp,True);
2983 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2984 fsp->fnum, (int)numtowrite, (int)nwritten,
2985 conn->num_files_open));
2987 if (nwritten <= 0) {
2988 END_PROFILE(SMBwriteclose);
2989 return(UNIXERROR(ERRDOS,ERRnoaccess));
2992 if(close_err != 0) {
2993 errno = close_err;
2994 END_PROFILE(SMBwriteclose);
2995 return(UNIXERROR(ERRHRD,ERRgeneral));
2998 outsize = set_message(outbuf,1,0,True);
3000 SSVAL(outbuf,smb_vwv0,nwritten);
3001 END_PROFILE(SMBwriteclose);
3002 return(outsize);
3006 /****************************************************************************
3007 reply to a lock
3008 ****************************************************************************/
3009 int reply_lock(connection_struct *conn,
3010 char *inbuf,char *outbuf, int length, int dum_buffsize)
3012 int outsize = set_message(outbuf,0,0,True);
3013 SMB_BIG_UINT count,offset;
3014 int eclass;
3015 uint32 ecode;
3016 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3017 START_PROFILE(SMBlock);
3019 CHECK_FSP(fsp,conn);
3020 CHECK_ERROR(fsp);
3022 release_level_2_oplocks_on_change(fsp);
3024 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3025 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3027 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3028 fsp->fd, fsp->fnum, (double)offset, (double)count));
3030 if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode)) {
3031 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
3033 * A blocking lock was requested. Package up
3034 * this smb into a queued request and push it
3035 * onto the blocking lock queue.
3037 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
3038 END_PROFILE(SMBlock);
3039 return -1;
3042 END_PROFILE(SMBlock);
3043 return (ERROR(eclass,ecode));
3046 END_PROFILE(SMBlock);
3047 return(outsize);
3051 /****************************************************************************
3052 reply to a unlock
3053 ****************************************************************************/
3054 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3056 int outsize = set_message(outbuf,0,0,True);
3057 SMB_BIG_UINT count,offset;
3058 int eclass;
3059 uint32 ecode;
3060 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3061 START_PROFILE(SMBunlock);
3063 CHECK_FSP(fsp,conn);
3064 CHECK_ERROR(fsp);
3066 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3067 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3069 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode)) {
3070 END_PROFILE(SMBunlock);
3071 return (ERROR(eclass,ecode));
3074 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3075 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3077 END_PROFILE(SMBunlock);
3078 return(outsize);
3082 /****************************************************************************
3083 reply to a tdis
3084 ****************************************************************************/
3085 int reply_tdis(connection_struct *conn,
3086 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3088 int outsize = set_message(outbuf,0,0,True);
3089 uint16 vuid;
3090 START_PROFILE(SMBtdis);
3092 vuid = SVAL(inbuf,smb_uid);
3094 if (!conn) {
3095 DEBUG(4,("Invalid connection in tdis\n"));
3096 END_PROFILE(SMBtdis);
3097 return(ERROR(ERRSRV,ERRinvnid));
3100 conn->used = False;
3102 close_cnum(conn,vuid);
3104 END_PROFILE(SMBtdis);
3105 return outsize;
3110 /****************************************************************************
3111 reply to a echo
3112 ****************************************************************************/
3113 int reply_echo(connection_struct *conn,
3114 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3116 int smb_reverb = SVAL(inbuf,smb_vwv0);
3117 int seq_num;
3118 unsigned int data_len = smb_buflen(inbuf);
3119 int outsize = set_message(outbuf,1,data_len,True);
3120 START_PROFILE(SMBecho);
3122 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3124 /* copy any incoming data back out */
3125 if (data_len > 0)
3126 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3128 if (smb_reverb > 100) {
3129 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3130 smb_reverb = 100;
3133 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3134 SSVAL(outbuf,smb_vwv0,seq_num);
3136 smb_setlen(outbuf,outsize - 4);
3138 send_smb(smbd_server_fd(),outbuf);
3141 DEBUG(3,("echo %d times\n", smb_reverb));
3143 smb_echo_count++;
3145 END_PROFILE(SMBecho);
3146 return -1;
3150 /****************************************************************************
3151 reply to a printopen
3152 ****************************************************************************/
3153 int reply_printopen(connection_struct *conn,
3154 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3156 int outsize = 0;
3157 files_struct *fsp;
3158 START_PROFILE(SMBsplopen);
3160 if (!CAN_PRINT(conn)) {
3161 END_PROFILE(SMBsplopen);
3162 return(ERROR(ERRDOS,ERRnoaccess));
3165 /* Open for exclusive use, write only. */
3166 fsp = print_fsp_open(conn,"dos.prn");
3168 if (!fsp) {
3169 END_PROFILE(SMBsplopen);
3170 return(UNIXERROR(ERRDOS,ERRnoaccess));
3173 outsize = set_message(outbuf,1,0,True);
3174 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3176 DEBUG(3,("openprint fd=%d fnum=%d\n",
3177 fsp->fd, fsp->fnum));
3179 END_PROFILE(SMBsplopen);
3180 return(outsize);
3184 /****************************************************************************
3185 reply to a printclose
3186 ****************************************************************************/
3187 int reply_printclose(connection_struct *conn,
3188 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3190 int outsize = set_message(outbuf,0,0,True);
3191 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3192 int close_err = 0;
3193 START_PROFILE(SMBsplclose);
3195 CHECK_FSP(fsp,conn);
3196 CHECK_ERROR(fsp);
3198 if (!CAN_PRINT(conn)) {
3199 END_PROFILE(SMBsplclose);
3200 return(ERROR(ERRDOS,ERRnoaccess));
3203 DEBUG(3,("printclose fd=%d fnum=%d\n",
3204 fsp->fd,fsp->fnum));
3206 close_err = close_file(fsp,True);
3208 if(close_err != 0) {
3209 errno = close_err;
3210 END_PROFILE(SMBsplclose);
3211 return(UNIXERROR(ERRHRD,ERRgeneral));
3214 END_PROFILE(SMBsplclose);
3215 return(outsize);
3219 /****************************************************************************
3220 reply to a printqueue
3221 ****************************************************************************/
3222 int reply_printqueue(connection_struct *conn,
3223 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3225 int outsize = set_message(outbuf,2,3,True);
3226 int max_count = SVAL(inbuf,smb_vwv0);
3227 int start_index = SVAL(inbuf,smb_vwv1);
3228 START_PROFILE(SMBsplretq);
3230 /* we used to allow the client to get the cnum wrong, but that
3231 is really quite gross and only worked when there was only
3232 one printer - I think we should now only accept it if they
3233 get it right (tridge) */
3234 if (!CAN_PRINT(conn)) {
3235 END_PROFILE(SMBsplretq);
3236 return(ERROR(ERRDOS,ERRnoaccess));
3239 SSVAL(outbuf,smb_vwv0,0);
3240 SSVAL(outbuf,smb_vwv1,0);
3241 CVAL(smb_buf(outbuf),0) = 1;
3242 SSVAL(smb_buf(outbuf),1,0);
3244 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3245 start_index, max_count));
3248 print_queue_struct *queue = NULL;
3249 char *p = smb_buf(outbuf) + 3;
3250 int count = print_queue_status(SNUM(conn), &queue,NULL);
3251 int num_to_get = ABS(max_count);
3252 int first = (max_count>0?start_index:start_index+max_count+1);
3253 int i;
3255 if (first >= count)
3256 num_to_get = 0;
3257 else
3258 num_to_get = MIN(num_to_get,count-first);
3261 for (i=first;i<first+num_to_get;i++) {
3262 put_dos_date2(p,0,queue[i].time);
3263 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3264 SSVAL(p,5, queue[i].job);
3265 SIVAL(p,7,queue[i].size);
3266 CVAL(p,11) = 0;
3267 StrnCpy(p+12,queue[i].user,16);
3268 p += 28;
3271 if (count > 0) {
3272 outsize = set_message(outbuf,2,28*count+3,False);
3273 SSVAL(outbuf,smb_vwv0,count);
3274 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3275 CVAL(smb_buf(outbuf),0) = 1;
3276 SSVAL(smb_buf(outbuf),1,28*count);
3279 if (queue) free(queue);
3281 DEBUG(3,("%d entries returned in queue\n",count));
3284 END_PROFILE(SMBsplretq);
3285 return(outsize);
3289 /****************************************************************************
3290 reply to a printwrite
3291 ****************************************************************************/
3292 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3294 int numtowrite;
3295 int outsize = set_message(outbuf,0,0,True);
3296 char *data;
3297 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3298 START_PROFILE(SMBsplwr);
3300 if (!CAN_PRINT(conn)) {
3301 END_PROFILE(SMBsplwr);
3302 return(ERROR(ERRDOS,ERRnoaccess));
3305 CHECK_FSP(fsp,conn);
3306 CHECK_WRITE(fsp);
3307 CHECK_ERROR(fsp);
3309 numtowrite = SVAL(smb_buf(inbuf),1);
3310 data = smb_buf(inbuf) + 3;
3312 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3313 END_PROFILE(SMBsplwr);
3314 return(UNIXERROR(ERRDOS,ERRnoaccess));
3317 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3319 END_PROFILE(SMBsplwr);
3320 return(outsize);
3324 /****************************************************************************
3325 The guts of the mkdir command, split out so it may be called by the NT SMB
3326 code.
3327 ****************************************************************************/
3328 int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
3330 BOOL bad_path = False;
3331 SMB_STRUCT_STAT sbuf;
3332 int ret= -1;
3334 unix_convert(directory,conn,0,&bad_path,&sbuf);
3336 if (check_name(directory, conn))
3337 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3339 if (ret < 0)
3341 if((errno == ENOENT) && bad_path)
3343 unix_ERR_class = ERRDOS;
3344 unix_ERR_code = ERRbadpath;
3346 return(UNIXERROR(ERRDOS,ERRnoaccess));
3349 return ret;
3352 /****************************************************************************
3353 reply to a mkdir
3354 ****************************************************************************/
3355 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3357 pstring directory;
3358 int outsize;
3359 START_PROFILE(SMBmkdir);
3361 pstrcpy(directory,smb_buf(inbuf) + 1);
3363 outsize=mkdir_internal(conn, inbuf, outbuf, directory);
3364 if(outsize == 0)
3365 outsize = set_message(outbuf,0,0,True);
3367 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3369 END_PROFILE(SMBmkdir);
3370 return(outsize);
3373 /****************************************************************************
3374 Static function used by reply_rmdir to delete an entire directory
3375 tree recursively.
3376 ****************************************************************************/
3378 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3380 char *dname = NULL;
3381 BOOL ret = False;
3382 void *dirptr = OpenDir(NULL, directory, False);
3384 if(dirptr == NULL)
3385 return True;
3387 while((dname = ReadDirName(dirptr)))
3389 pstring fullname;
3390 SMB_STRUCT_STAT st;
3392 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3393 continue;
3395 /* Construct the full name. */
3396 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3398 errno = ENOMEM;
3399 ret = True;
3400 break;
3402 pstrcpy(fullname, directory);
3403 pstrcat(fullname, "/");
3404 pstrcat(fullname, dname);
3406 if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname,False), &st) != 0)
3408 ret = True;
3409 break;
3412 if(st.st_mode & S_IFDIR)
3414 if(recursive_rmdir(conn, fullname)!=0)
3416 ret = True;
3417 break;
3419 if(vfs_rmdir(conn,fullname) != 0)
3421 ret = True;
3422 break;
3425 else if(vfs_unlink(conn,fullname) != 0)
3427 ret = True;
3428 break;
3431 CloseDir(dirptr);
3432 return ret;
3435 /****************************************************************************
3436 The internals of the rmdir code - called elsewhere.
3437 ****************************************************************************/
3439 BOOL rmdir_internals(connection_struct *conn, char *directory)
3441 BOOL ok;
3443 ok = (vfs_rmdir(conn,directory) == 0);
3444 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3447 * Check to see if the only thing in this directory are
3448 * vetoed files/directories. If so then delete them and
3449 * retry. If we fail to delete any of them (and we *don't*
3450 * do a recursive delete) then fail the rmdir.
3452 BOOL all_veto_files = True;
3453 char *dname;
3454 void *dirptr = OpenDir(conn, directory, False);
3456 if(dirptr != NULL)
3458 int dirpos = TellDir(dirptr);
3459 while ((dname = ReadDirName(dirptr)))
3461 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3462 continue;
3463 if(!IS_VETO_PATH(conn, dname))
3465 all_veto_files = False;
3466 break;
3469 if(all_veto_files)
3471 SeekDir(dirptr,dirpos);
3472 while ((dname = ReadDirName(dirptr)))
3474 pstring fullname;
3475 SMB_STRUCT_STAT st;
3477 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3478 continue;
3480 /* Construct the full name. */
3481 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3483 errno = ENOMEM;
3484 break;
3486 pstrcpy(fullname, directory);
3487 pstrcat(fullname, "/");
3488 pstrcat(fullname, dname);
3490 if(conn->vfs_ops.lstat(conn,dos_to_unix(fullname, False), &st) != 0)
3491 break;
3492 if(st.st_mode & S_IFDIR)
3494 if(lp_recursive_veto_delete(SNUM(conn)))
3496 if(recursive_rmdir(conn, fullname) != 0)
3497 break;
3499 if(vfs_rmdir(conn,fullname) != 0)
3500 break;
3502 else if(vfs_unlink(conn,fullname) != 0)
3503 break;
3505 CloseDir(dirptr);
3506 /* Retry the rmdir */
3507 ok = (vfs_rmdir(conn,directory) == 0);
3509 else
3510 CloseDir(dirptr);
3512 else
3513 errno = ENOTEMPTY;
3516 if (!ok)
3517 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3518 directory,strerror(errno)));
3520 return ok;
3523 /****************************************************************************
3524 Reply to a rmdir.
3525 ****************************************************************************/
3527 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3529 pstring directory;
3530 int outsize = 0;
3531 BOOL ok = False;
3532 BOOL bad_path = False;
3533 SMB_STRUCT_STAT sbuf;
3534 START_PROFILE(SMBrmdir);
3536 pstrcpy(directory,smb_buf(inbuf) + 1);
3538 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3540 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3542 if (check_name(directory,conn))
3544 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3545 ok = rmdir_internals(conn, directory);
3548 if (!ok)
3550 if((errno == ENOENT) && bad_path)
3552 unix_ERR_class = ERRDOS;
3553 unix_ERR_code = ERRbadpath;
3555 END_PROFILE(SMBrmdir);
3556 return(UNIXERROR(ERRDOS,ERRbadpath));
3559 outsize = set_message(outbuf,0,0,True);
3561 DEBUG( 3, ( "rmdir %s\n", directory ) );
3563 END_PROFILE(SMBrmdir);
3564 return(outsize);
3568 /*******************************************************************
3569 resolve wildcards in a filename rename
3570 ********************************************************************/
3571 static BOOL resolve_wildcards(char *name1,char *name2)
3573 fstring root1,root2;
3574 fstring ext1,ext2;
3575 char *p,*p2;
3577 name1 = strrchr(name1,'/');
3578 name2 = strrchr(name2,'/');
3580 if (!name1 || !name2) return(False);
3582 fstrcpy(root1,name1);
3583 fstrcpy(root2,name2);
3584 p = strrchr(root1,'.');
3585 if (p) {
3586 *p = 0;
3587 fstrcpy(ext1,p+1);
3588 } else {
3589 fstrcpy(ext1,"");
3591 p = strrchr(root2,'.');
3592 if (p) {
3593 *p = 0;
3594 fstrcpy(ext2,p+1);
3595 } else {
3596 fstrcpy(ext2,"");
3599 p = root1;
3600 p2 = root2;
3601 while (*p2) {
3602 if (*p2 == '?') {
3603 *p2 = *p;
3604 p2++;
3605 } else {
3606 p2++;
3608 if (*p) p++;
3611 p = ext1;
3612 p2 = ext2;
3613 while (*p2) {
3614 if (*p2 == '?') {
3615 *p2 = *p;
3616 p2++;
3617 } else {
3618 p2++;
3620 if (*p) p++;
3623 pstrcpy(name2,root2);
3624 if (ext2[0]) {
3625 pstrcat(name2,".");
3626 pstrcat(name2,ext2);
3629 return(True);
3632 /*******************************************************************
3633 check if a user is allowed to rename a file
3634 ********************************************************************/
3635 static BOOL can_rename(char *fname,connection_struct *conn)
3637 SMB_STRUCT_STAT sbuf;
3639 if (!CAN_WRITE(conn)) return(False);
3641 if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False);
3642 if (!check_file_sharing(conn,fname,True)) return(False);
3643 return(True);
3646 /****************************************************************************
3647 The guts of the rename command, split out so it may be called by the NT SMB
3648 code.
3649 ****************************************************************************/
3650 int rename_internals(connection_struct *conn,
3651 char *inbuf, char *outbuf, char *name,
3652 char *newname, BOOL replace_if_exists)
3654 pstring directory;
3655 pstring mask;
3656 pstring newname_last_component;
3657 char *p;
3658 BOOL has_wild;
3659 BOOL bad_path1 = False;
3660 BOOL bad_path2 = False;
3661 int count=0;
3662 int error = ERRnoaccess;
3663 BOOL exists=False;
3664 BOOL rc = True;
3665 SMB_STRUCT_STAT sbuf1, sbuf2;
3666 pstring zdirectory;
3668 *directory = *mask = 0;
3670 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3671 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3674 * Split the old name into directory and last component
3675 * strings. Note that unix_convert may have stripped off a
3676 * leading ./ from both name and newname if the rename is
3677 * at the root of the share. We need to make sure either both
3678 * name and newname contain a / character or neither of them do
3679 * as this is checked in resolve_wildcards().
3682 p = strrchr(name,'/');
3683 if (!p) {
3684 pstrcpy(directory,".");
3685 pstrcpy(mask,name);
3686 } else {
3687 *p = 0;
3688 pstrcpy(directory,name);
3689 pstrcpy(mask,p+1);
3690 *p = '/'; /* Replace needed for exceptional test below. */
3694 * We should only check the mangled cache
3695 * here if unix_convert failed. This means
3696 * that the path in 'mask' doesn't exist
3697 * on the file system and so we need to look
3698 * for a possible mangle. This patch from
3699 * Tine Smukavec <valentin.smukavec@hermes.si>.
3702 if (!rc && is_mangled(mask))
3703 check_mangled_cache( mask );
3705 has_wild = ms_has_wild(mask);
3707 if (!has_wild) {
3709 * No wildcards - just process the one file.
3711 BOOL is_short_name = is_8_3(name, True);
3713 /* Add a terminating '/' to the directory name. */
3714 pstrcat(directory,"/");
3715 pstrcat(directory,mask);
3717 /* Ensure newname contains a '/' also */
3718 if(strrchr(newname,'/') == 0) {
3719 pstring tmpstr;
3721 pstrcpy(tmpstr, "./");
3722 pstrcat(tmpstr, newname);
3723 pstrcpy(newname, tmpstr);
3726 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",
3727 case_sensitive, case_preserve, short_case_preserve, directory,
3728 newname, newname_last_component, is_short_name));
3731 * Check for special case with case preserving and not
3732 * case sensitive, if directory and newname are identical,
3733 * and the old last component differs from the original
3734 * last component only by case, then we should allow
3735 * the rename (user is trying to change the case of the
3736 * filename).
3738 if((case_sensitive == False) &&
3739 (((case_preserve == True) &&
3740 (is_short_name == False)) ||
3741 ((short_case_preserve == True) &&
3742 (is_short_name == True))) &&
3743 strcsequal(directory, newname)) {
3744 pstring newname_modified_last_component;
3747 * Get the last component of the modified name.
3748 * Note that we guarantee that newname contains a '/'
3749 * character above.
3751 p = strrchr(newname,'/');
3752 pstrcpy(newname_modified_last_component,p+1);
3754 if(strcsequal(newname_modified_last_component,
3755 newname_last_component) == False) {
3757 * Replace the modified last component with
3758 * the original.
3760 pstrcpy(p+1, newname_last_component);
3764 pstrcpy(zdirectory, dos_to_unix(directory, False));
3765 if(replace_if_exists) {
3767 * NT SMB specific flag - rename can overwrite
3768 * file with the same name so don't check for
3769 * vfs_file_exist().
3772 if(resolve_wildcards(directory,newname) &&
3773 can_rename(directory,conn) &&
3774 !conn->vfs_ops.rename(conn,zdirectory,
3775 dos_to_unix(newname,False)))
3776 count++;
3777 } else {
3778 if (resolve_wildcards(directory,newname) &&
3779 can_rename(directory,conn) &&
3780 !vfs_file_exist(conn,newname,NULL) &&
3781 !conn->vfs_ops.rename(conn,zdirectory,
3782 dos_to_unix(newname,False)))
3783 count++;
3786 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3787 directory,newname));
3789 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3790 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3791 exists = True;
3792 error = ERRrename;
3794 } else {
3796 * Wildcards - process each file that matches.
3798 void *dirptr = NULL;
3799 char *dname;
3800 pstring destname;
3802 if (check_name(directory,conn))
3803 dirptr = OpenDir(conn, directory, True);
3805 if (dirptr) {
3806 error = ERRbadfile;
3808 if (strequal(mask,"????????.???"))
3809 pstrcpy(mask,"*");
3811 while ((dname = ReadDirName(dirptr))) {
3812 pstring fname;
3814 pstrcpy(fname,dname);
3816 if(!mask_match(fname, mask, case_sensitive))
3817 continue;
3819 error = ERRnoaccess;
3820 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3821 if (!can_rename(fname,conn)) {
3822 DEBUG(6,("rename %s refused\n", fname));
3823 continue;
3825 pstrcpy(destname,newname);
3827 if (!resolve_wildcards(fname,destname)) {
3828 DEBUG(6,("resolve_wildcards %s %s failed\n",
3829 fname, destname));
3830 continue;
3833 if (!replace_if_exists &&
3834 vfs_file_exist(conn,destname, NULL)) {
3835 DEBUG(6,("file_exist %s\n", destname));
3836 error = 183;
3837 continue;
3840 if (!conn->vfs_ops.rename(conn,dos_to_unix(fname,False),
3841 dos_to_unix(destname,False)))
3842 count++;
3843 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3845 CloseDir(dirptr);
3849 if (count == 0) {
3850 if (exists)
3851 return(ERROR(ERRDOS,error));
3852 else {
3853 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3854 unix_ERR_class = ERRDOS;
3855 unix_ERR_code = ERRbadpath;
3857 return(UNIXERROR(ERRDOS,error));
3861 return 0;
3864 /****************************************************************************
3865 Reply to a mv.
3866 ****************************************************************************/
3868 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3870 int outsize = 0;
3871 pstring name;
3872 pstring newname;
3873 START_PROFILE(SMBmv);
3875 pstrcpy(name,smb_buf(inbuf) + 1);
3876 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3878 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3879 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3881 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3883 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3884 if(outsize == 0) {
3887 * Win2k needs a changenotify request response before it will
3888 * update after a rename..
3891 process_pending_change_notify_queue((time_t)0);
3893 outsize = set_message(outbuf,0,0,True);
3896 END_PROFILE(SMBmv);
3897 return(outsize);
3900 /*******************************************************************
3901 copy a file as part of a reply_copy
3902 ******************************************************************/
3904 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3905 int count,BOOL target_is_directory, int *err_ret)
3907 int Access,action;
3908 SMB_STRUCT_STAT src_sbuf, sbuf2;
3909 SMB_OFF_T ret=-1;
3910 files_struct *fsp1,*fsp2;
3911 pstring dest;
3913 *err_ret = 0;
3915 pstrcpy(dest,dest1);
3916 if (target_is_directory) {
3917 char *p = strrchr(src,'/');
3918 if (p)
3919 p++;
3920 else
3921 p = src;
3922 pstrcat(dest,"/");
3923 pstrcat(dest,p);
3926 if (!vfs_file_exist(conn,src,&src_sbuf))
3927 return(False);
3929 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3930 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3932 if (!fsp1) {
3933 return(False);
3936 if (!target_is_directory && count)
3937 ofun = FILE_EXISTS_OPEN;
3939 vfs_stat(conn,dest,&sbuf2);
3940 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3941 ofun,src_sbuf.st_mode,0,&Access,&action);
3943 if (!fsp2) {
3944 close_file(fsp1,False);
3945 return(False);
3948 if ((ofun&3) == 1) {
3949 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3950 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3951 strerror(errno) ));
3953 * Stop the copy from occurring.
3955 ret = -1;
3956 src_sbuf.st_size = 0;
3960 if (src_sbuf.st_size)
3961 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
3963 close_file(fsp1,False);
3965 * As we are opening fsp1 read-only we only expect
3966 * an error on close on fsp2 if we are out of space.
3967 * Thus we don't look at the error return from the
3968 * close of fsp1.
3970 *err_ret = close_file(fsp2,False);
3972 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3977 /****************************************************************************
3978 reply to a file copy.
3979 ****************************************************************************/
3980 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3982 int outsize = 0;
3983 pstring name;
3984 pstring directory;
3985 pstring mask,newname;
3986 char *p;
3987 int count=0;
3988 int error = ERRnoaccess;
3989 int err = 0;
3990 BOOL has_wild;
3991 BOOL exists=False;
3992 int tid2 = SVAL(inbuf,smb_vwv0);
3993 int ofun = SVAL(inbuf,smb_vwv1);
3994 int flags = SVAL(inbuf,smb_vwv2);
3995 BOOL target_is_directory=False;
3996 BOOL bad_path1 = False;
3997 BOOL bad_path2 = False;
3998 BOOL rc = True;
3999 SMB_STRUCT_STAT sbuf1, sbuf2;
4000 START_PROFILE(SMBcopy);
4002 *directory = *mask = 0;
4004 pstrcpy(name,smb_buf(inbuf));
4005 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
4007 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4009 if (tid2 != conn->cnum) {
4010 /* can't currently handle inter share copies XXXX */
4011 DEBUG(3,("Rejecting inter-share copy\n"));
4012 END_PROFILE(SMBcopy);
4013 return(ERROR(ERRSRV,ERRinvdevice));
4016 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4017 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4019 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4020 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4022 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4024 if ((flags&1) && target_is_directory) {
4025 END_PROFILE(SMBcopy);
4026 return(ERROR(ERRDOS,ERRbadfile));
4029 if ((flags&2) && !target_is_directory) {
4030 END_PROFILE(SMBcopy);
4031 return(ERROR(ERRDOS,ERRbadpath));
4034 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4035 /* wants a tree copy! XXXX */
4036 DEBUG(3,("Rejecting tree copy\n"));
4037 END_PROFILE(SMBcopy);
4038 return(ERROR(ERRSRV,ERRerror));
4041 p = strrchr(name,'/');
4042 if (!p) {
4043 pstrcpy(directory,"./");
4044 pstrcpy(mask,name);
4045 } else {
4046 *p = 0;
4047 pstrcpy(directory,name);
4048 pstrcpy(mask,p+1);
4052 * We should only check the mangled cache
4053 * here if unix_convert failed. This means
4054 * that the path in 'mask' doesn't exist
4055 * on the file system and so we need to look
4056 * for a possible mangle. This patch from
4057 * Tine Smukavec <valentin.smukavec@hermes.si>.
4060 if (!rc && is_mangled(mask))
4061 check_mangled_cache( mask );
4063 has_wild = ms_has_wild(mask);
4065 if (!has_wild) {
4066 pstrcat(directory,"/");
4067 pstrcat(directory,mask);
4068 if (resolve_wildcards(directory,newname) &&
4069 copy_file(directory,newname,conn,ofun,
4070 count,target_is_directory,&err)) count++;
4071 if(!count && err) {
4072 errno = err;
4073 END_PROFILE(SMBcopy);
4074 return(UNIXERROR(ERRHRD,ERRgeneral));
4076 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4077 } else {
4078 void *dirptr = NULL;
4079 char *dname;
4080 pstring destname;
4082 if (check_name(directory,conn))
4083 dirptr = OpenDir(conn, directory, True);
4085 if (dirptr) {
4086 error = ERRbadfile;
4088 if (strequal(mask,"????????.???"))
4089 pstrcpy(mask,"*");
4091 while ((dname = ReadDirName(dirptr))) {
4092 pstring fname;
4093 pstrcpy(fname,dname);
4095 if(!mask_match(fname, mask, case_sensitive))
4096 continue;
4098 error = ERRnoaccess;
4099 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4100 pstrcpy(destname,newname);
4101 if (resolve_wildcards(fname,destname) &&
4102 copy_file(fname,destname,conn,ofun,
4103 count,target_is_directory,&err)) count++;
4104 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4106 CloseDir(dirptr);
4110 if (count == 0) {
4111 if(err) {
4112 /* Error on close... */
4113 errno = err;
4114 END_PROFILE(SMBcopy);
4115 return(UNIXERROR(ERRHRD,ERRgeneral));
4118 if (exists) {
4119 END_PROFILE(SMBcopy);
4120 return(ERROR(ERRDOS,error));
4121 } else
4123 if((errno == ENOENT) && (bad_path1 || bad_path2))
4125 unix_ERR_class = ERRDOS;
4126 unix_ERR_code = ERRbadpath;
4128 END_PROFILE(SMBcopy);
4129 return(UNIXERROR(ERRDOS,error));
4133 outsize = set_message(outbuf,1,0,True);
4134 SSVAL(outbuf,smb_vwv0,count);
4136 END_PROFILE(SMBcopy);
4137 return(outsize);
4140 /****************************************************************************
4141 reply to a setdir
4142 ****************************************************************************/
4143 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4145 int snum;
4146 int outsize = 0;
4147 BOOL ok = False;
4148 pstring newdir;
4149 START_PROFILE(pathworks_setdir);
4151 snum = SNUM(conn);
4152 if (!CAN_SETDIR(snum)) {
4153 END_PROFILE(pathworks_setdir);
4154 return(ERROR(ERRDOS,ERRnoaccess));
4157 pstrcpy(newdir,smb_buf(inbuf) + 1);
4158 strlower(newdir);
4160 if (strlen(newdir) == 0) {
4161 ok = True;
4162 } else {
4163 ok = vfs_directory_exist(conn,newdir,NULL);
4164 if (ok) {
4165 string_set(&conn->connectpath,newdir);
4169 if (!ok) {
4170 END_PROFILE(pathworks_setdir);
4171 return(ERROR(ERRDOS,ERRbadpath));
4174 outsize = set_message(outbuf,0,0,True);
4175 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4177 DEBUG(3,("setdir %s\n", newdir));
4179 END_PROFILE(pathworks_setdir);
4180 return(outsize);
4183 /****************************************************************************
4184 Get a lock count, dealing with large count requests.
4185 ****************************************************************************/
4187 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4189 SMB_BIG_UINT count = 0;
4191 if(!large_file_format) {
4192 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4193 } else {
4195 #if defined(HAVE_LONGLONG)
4196 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4197 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4198 #else /* HAVE_LONGLONG */
4201 * NT4.x seems to be broken in that it sends large file (64 bit)
4202 * lockingX calls even if the CAP_LARGE_FILES was *not*
4203 * negotiated. For boxes without large unsigned ints truncate the
4204 * lock count by dropping the top 32 bits.
4207 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4208 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4209 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4210 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4211 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4214 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4215 #endif /* HAVE_LONGLONG */
4218 return count;
4221 /****************************************************************************
4222 Get a lock offset, dealing with large offset requests.
4223 ****************************************************************************/
4225 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4227 SMB_BIG_UINT offset = 0;
4229 *err = False;
4231 if(!large_file_format) {
4232 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4233 } else {
4235 #if defined(HAVE_LONGLONG)
4236 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4237 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4238 #else /* HAVE_LONGLONG */
4241 * NT4.x seems to be broken in that it sends large file (64 bit)
4242 * lockingX calls even if the CAP_LARGE_FILES was *not*
4243 * negotiated. For boxes without large unsigned ints mangle the
4244 * lock offset by mapping the top 32 bits onto the lower 32.
4247 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4248 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4249 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4250 uint32 new_low = 0;
4252 if((new_low = map_lock_offset(high, low)) == 0) {
4253 *err = True;
4254 return (SMB_BIG_UINT)-1;
4257 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4258 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4259 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4260 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4263 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4264 #endif /* HAVE_LONGLONG */
4267 return offset;
4270 /****************************************************************************
4271 reply to a lockingX request
4272 ****************************************************************************/
4274 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4276 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4277 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4278 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4279 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4280 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4281 SMB_BIG_UINT count = 0, offset = 0;
4282 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4283 int i;
4284 char *data;
4285 uint32 ecode=0, dummy2;
4286 int eclass=0, dummy1;
4287 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4288 BOOL err;
4289 START_PROFILE(SMBlockingX);
4291 CHECK_FSP(fsp,conn);
4292 CHECK_ERROR(fsp);
4294 data = smb_buf(inbuf);
4296 /* Check if this is an oplock break on a file
4297 we have granted an oplock on.
4299 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4301 /* Client can insist on breaking to none. */
4302 BOOL break_to_none = (oplocklevel == 0);
4304 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4305 fsp->fnum, (unsigned int)oplocklevel ));
4308 * Make sure we have granted an exclusive or batch oplock on this file.
4311 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4313 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4314 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4316 /* if this is a pure oplock break request then don't send a reply */
4317 if (num_locks == 0 && num_ulocks == 0) {
4318 END_PROFILE(SMBlockingX);
4319 return -1;
4320 } else {
4321 END_PROFILE(SMBlockingX);
4322 return ERROR(ERRDOS,ERRlock);
4326 if (remove_oplock(fsp, break_to_none) == False) {
4327 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4328 fsp->fsp_name ));
4331 /* if this is a pure oplock break request then don't send a reply */
4332 if (num_locks == 0 && num_ulocks == 0)
4334 /* Sanity check - ensure a pure oplock break is not a
4335 chained request. */
4336 if(CVAL(inbuf,smb_vwv0) != 0xff)
4337 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4338 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4339 END_PROFILE(SMBlockingX);
4340 return -1;
4345 * We do this check *after* we have checked this is not a oplock break
4346 * response message. JRA.
4349 release_level_2_oplocks_on_change(fsp);
4351 /* Data now points at the beginning of the list
4352 of smb_unlkrng structs */
4353 for(i = 0; i < (int)num_ulocks; i++) {
4354 count = get_lock_count( data, i, large_file_format);
4355 offset = get_lock_offset( data, i, large_file_format, &err);
4358 * There is no error code marked "stupid client bug".... :-).
4360 if(err) {
4361 END_PROFILE(SMBlockingX);
4362 return ERROR(ERRDOS,ERRnoaccess);
4365 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
4366 (double)offset, (double)count, fsp->fsp_name ));
4368 if(!do_unlock(fsp,conn,count,offset, &eclass, &ecode)) {
4369 END_PROFILE(SMBlockingX);
4370 return ERROR(eclass,ecode);
4374 /* Setup the timeout in seconds. */
4375 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4377 /* Now do any requested locks */
4378 data += ((large_file_format ? 20 : 10)*num_ulocks);
4380 /* Data now points at the beginning of the list
4381 of smb_lkrng structs */
4383 for(i = 0; i < (int)num_locks; i++) {
4384 count = get_lock_count( data, i, large_file_format);
4385 offset = get_lock_offset( data, i, large_file_format, &err);
4388 * There is no error code marked "stupid client bug".... :-).
4390 if(err) {
4391 END_PROFILE(SMBlockingX);
4392 return ERROR(ERRDOS,ERRnoaccess);
4395 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
4396 (double)offset, (double)count, fsp->fsp_name ));
4398 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4399 &eclass, &ecode)) {
4400 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4402 * A blocking lock was requested. Package up
4403 * this smb into a queued request and push it
4404 * onto the blocking lock queue.
4406 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4407 END_PROFILE(SMBlockingX);
4408 return -1;
4411 break;
4415 /* If any of the above locks failed, then we must unlock
4416 all of the previous locks (X/Open spec). */
4417 if(i != num_locks && num_locks != 0) {
4419 * Ensure we don't do a remove on the lock that just failed,
4420 * as under POSIX rules, if we have a lock already there, we
4421 * will delete it (and we shouldn't) .....
4423 for(i--; i >= 0; i--) {
4424 count = get_lock_count( data, i, large_file_format);
4425 offset = get_lock_offset( data, i, large_file_format, &err);
4428 * There is no error code marked "stupid client bug".... :-).
4430 if(err) {
4431 END_PROFILE(SMBlockingX);
4432 return ERROR(ERRDOS,ERRnoaccess);
4435 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
4437 END_PROFILE(SMBlockingX);
4438 return ERROR(eclass,ecode);
4441 set_message(outbuf,2,0,True);
4443 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4444 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4446 END_PROFILE(SMBlockingX);
4447 return chain_reply(inbuf,outbuf,length,bufsize);
4451 /****************************************************************************
4452 reply to a SMBreadbmpx (read block multiplex) request
4453 ****************************************************************************/
4454 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4456 ssize_t nread = -1;
4457 ssize_t total_read;
4458 char *data;
4459 SMB_OFF_T startpos;
4460 int outsize;
4461 size_t maxcount;
4462 int max_per_packet;
4463 size_t tcount;
4464 int pad;
4465 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4466 START_PROFILE(SMBreadBmpx);
4468 /* this function doesn't seem to work - disable by default */
4469 if (!lp_readbmpx()) {
4470 END_PROFILE(SMBreadBmpx);
4471 return(ERROR(ERRSRV,ERRuseSTD));
4474 outsize = set_message(outbuf,8,0,True);
4476 CHECK_FSP(fsp,conn);
4477 CHECK_READ(fsp);
4478 CHECK_ERROR(fsp);
4480 startpos = IVAL(inbuf,smb_vwv1);
4481 maxcount = SVAL(inbuf,smb_vwv3);
4483 data = smb_buf(outbuf);
4484 pad = ((long)data)%4;
4485 if (pad) pad = 4 - pad;
4486 data += pad;
4488 max_per_packet = bufsize-(outsize+pad);
4489 tcount = maxcount;
4490 total_read = 0;
4492 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
4493 END_PROFILE(SMBreadBmpx);
4494 return(ERROR(ERRDOS,ERRlock));
4499 size_t N = MIN(max_per_packet,tcount-total_read);
4501 nread = read_file(fsp,data,startpos,N);
4503 if (nread <= 0) nread = 0;
4505 if (nread < (ssize_t)N)
4506 tcount = total_read + nread;
4508 set_message(outbuf,8,nread,False);
4509 SIVAL(outbuf,smb_vwv0,startpos);
4510 SSVAL(outbuf,smb_vwv2,tcount);
4511 SSVAL(outbuf,smb_vwv6,nread);
4512 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4514 send_smb(smbd_server_fd(),outbuf);
4516 total_read += nread;
4517 startpos += nread;
4519 while (total_read < (ssize_t)tcount);
4521 END_PROFILE(SMBreadBmpx);
4522 return(-1);
4525 /****************************************************************************
4526 reply to a SMBwritebmpx (write block multiplex primary) request
4527 ****************************************************************************/
4529 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4531 size_t numtowrite;
4532 ssize_t nwritten = -1;
4533 int outsize = 0;
4534 SMB_OFF_T startpos;
4535 size_t tcount;
4536 BOOL write_through;
4537 int smb_doff;
4538 char *data;
4539 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4540 START_PROFILE(SMBwriteBmpx);
4542 CHECK_FSP(fsp,conn);
4543 CHECK_WRITE(fsp);
4544 CHECK_ERROR(fsp);
4546 tcount = SVAL(inbuf,smb_vwv1);
4547 startpos = IVAL(inbuf,smb_vwv3);
4548 write_through = BITSETW(inbuf+smb_vwv7,0);
4549 numtowrite = SVAL(inbuf,smb_vwv10);
4550 smb_doff = SVAL(inbuf,smb_vwv11);
4552 data = smb_base(inbuf) + smb_doff;
4554 /* If this fails we need to send an SMBwriteC response,
4555 not an SMBwritebmpx - set this up now so we don't forget */
4556 CVAL(outbuf,smb_com) = SMBwritec;
4558 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
4559 END_PROFILE(SMBwriteBmpx);
4560 return(ERROR(ERRDOS,ERRlock));
4563 nwritten = write_file(fsp,data,startpos,numtowrite);
4565 if(lp_syncalways(SNUM(conn)) || write_through)
4566 sync_file(conn,fsp);
4568 if(nwritten < (ssize_t)numtowrite) {
4569 END_PROFILE(SMBwriteBmpx);
4570 return(UNIXERROR(ERRHRD,ERRdiskfull));
4573 /* If the maximum to be written to this file
4574 is greater than what we just wrote then set
4575 up a secondary struct to be attached to this
4576 fd, we will use this to cache error messages etc. */
4577 if((ssize_t)tcount > nwritten)
4579 write_bmpx_struct *wbms;
4580 if(fsp->wbmpx_ptr != NULL)
4581 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4582 else
4583 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4584 if(!wbms)
4586 DEBUG(0,("Out of memory in reply_readmpx\n"));
4587 END_PROFILE(SMBwriteBmpx);
4588 return(ERROR(ERRSRV,ERRnoresource));
4590 wbms->wr_mode = write_through;
4591 wbms->wr_discard = False; /* No errors yet */
4592 wbms->wr_total_written = nwritten;
4593 wbms->wr_errclass = 0;
4594 wbms->wr_error = 0;
4595 fsp->wbmpx_ptr = wbms;
4598 /* We are returning successfully, set the message type back to
4599 SMBwritebmpx */
4600 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4602 outsize = set_message(outbuf,1,0,True);
4604 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4606 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4607 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4609 if (write_through && tcount==nwritten) {
4610 /* we need to send both a primary and a secondary response */
4611 smb_setlen(outbuf,outsize - 4);
4612 send_smb(smbd_server_fd(),outbuf);
4614 /* now the secondary */
4615 outsize = set_message(outbuf,1,0,True);
4616 CVAL(outbuf,smb_com) = SMBwritec;
4617 SSVAL(outbuf,smb_vwv0,nwritten);
4620 END_PROFILE(SMBwriteBmpx);
4621 return(outsize);
4625 /****************************************************************************
4626 reply to a SMBwritebs (write block multiplex secondary) request
4627 ****************************************************************************/
4628 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4630 size_t numtowrite;
4631 ssize_t nwritten = -1;
4632 int outsize = 0;
4633 SMB_OFF_T startpos;
4634 size_t tcount;
4635 BOOL write_through;
4636 int smb_doff;
4637 char *data;
4638 write_bmpx_struct *wbms;
4639 BOOL send_response = False;
4640 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4641 START_PROFILE(SMBwriteBs);
4643 CHECK_FSP(fsp,conn);
4644 CHECK_WRITE(fsp);
4646 tcount = SVAL(inbuf,smb_vwv1);
4647 startpos = IVAL(inbuf,smb_vwv2);
4648 numtowrite = SVAL(inbuf,smb_vwv6);
4649 smb_doff = SVAL(inbuf,smb_vwv7);
4651 data = smb_base(inbuf) + smb_doff;
4653 /* We need to send an SMBwriteC response, not an SMBwritebs */
4654 CVAL(outbuf,smb_com) = SMBwritec;
4656 /* This fd should have an auxiliary struct attached,
4657 check that it does */
4658 wbms = fsp->wbmpx_ptr;
4659 if(!wbms) {
4660 END_PROFILE(SMBwriteBs);
4661 return(-1);
4664 /* If write through is set we can return errors, else we must
4665 cache them */
4666 write_through = wbms->wr_mode;
4668 /* Check for an earlier error */
4669 if(wbms->wr_discard) {
4670 END_PROFILE(SMBwriteBs);
4671 return -1; /* Just discard the packet */
4674 nwritten = write_file(fsp,data,startpos,numtowrite);
4676 if(lp_syncalways(SNUM(conn)) || write_through)
4677 sync_file(conn,fsp);
4679 if (nwritten < (ssize_t)numtowrite)
4681 if(write_through)
4683 /* We are returning an error - we can delete the aux struct */
4684 if (wbms) free((char *)wbms);
4685 fsp->wbmpx_ptr = NULL;
4686 END_PROFILE(SMBwriteBs);
4687 return(ERROR(ERRHRD,ERRdiskfull));
4689 END_PROFILE(SMBwriteBs);
4690 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4693 /* Increment the total written, if this matches tcount
4694 we can discard the auxiliary struct (hurrah !) and return a writeC */
4695 wbms->wr_total_written += nwritten;
4696 if(wbms->wr_total_written >= tcount)
4698 if (write_through)
4700 outsize = set_message(outbuf,1,0,True);
4701 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4702 send_response = True;
4705 free((char *)wbms);
4706 fsp->wbmpx_ptr = NULL;
4709 if(send_response) {
4710 END_PROFILE(SMBwriteBs);
4711 return(outsize);
4714 END_PROFILE(SMBwriteBs);
4715 return(-1);
4719 /****************************************************************************
4720 reply to a SMBsetattrE
4721 ****************************************************************************/
4723 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4725 struct utimbuf unix_times;
4726 int outsize = 0;
4727 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4728 START_PROFILE(SMBsetattrE);
4730 outsize = set_message(outbuf,0,0,True);
4732 CHECK_FSP(fsp,conn);
4733 CHECK_ERROR(fsp);
4735 /* Convert the DOS times into unix times. Ignore create
4736 time as UNIX can't set this.
4738 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4739 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4742 * Patch from Ray Frush <frush@engr.colostate.edu>
4743 * Sometimes times are sent as zero - ignore them.
4746 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4748 /* Ignore request */
4749 if( DEBUGLVL( 3 ) )
4751 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4752 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4754 END_PROFILE(SMBsetattrE);
4755 return(outsize);
4757 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4759 /* set modify time = to access time if modify time was 0 */
4760 unix_times.modtime = unix_times.actime;
4763 /* Set the date on this file */
4764 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4765 END_PROFILE(SMBsetattrE);
4766 return(ERROR(ERRDOS,ERRnoaccess));
4769 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4770 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4772 END_PROFILE(SMBsetattrE);
4773 return(outsize);
4777 /****************************************************************************
4778 reply to a SMBgetattrE
4779 ****************************************************************************/
4781 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4783 SMB_STRUCT_STAT sbuf;
4784 int outsize = 0;
4785 int mode;
4786 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4787 START_PROFILE(SMBgetattrE);
4789 outsize = set_message(outbuf,11,0,True);
4791 CHECK_FSP(fsp,conn);
4792 CHECK_ERROR(fsp);
4794 /* Do an fstat on this file */
4795 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4796 END_PROFILE(SMBgetattrE);
4797 return(UNIXERROR(ERRDOS,ERRnoaccess));
4800 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4802 /* Convert the times into dos times. Set create
4803 date to be last modify date as UNIX doesn't save
4804 this */
4805 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4806 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4807 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4808 if (mode & aDIR)
4810 SIVAL(outbuf,smb_vwv6,0);
4811 SIVAL(outbuf,smb_vwv8,0);
4813 else
4815 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4816 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4818 SSVAL(outbuf,smb_vwv10, mode);
4820 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4822 END_PROFILE(SMBgetattrE);
4823 return(outsize);
4825 #undef OLD_NTDOMAIN