2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
31 extern int DEBUGLEVEL;
34 extern char magic_char;
35 extern BOOL case_sensitive;
36 extern BOOL case_preserve;
37 extern BOOL short_case_preserve;
38 extern userdom_struct current_user_info;
39 extern pstring global_myname;
40 extern fstring global_myworkgroup;
41 extern int global_oplock_break;
42 uint32 global_client_caps = 0;
43 unsigned int smb_echo_count = 0;
45 /****************************************************************************
46 report a possible attack via the password buffer overflow bug
47 ****************************************************************************/
49 static void overflow_attack(int len)
52 dbgtext( "ERROR: Invalid password length %d.\n", len );
53 dbgtext( "Your machine may be under attack by someone " );
54 dbgtext( "attempting to exploit an old bug.\n" );
55 dbgtext( "Attack was from IP = %s.\n", client_addr() );
60 /****************************************************************************
61 reply to an special message
62 ****************************************************************************/
64 int reply_special(char *inbuf,char *outbuf)
67 int msg_type = CVAL(inbuf,0);
68 int msg_flags = CVAL(inbuf,1);
70 extern fstring remote_machine;
71 extern fstring local_machine;
77 memset(outbuf,'\0',smb_size);
82 case 0x81: /* session request */
83 CVAL(outbuf,0) = 0x82;
85 if (name_len(inbuf+4) > 50 ||
86 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
87 DEBUG(0,("Invalid name length in session request\n"));
90 name_extract(inbuf,4,name1);
91 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
92 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
95 fstrcpy(remote_machine,name2);
96 remote_machine[15] = 0;
97 trim_string(remote_machine," "," ");
98 strlower(remote_machine);
99 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
101 fstrcpy(local_machine,name1);
102 len = strlen(local_machine);
104 name_type = local_machine[15];
105 local_machine[15] = 0;
107 trim_string(local_machine," "," ");
108 strlower(local_machine);
109 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
111 DEBUG(2,("netbios connect: local=%s remote=%s\n",
112 local_machine, remote_machine ));
114 if (name_type == 'R') {
115 /* We are being asked for a pathworks session ---
117 CVAL(outbuf, 0) = 0x83;
121 /* only add the client's machine name to the list
122 of possibly valid usernames if we are operating
123 in share mode security */
124 if (lp_security() == SEC_SHARE) {
125 add_session_user(remote_machine);
128 reload_services(True);
132 claim_connection(NULL,"",MAXSTATUS,True);
137 case 0x89: /* session keepalive request
138 (some old clients produce this?) */
139 CVAL(outbuf,0) = 0x85;
143 case 0x82: /* positive session response */
144 case 0x83: /* negative session response */
145 case 0x84: /* retarget session response */
146 DEBUG(0,("Unexpected session response\n"));
149 case 0x85: /* session keepalive */
154 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
155 msg_type, msg_flags));
161 /*******************************************************************
162 work out what error to give to a failed connection
163 ********************************************************************/
165 static int connection_error(char *inbuf,char *outbuf,int ecode)
167 if (ecode == ERRnoipc || ecode == ERRnosuchshare)
168 return(ERROR(ERRDOS,ecode));
170 return(ERROR(ERRSRV,ecode));
174 /****************************************************************************
176 ****************************************************************************/
178 int reply_tcon(connection_struct *conn,
179 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
186 uint16 vuid = SVAL(inbuf,smb_uid);
191 START_PROFILE(SMBtcon);
193 *service = *user = *password = *dev = 0;
195 p = smb_buf(inbuf)+1;
196 p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1;
197 p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
198 p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1;
201 p = strchr_m(service,'%');
207 p = strrchr_m(service,'\\');
209 pstrcpy(service, p+1);
213 * If the vuid is valid, we should be using that....
216 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
217 pstrcpy(user,validated_username(vuid));
221 * Pass the user through the NT -> unix user mapping
225 (void)map_username(user);
228 * Do any UNIX username case mangling.
230 (void)Get_Pwnam( user, True);
233 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
236 END_PROFILE(SMBtcon);
237 return(connection_error(inbuf,outbuf,ecode));
240 outsize = set_message(outbuf,2,0,True);
241 SSVAL(outbuf,smb_vwv0,max_recv);
242 SSVAL(outbuf,smb_vwv1,conn->cnum);
243 SSVAL(outbuf,smb_tid,conn->cnum);
245 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
246 service, user, conn->cnum));
248 END_PROFILE(SMBtcon);
252 /****************************************************************************
253 Reply to a tcon and X.
254 ****************************************************************************/
256 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
263 uint16 vuid = SVAL(inbuf,smb_uid);
264 int passlen = SVAL(inbuf,smb_vwv3);
267 START_PROFILE(SMBtconX);
269 *service = *user = *password = *devicename = 0;
271 /* we might have to close an old one */
272 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
273 close_cnum(conn,vuid);
276 if (passlen > MAX_PASS_LEN) {
277 overflow_attack(passlen);
278 return(ERROR(ERRDOS,ERRbuftoosmall));
281 memcpy(password,smb_buf(inbuf),passlen);
283 p = smb_buf(inbuf) + passlen;
284 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
287 if (strequal(password," "))
289 passlen = strlen(password);
292 q = strchr_m(path+2,'\\');
294 END_PROFILE(SMBtconX);
295 return(ERROR(ERRDOS,ERRnosuchshare));
297 fstrcpy(service,q+1);
298 q = strchr_m(service,'%');
303 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
305 DEBUG(4,("Got device type %s\n",devicename));
308 * If the vuid is valid, we should be using that....
311 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
312 pstrcpy(user,validated_username(vuid));
316 * Pass the user through the NT -> unix user mapping
320 (void)map_username(user);
323 * Do any UNIX username case mangling.
325 (void)Get_Pwnam(user, True);
329 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
332 END_PROFILE(SMBtconX);
333 return(connection_error(inbuf,outbuf,ecode));
336 if (Protocol < PROTOCOL_NT1) {
337 set_message(outbuf,2,0,True);
339 p += srvstr_push(outbuf, p, devicename, -1,
340 STR_TERMINATE|STR_ASCII);
341 set_message_end(outbuf,p);
343 /* NT sets the fstype of IPC$ to the null string */
344 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
346 set_message(outbuf,3,0,True);
349 p += srvstr_push(outbuf, p, devicename, -1,
350 STR_TERMINATE|STR_ASCII);
351 p += srvstr_push(outbuf, p, fsname, -1,
354 set_message_end(outbuf,p);
356 /* what does setting this bit do? It is set by NT4 and
357 may affect the ability to autorun mounted cdroms */
358 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
360 init_dfsroot(conn, inbuf, outbuf);
364 DEBUG(3,("tconX service=%s user=%s\n",
367 /* set the incoming and outgoing tid to the just created one */
368 SSVAL(inbuf,smb_tid,conn->cnum);
369 SSVAL(outbuf,smb_tid,conn->cnum);
371 END_PROFILE(SMBtconX);
372 return chain_reply(inbuf,outbuf,length,bufsize);
376 /****************************************************************************
377 reply to an unknown type
378 ****************************************************************************/
379 int reply_unknown(char *inbuf,char *outbuf)
382 type = CVAL(inbuf,smb_com);
384 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
385 smb_fn_name(type), type, type));
387 return(ERROR(ERRSRV,ERRunknownsmb));
391 /****************************************************************************
393 ****************************************************************************/
394 int reply_ioctl(connection_struct *conn,
395 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
397 uint16 device = SVAL(inbuf,smb_vwv1);
398 uint16 function = SVAL(inbuf,smb_vwv2);
399 uint32 ioctl_code = (device << 16) + function;
400 int replysize, outsize;
402 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
403 START_PROFILE(SMBioctl);
405 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
409 case IOCTL_QUERY_JOB_INFO:
413 END_PROFILE(SMBioctl);
414 return(ERROR(ERRSRV,ERRnosupport));
417 outsize = set_message(outbuf,8,replysize+1,True);
418 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
419 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
420 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
421 p = smb_buf(outbuf) + 1; /* Allow for alignment */
425 case IOCTL_QUERY_JOB_INFO:
426 SSVAL(p,0,fsp->print_jobid); /* Job number */
427 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
428 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
432 END_PROFILE(SMBioctl);
436 /****************************************************************************
437 This function breaks the authentication split. It needs sorting out.
438 I can't see why we can't hadle this INSIDE the check_password, as in then
439 end all it does it spit out an nt_status code.
440 ****************************************************************************/
441 /****************************************************************************
442 always return an error: it's just a matter of which one...
443 ****************************************************************************/
444 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
445 char *smb_passwd, int smb_passlen,
446 char *smb_nt_passwd, int smb_nt_passlen)
448 /* check if trust account exists */
449 SAM_ACCOUNT *sam_trust_acct = NULL;
452 auth_usersupplied_info user_info;
453 auth_serversupplied_info server_info;
454 AUTH_STR domain, smb_username, wksta_name;
456 ZERO_STRUCT(user_info);
457 ZERO_STRUCT(server_info);
459 ZERO_STRUCT(smb_username);
460 ZERO_STRUCT(wksta_name);
462 domain.str = lp_workgroup();
463 domain.len = strlen(domain.str);
465 user_info.requested_domain = domain;
466 user_info.domain = domain;
468 smb_username.str = user;
469 smb_username.len = strlen(smb_username.str);
471 user_info.requested_username = smb_username; /* For the time-being */
472 user_info.smb_username = smb_username;
474 user_info.wksta_name = wksta_name;
476 user_info.lm_resp.buffer = (uint8 *)smb_passwd;
477 user_info.lm_resp.len = smb_passlen;
478 user_info.nt_resp.buffer = (uint8 *)smb_nt_passwd;
479 user_info.nt_resp.len = smb_nt_passlen;
481 if (!last_challenge(user_info.chal)) {
482 DEBUG(1,("smb_password_ok: no challenge done - password failed\n"));
483 return NT_STATUS_LOGON_FAILURE;
486 pdb_init_sam(&sam_trust_acct);
488 if (lp_security() == SEC_USER) {
489 ret = pdb_getsampwnam(sam_trust_acct, user);
491 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
492 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
493 pdb_free_sam(sam_trust_acct);
494 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
498 /* lkclXXXX: workstation entry doesn't exist */
499 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
500 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
501 pdb_free_sam(sam_trust_acct);
502 return(ERROR(0, NT_STATUS_NO_SUCH_USER));
504 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
505 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
506 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
507 pdb_free_sam(sam_trust_acct);
508 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
511 if (!smb_password_ok(sam_trust_acct, &user_info, &server_info)) {
512 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
513 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
514 pdb_free_sam(sam_trust_acct);
515 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
518 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
519 pdb_free_sam(sam_trust_acct);
520 if (acct_ctrl & ACB_DOMTRUST) {
521 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
522 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
523 return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
526 if (acct_ctrl & ACB_SVRTRUST) {
527 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
528 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
529 return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
532 if (acct_ctrl & ACB_WSTRUST) {
533 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
534 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
535 return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
539 /* don't know what to do: indicate logon failure */
540 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
541 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
544 /****************************************************************************
545 Return a bad password error configured for the correct client type.
546 ****************************************************************************/
548 static int bad_password_error(char *inbuf,char *outbuf)
550 enum remote_arch_types ra_type = get_remote_arch();
552 if(((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
553 (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
554 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
555 return(ERROR(0,NT_STATUS_LOGON_FAILURE));
558 return(ERROR(ERRSRV,ERRbadpw));
561 /****************************************************************************
562 reply to a session setup command
563 ****************************************************************************/
565 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
571 int smb_apasslen = 0;
573 int smb_ntpasslen = 0;
574 pstring smb_ntpasswd;
575 BOOL valid_password = False;
580 fstring native_lanman;
582 static BOOL done_sesssetup = False;
583 BOOL doencrypt = SMBENCRYPT();
584 START_PROFILE(SMBsesssetupX);
589 smb_bufsize = SVAL(inbuf,smb_vwv2);
591 if (Protocol < PROTOCOL_NT1) {
592 smb_apasslen = SVAL(inbuf,smb_vwv7);
593 if (smb_apasslen > MAX_PASS_LEN) {
594 overflow_attack(smb_apasslen);
595 return(ERROR(ERRDOS,ERRbuftoosmall));
598 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
599 srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE);
601 if (!doencrypt && (lp_security() != SEC_SERVER)) {
602 smb_apasslen = strlen(smb_apasswd);
605 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
606 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
607 enum remote_arch_types ra_type = get_remote_arch();
608 char *p = smb_buf(inbuf);
610 if(global_client_caps == 0)
611 global_client_caps = IVAL(inbuf,smb_vwv11);
613 /* client_caps is used as final determination if client is NT or Win95.
614 This is needed to return the correct error codes in some
618 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
619 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
620 set_remote_arch( RA_WIN95);
624 if (passlen1 != 24 && passlen2 != 24)
627 if (passlen1 > MAX_PASS_LEN) {
628 overflow_attack(passlen1);
629 return(ERROR(ERRDOS,ERRbuftoosmall));
632 passlen1 = MIN(passlen1, MAX_PASS_LEN);
633 passlen2 = MIN(passlen2, MAX_PASS_LEN);
636 /* both Win95 and WinNT stuff up the password lengths for
637 non-encrypting systems. Uggh.
639 if passlen1==24 its a win95 system, and its setting the
640 password length incorrectly. Luckily it still works with the
641 default code because Win95 will null terminate the password
644 if passlen1>0 and passlen2>0 then maybe its a NT box and its
645 setting passlen2 to some random value which really stuffs
646 things up. we need to fix that one. */
648 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
652 if (lp_restrict_anonymous()) {
653 /* there seems to be no reason behind the differences in MS clients formatting
654 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
655 * in particular seems to have an extra null byte between the username and the
656 * domain, or the password length calculation is wrong, which throws off the
657 * string extraction routines below. This makes the value of domain be the
658 * empty string, which fails the restrict anonymous check further down.
659 * This compensates for that, and allows browsing to work in mixed NT and
660 * win95 environments even when restrict anonymous is true. AAB
662 dump_data(100, p, 0x70);
663 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
664 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
665 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
666 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
667 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
672 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
673 /* Save the lanman2 password and the NT md4 password. */
674 smb_apasslen = passlen1;
675 memcpy(smb_apasswd,p,smb_apasslen);
676 smb_apasswd[smb_apasslen] = 0;
677 smb_ntpasslen = passlen2;
678 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
679 smb_ntpasswd[smb_ntpasslen] = 0;
681 /* we use the first password that they gave */
682 smb_apasslen = passlen1;
683 StrnCpy(smb_apasswd,p,smb_apasslen);
685 /* trim the password */
686 smb_apasslen = strlen(smb_apasswd);
688 /* wfwg sometimes uses a space instead of a null */
689 if (strequal(smb_apasswd," ")) {
695 p += passlen1 + passlen2;
696 p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
699 * Incoming user and domain are in DOS codepage format. Convert
702 p += srvstr_pull(inbuf, domain, p, sizeof(domain),
704 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
706 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
708 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
709 domain,native_os,native_lanman));
712 /* don't allow for weird usernames or domains */
713 alpha_strcpy(user, user, ". _-$", sizeof(user));
714 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
715 if (strstr(user, "..") || strstr(domain,"..")) {
716 return bad_password_error(inbuf, outbuf);
719 DEBUG(3,("sesssetupX:name=[%s]\n",user));
721 /* If name ends in $ then I think it's asking about whether a */
722 /* computer with that name (minus the $) has access. For now */
723 /* say yes to everything ending in $. */
725 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
726 END_PROFILE(SMBsesssetupX);
727 return session_trust_account(conn, inbuf, outbuf, user,
728 smb_apasswd, smb_apasslen,
729 smb_ntpasswd, smb_ntpasslen);
732 if (done_sesssetup && lp_restrict_anonymous()) {
733 /* tests show that even if browsing is done over already validated connections
734 * without a username and password the domain is still provided, which it
735 * wouldn't be if it was a purely anonymous connection. So, in order to
736 * restrict anonymous, we only deny connections that have no session
737 * information. If a domain has been provided, then it's not a purely
738 * anonymous connection. AAB
740 if (!*user && !*smb_apasswd && !*domain) {
741 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
742 END_PROFILE(SMBsesssetupX);
743 return(ERROR(ERRDOS,ERRnoaccess));
747 /* If no username is sent use the guest account */
749 pstrcpy(user,lp_guestaccount(-1));
753 pstrcpy(current_user_info.smb_name,user);
755 reload_services(True);
758 * Save the username before mapping. We will use
759 * the original username sent to us for security=server
760 * and security=domain checking.
763 pstrcpy( orig_user, user);
766 * Always try the "DOMAIN\user" lookup first, as this is the most
767 * specific case. If this fails then try the simple "user" lookup.
768 * But don't do this for guests, as this is always a local user.
774 /* Work out who's who */
776 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
777 domain, lp_winbind_separator(), user);
779 if (sys_getpwnam(dom_user) != NULL) {
780 pstrcpy(user, dom_user);
781 DEBUG(3,("Using unix username %s\n", dom_user));
785 * Pass the user through the NT -> unix user mapping
789 (void)map_username(user);
792 * Do any UNIX username case mangling.
794 smb_getpwnam(user, True);
797 add_session_user(user);
800 valid_password = (pass_check_smb(user, domain,
801 smb_apasswd, smb_apasslen,
802 smb_ntpasswd, smb_ntpasslen) == NT_STATUS_NOPROBLEMO);
804 /* The true branch will be executed if
805 (1) the NT password failed (or was not tried), and
806 (2) LanMan authentication failed (or was disabled)
810 if (lp_security() >= SEC_USER)
812 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
814 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
815 END_PROFILE(SMBsesssetupX);
816 return bad_password_error(inbuf,outbuf);
819 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
821 if (smb_getpwnam(user,True))
823 DEBUG(1,("Rejecting user '%s': bad password\n", user));
824 END_PROFILE(SMBsesssetupX);
825 return bad_password_error(inbuf,outbuf);
830 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
831 * Then always map to guest account - as done below.
835 if (*smb_apasswd || !smb_getpwnam(user,True))
836 pstrcpy(user,lp_guestaccount(-1));
837 DEBUG(3,("Registered username %s for guest access\n",user));
842 if (!smb_getpwnam(user,True)) {
843 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
844 pstrcpy(user,lp_guestaccount(-1));
848 if (!strequal(user,lp_guestaccount(-1)) &&
849 lp_servicenumber(user) < 0)
851 add_home_service(user,get_user_home_dir(user));
855 /* it's ok - setup a reply */
856 if (Protocol < PROTOCOL_NT1) {
857 set_message(outbuf,3,0,True);
860 set_message(outbuf,3,0,True);
862 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
863 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
864 p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_TERMINATE);
865 set_message_end(outbuf,p);
866 /* perhaps grab OS version here?? */
869 /* Set the correct uid in the outgoing and incoming packets
870 We will use this on future requests to determine which
871 user we should become.
874 const struct passwd *pw = smb_getpwnam(user,False);
876 DEBUG(1,("Username %s is invalid on this system\n",user));
877 END_PROFILE(SMBsesssetupX);
878 return bad_password_error(inbuf,outbuf);
885 SSVAL(outbuf,smb_vwv2,1);
887 /* register the name and uid as being validated, so further connections
888 to a uid can get through without a password, on the same VC */
890 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest);
892 if (sess_vuid == -1) {
893 return(ERROR(ERRDOS,ERRnoaccess));
897 SSVAL(outbuf,smb_uid,sess_vuid);
898 SSVAL(inbuf,smb_uid,sess_vuid);
901 max_send = MIN(max_send,smb_bufsize);
903 DEBUG(6,("Client requested max send size of %d\n", max_send));
905 done_sesssetup = True;
907 END_PROFILE(SMBsesssetupX);
908 return chain_reply(inbuf,outbuf,length,bufsize);
911 /****************************************************************************
913 ****************************************************************************/
914 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
920 BOOL bad_path = False;
921 SMB_STRUCT_STAT sbuf;
922 START_PROFILE(SMBchkpth);
924 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
926 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
928 unix_convert(name,conn,0,&bad_path,&sbuf);
930 mode = SVAL(inbuf,smb_vwv0);
932 if (check_name(name,conn)) {
933 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
934 ok = S_ISDIR(sbuf.st_mode);
939 /* We special case this - as when a Windows machine
940 is parsing a path is steps through the components
941 one at a time - if a component fails it expects
942 ERRbadpath, not ERRbadfile.
946 unix_ERR_class = ERRDOS;
947 unix_ERR_code = ERRbadpath;
951 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
952 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
953 (get_remote_arch() == RA_WINNT))
955 unix_ERR_class = ERRDOS;
956 unix_ERR_code = ERRbaddirectory;
960 return(UNIXERROR(ERRDOS,ERRbadpath));
963 outsize = set_message(outbuf,0,0,True);
965 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
967 END_PROFILE(SMBchkpth);
972 /****************************************************************************
974 ****************************************************************************/
975 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
979 SMB_STRUCT_STAT sbuf;
984 BOOL bad_path = False;
986 START_PROFILE(SMBgetatr);
988 p = smb_buf(inbuf) + 1;
989 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
991 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
993 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
994 under WfWg - weird! */
997 mode = aHIDDEN | aDIR;
998 if (!CAN_WRITE(conn)) mode |= aRONLY;
1005 unix_convert(fname,conn,0,&bad_path,&sbuf);
1006 if (check_name(fname,conn))
1008 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1010 mode = dos_mode(conn,fname,&sbuf);
1011 size = sbuf.st_size;
1012 mtime = sbuf.st_mtime;
1018 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1024 if((errno == ENOENT) && bad_path)
1026 unix_ERR_class = ERRDOS;
1027 unix_ERR_code = ERRbadpath;
1030 END_PROFILE(SMBgetatr);
1031 return(UNIXERROR(ERRDOS,ERRbadfile));
1034 outsize = set_message(outbuf,10,0,True);
1036 SSVAL(outbuf,smb_vwv0,mode);
1037 if(lp_dos_filetime_resolution(SNUM(conn)) )
1038 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1040 put_dos_date3(outbuf,smb_vwv1,mtime);
1041 SIVAL(outbuf,smb_vwv3,(uint32)size);
1043 if (Protocol >= PROTOCOL_NT1) {
1044 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1047 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1049 END_PROFILE(SMBgetatr);
1054 /****************************************************************************
1056 ****************************************************************************/
1057 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1064 SMB_STRUCT_STAT sbuf;
1065 BOOL bad_path = False;
1068 START_PROFILE(SMBsetatr);
1070 p = smb_buf(inbuf) + 1;
1071 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1072 unix_convert(fname,conn,0,&bad_path,&sbuf);
1074 mode = SVAL(inbuf,smb_vwv0);
1075 mtime = make_unix_date3(inbuf+smb_vwv1);
1077 if (VALID_STAT_OF_DIR(sbuf))
1079 if (check_name(fname,conn))
1080 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1082 ok = set_filetime(conn,fname,mtime);
1086 if((errno == ENOENT) && bad_path)
1088 unix_ERR_class = ERRDOS;
1089 unix_ERR_code = ERRbadpath;
1092 END_PROFILE(SMBsetatr);
1093 return(UNIXERROR(ERRDOS,ERRnoaccess));
1096 outsize = set_message(outbuf,0,0,True);
1098 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1100 END_PROFILE(SMBsetatr);
1105 /****************************************************************************
1107 ****************************************************************************/
1108 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1111 SMB_BIG_UINT dfree,dsize,bsize;
1112 START_PROFILE(SMBdskattr);
1114 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1116 outsize = set_message(outbuf,5,0,True);
1118 SSVAL(outbuf,smb_vwv0,dsize);
1119 SSVAL(outbuf,smb_vwv1,bsize/512);
1120 SSVAL(outbuf,smb_vwv2,512);
1121 SSVAL(outbuf,smb_vwv3,dfree);
1123 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1125 END_PROFILE(SMBdskattr);
1130 /****************************************************************************
1132 Can be called from SMBsearch, SMBffirst or SMBfunique.
1133 ****************************************************************************/
1134 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1145 BOOL finished = False;
1154 BOOL check_descend = False;
1155 BOOL expect_close = False;
1156 BOOL can_open = True;
1157 BOOL bad_path = False;
1158 START_PROFILE(SMBsearch);
1160 *mask = *directory = *fname = 0;
1162 /* If we were called as SMBffirst then we must expect close. */
1163 if(CVAL(inbuf,smb_com) == SMBffirst)
1164 expect_close = True;
1166 outsize = set_message(outbuf,1,3,True);
1167 maxentries = SVAL(inbuf,smb_vwv0);
1168 dirtype = SVAL(inbuf,smb_vwv1);
1169 p = smb_buf(inbuf) + 1;
1170 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1172 status_len = SVAL(p, 0);
1175 /* dirtype &= ~aDIR; */
1177 if (status_len == 0)
1179 SMB_STRUCT_STAT sbuf;
1182 pstrcpy(directory,path);
1184 unix_convert(directory,conn,0,&bad_path,&sbuf);
1187 if (!check_name(directory,conn))
1190 p = strrchr_m(dir2,'/');
1202 p = strrchr_m(directory,'/');
1208 if (strlen(directory) == 0)
1209 pstrcpy(directory,"./");
1210 memset((char *)status,'\0',21);
1211 CVAL(status,0) = dirtype;
1215 memcpy(status,p,21);
1216 dirtype = CVAL(status,0) & 0x1F;
1217 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1220 string_set(&conn->dirpath,dptr_path(dptr_num));
1221 fstrcpy(mask, dptr_wcard(dptr_num));
1226 p = smb_buf(outbuf) + 3;
1230 if (status_len == 0)
1232 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1237 if((errno == ENOENT) && bad_path)
1239 unix_ERR_class = ERRDOS;
1240 unix_ERR_code = ERRbadpath;
1242 END_PROFILE(SMBsearch);
1243 return (UNIXERROR(ERRDOS,ERRnofids));
1245 END_PROFILE(SMBsearch);
1246 return(ERROR(ERRDOS,ERRnofids));
1248 dptr_set_wcard(dptr_num, strdup(mask));
1251 DEBUG(4,("dptr_num is %d\n",dptr_num));
1255 if ((dirtype&0x1F) == aVOLID)
1257 memcpy(p,status,21);
1258 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1259 dptr_fill(p+12,dptr_num);
1260 if (dptr_zero(p+12) && (status_len==0))
1264 p += DIR_STRUCT_SIZE;
1268 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1269 conn->dirpath,lp_dontdescend(SNUM(conn))));
1270 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1271 check_descend = True;
1273 for (i=numentries;(i<maxentries) && !finished;i++)
1276 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1279 memcpy(p,status,21);
1280 make_dir_struct(p,mask,fname,size,mode,date);
1281 dptr_fill(p+12,dptr_num);
1284 p += DIR_STRUCT_SIZE;
1293 if (numentries == 0 || !ok)
1295 CVAL(outbuf,smb_rcls) = ERRDOS;
1296 SSVAL(outbuf,smb_err,ERRnofiles);
1297 dptr_close(&dptr_num);
1300 /* If we were called as SMBffirst with smb_search_id == NULL
1301 and no entries were found then return error and close dirptr
1304 if(ok && expect_close && numentries == 0 && status_len == 0)
1306 CVAL(outbuf,smb_rcls) = ERRDOS;
1307 SSVAL(outbuf,smb_err,ERRnofiles);
1308 /* Also close the dptr - we know it's gone */
1309 dptr_close(&dptr_num);
1312 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1313 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1314 dptr_close(&dptr_num);
1316 SSVAL(outbuf,smb_vwv0,numentries);
1317 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1318 CVAL(smb_buf(outbuf),0) = 5;
1319 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1321 if (Protocol >= PROTOCOL_NT1) {
1322 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1325 outsize += DIR_STRUCT_SIZE*numentries;
1326 smb_setlen(outbuf,outsize - 4);
1328 if ((! *directory) && dptr_path(dptr_num))
1329 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1331 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1332 smb_fn_name(CVAL(inbuf,smb_com)),
1333 mask, directory, dirtype, numentries, maxentries ) );
1335 END_PROFILE(SMBsearch);
1340 /****************************************************************************
1341 reply to a fclose (stop directory search)
1342 ****************************************************************************/
1343 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1352 START_PROFILE(SMBfclose);
1354 outsize = set_message(outbuf,1,0,True);
1355 p = smb_buf(inbuf) + 1;
1356 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1358 status_len = SVAL(p,0);
1361 if (status_len == 0) {
1362 END_PROFILE(SMBfclose);
1363 return(ERROR(ERRSRV,ERRsrverror));
1366 memcpy(status,p,21);
1368 if(dptr_fetch(status+12,&dptr_num)) {
1369 /* Close the dptr - we know it's gone */
1370 dptr_close(&dptr_num);
1373 SSVAL(outbuf,smb_vwv0,0);
1375 DEBUG(3,("search close\n"));
1377 END_PROFILE(SMBfclose);
1382 /****************************************************************************
1384 ****************************************************************************/
1386 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1396 SMB_STRUCT_STAT sbuf;
1397 BOOL bad_path = False;
1399 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1400 START_PROFILE(SMBopen);
1402 share_mode = SVAL(inbuf,smb_vwv0);
1404 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1406 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1408 unix_convert(fname,conn,0,&bad_path,&sbuf);
1410 unixmode = unix_mode(conn,aARCH,fname);
1412 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1413 unixmode, oplock_request,&rmode,NULL);
1417 if((errno == ENOENT) && bad_path)
1419 unix_ERR_class = ERRDOS;
1420 unix_ERR_code = ERRbadpath;
1422 END_PROFILE(SMBopen);
1423 return(UNIXERROR(ERRDOS,ERRnoaccess));
1426 size = sbuf.st_size;
1427 fmode = dos_mode(conn,fname,&sbuf);
1428 mtime = sbuf.st_mtime;
1431 DEBUG(3,("attempt to open a directory %s\n",fname));
1432 close_file(fsp,False);
1433 END_PROFILE(SMBopen);
1434 return(ERROR(ERRDOS,ERRnoaccess));
1437 outsize = set_message(outbuf,7,0,True);
1438 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1439 SSVAL(outbuf,smb_vwv1,fmode);
1440 if(lp_dos_filetime_resolution(SNUM(conn)) )
1441 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1443 put_dos_date3(outbuf,smb_vwv2,mtime);
1444 SIVAL(outbuf,smb_vwv4,(uint32)size);
1445 SSVAL(outbuf,smb_vwv6,rmode);
1447 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1448 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1451 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1452 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1453 END_PROFILE(SMBopen);
1458 /****************************************************************************
1459 reply to an open and X
1460 ****************************************************************************/
1461 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1464 int smb_mode = SVAL(inbuf,smb_vwv3);
1465 int smb_attr = SVAL(inbuf,smb_vwv5);
1466 /* Breakout the oplock request bits so we can set the
1467 reply bits separately. */
1468 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1469 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1470 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1472 int open_flags = SVAL(inbuf,smb_vwv2);
1473 int smb_sattr = SVAL(inbuf,smb_vwv4);
1474 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1476 int smb_ofun = SVAL(inbuf,smb_vwv8);
1479 int fmode=0,mtime=0,rmode=0;
1480 SMB_STRUCT_STAT sbuf;
1482 BOOL bad_path = False;
1484 START_PROFILE(SMBopenX);
1486 /* If it's an IPC, pass off the pipe handler. */
1488 if (lp_nt_pipe_support()) {
1489 END_PROFILE(SMBopenX);
1490 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1492 END_PROFILE(SMBopenX);
1493 return (ERROR(ERRSRV,ERRaccess));
1497 /* XXXX we need to handle passed times, sattr and flags */
1498 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1500 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1502 unix_convert(fname,conn,0,&bad_path,&sbuf);
1504 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1506 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1507 oplock_request, &rmode,&smb_action);
1511 if((errno == ENOENT) && bad_path)
1513 unix_ERR_class = ERRDOS;
1514 unix_ERR_code = ERRbadpath;
1516 END_PROFILE(SMBopenX);
1517 return(UNIXERROR(ERRDOS,ERRnoaccess));
1520 size = sbuf.st_size;
1521 fmode = dos_mode(conn,fname,&sbuf);
1522 mtime = sbuf.st_mtime;
1524 close_file(fsp,False);
1525 END_PROFILE(SMBopenX);
1526 return(ERROR(ERRDOS,ERRnoaccess));
1529 /* If the caller set the extended oplock request bit
1530 and we granted one (by whatever means) - set the
1531 correct bit for extended oplock reply.
1534 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1535 smb_action |= EXTENDED_OPLOCK_GRANTED;
1538 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1539 smb_action |= EXTENDED_OPLOCK_GRANTED;
1542 /* If the caller set the core oplock request bit
1543 and we granted one (by whatever means) - set the
1544 correct bit for core oplock reply.
1547 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1548 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1551 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1552 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1555 set_message(outbuf,15,0,True);
1556 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1557 SSVAL(outbuf,smb_vwv3,fmode);
1558 if(lp_dos_filetime_resolution(SNUM(conn)) )
1559 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1561 put_dos_date3(outbuf,smb_vwv4,mtime);
1562 SIVAL(outbuf,smb_vwv6,(uint32)size);
1563 SSVAL(outbuf,smb_vwv8,rmode);
1564 SSVAL(outbuf,smb_vwv11,smb_action);
1566 END_PROFILE(SMBopenX);
1567 return chain_reply(inbuf,outbuf,length,bufsize);
1571 /****************************************************************************
1572 reply to a SMBulogoffX
1573 ****************************************************************************/
1574 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1576 uint16 vuid = SVAL(inbuf,smb_uid);
1577 user_struct *vuser = get_valid_user_struct(vuid);
1578 START_PROFILE(SMBulogoffX);
1581 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1584 /* in user level security we are supposed to close any files
1585 open by this user */
1586 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1587 file_close_user(vuid);
1590 invalidate_vuid(vuid);
1592 set_message(outbuf,2,0,True);
1594 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1596 END_PROFILE(SMBulogoffX);
1597 return chain_reply(inbuf,outbuf,length,bufsize);
1601 /****************************************************************************
1602 reply to a mknew or a create
1603 ****************************************************************************/
1604 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1612 BOOL bad_path = False;
1614 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1615 SMB_STRUCT_STAT sbuf;
1616 START_PROFILE(SMBcreate);
1618 com = SVAL(inbuf,smb_com);
1620 createmode = SVAL(inbuf,smb_vwv0);
1621 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1623 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1625 unix_convert(fname,conn,0,&bad_path,&sbuf);
1627 if (createmode & aVOLID) {
1628 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1631 unixmode = unix_mode(conn,createmode,fname);
1635 /* We should fail if file exists. */
1636 ofun = FILE_CREATE_IF_NOT_EXIST;
1640 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1641 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1644 /* Open file in dos compatibility share mode. */
1645 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1646 ofun, unixmode, oplock_request, NULL, NULL);
1650 if((errno == ENOENT) && bad_path)
1652 unix_ERR_class = ERRDOS;
1653 unix_ERR_code = ERRbadpath;
1655 END_PROFILE(SMBcreate);
1656 return(UNIXERROR(ERRDOS,ERRnoaccess));
1659 outsize = set_message(outbuf,1,0,True);
1660 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1662 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1663 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1666 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1667 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1669 DEBUG( 2, ( "new file %s\n", fname ) );
1670 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1671 fname, fsp->fd, createmode, (int)unixmode ) );
1673 END_PROFILE(SMBcreate);
1678 /****************************************************************************
1679 reply to a create temporary file
1680 ****************************************************************************/
1681 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1687 BOOL bad_path = False;
1689 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1691 SMB_STRUCT_STAT sbuf;
1694 START_PROFILE(SMBctemp);
1696 createmode = SVAL(inbuf,smb_vwv0);
1697 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1698 pstrcat(fname,"/TMXXXXXX");
1700 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1702 unix_convert(fname,conn,0,&bad_path,&sbuf);
1704 unixmode = unix_mode(conn,createmode,fname);
1706 tmpfd = smb_mkstemp(fname);
1708 END_PROFILE(SMBctemp);
1709 return(UNIXERROR(ERRDOS,ERRnoaccess));
1712 vfs_stat(conn,fname,&sbuf);
1714 /* Open file in dos compatibility share mode. */
1715 /* We should fail if file does not exist. */
1716 fsp = open_file_shared(conn,fname,&sbuf,
1717 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1718 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1719 unixmode, oplock_request, NULL, NULL);
1721 /* close fd from smb_mkstemp() */
1726 if((errno == ENOENT) && bad_path)
1728 unix_ERR_class = ERRDOS;
1729 unix_ERR_code = ERRbadpath;
1731 END_PROFILE(SMBctemp);
1732 return(UNIXERROR(ERRDOS,ERRnoaccess));
1735 outsize = set_message(outbuf,1,0,True);
1736 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1737 CVAL(smb_buf(outbuf),0) = 4;
1738 p = smb_buf(outbuf) + 1;
1739 p += srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1740 set_message_end(outbuf, p);
1742 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1743 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1746 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1747 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1749 DEBUG( 2, ( "created temp file %s\n", fname ) );
1750 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1751 fname, fsp->fd, createmode, (int)unixmode ) );
1753 END_PROFILE(SMBctemp);
1758 /*******************************************************************
1759 check if a user is allowed to delete a file
1760 ********************************************************************/
1761 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1763 SMB_STRUCT_STAT sbuf;
1766 if (!CAN_WRITE(conn)) return(False);
1768 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
1769 fmode = dos_mode(conn,fname,&sbuf);
1770 if (fmode & aDIR) return(False);
1771 if (!lp_delete_readonly(SNUM(conn))) {
1772 if (fmode & aRONLY) return(False);
1774 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1776 if (!check_file_sharing(conn,fname,False)) return(False);
1780 /****************************************************************************
1781 The guts of the unlink command, split out so it may be called by the NT SMB
1783 ****************************************************************************/
1785 int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
1786 int dirtype, char *name)
1792 int error = ERRnoaccess;
1795 BOOL bad_path = False;
1797 SMB_STRUCT_STAT sbuf;
1799 *directory = *mask = 0;
1801 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1803 p = strrchr_m(name,'/');
1805 pstrcpy(directory,"./");
1809 pstrcpy(directory,name);
1814 * We should only check the mangled cache
1815 * here if unix_convert failed. This means
1816 * that the path in 'mask' doesn't exist
1817 * on the file system and so we need to look
1818 * for a possible mangle. This patch from
1819 * Tine Smukavec <valentin.smukavec@hermes.si>.
1822 if (!rc && is_mangled(mask))
1823 check_mangled_cache( mask );
1825 has_wild = ms_has_wild(mask);
1828 pstrcat(directory,"/");
1829 pstrcat(directory,mask);
1830 if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory))
1833 exists = vfs_file_exist(conn,directory,&sbuf);
1835 void *dirptr = NULL;
1838 if (check_name(directory,conn))
1839 dirptr = OpenDir(conn, directory, True);
1841 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1842 the pattern matches against the long name, otherwise the short name
1843 We don't implement this yet XXXX
1850 if (strequal(mask,"????????.???"))
1853 while ((dname = ReadDirName(dirptr)))
1856 pstrcpy(fname,dname);
1858 if(!mask_match(fname, mask, case_sensitive)) continue;
1860 error = ERRnoaccess;
1861 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1862 if (!can_delete(fname,conn,dirtype)) continue;
1863 if (!vfs_unlink(conn,fname)) count++;
1864 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1872 return(ERROR(ERRDOS,error));
1874 if((errno == ENOENT) && bad_path) {
1875 unix_ERR_class = ERRDOS;
1876 unix_ERR_code = ERRbadpath;
1878 return(UNIXERROR(ERRDOS,error));
1885 /****************************************************************************
1887 ****************************************************************************/
1889 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1894 START_PROFILE(SMBunlink);
1896 dirtype = SVAL(inbuf,smb_vwv0);
1898 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1900 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1902 DEBUG(3,("reply_unlink : %s\n",name));
1904 outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
1908 * Win2k needs a changenotify request response before it will
1909 * update after a rename..
1912 process_pending_change_notify_queue((time_t)0);
1914 outsize = set_message(outbuf,0,0,True);
1917 END_PROFILE(SMBunlink);
1922 /****************************************************************************
1923 reply to a readbraw (core+ protocol)
1924 ****************************************************************************/
1926 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1928 size_t maxcount,mincount;
1931 char *header = outbuf;
1934 START_PROFILE(SMBreadbraw);
1937 * Special check if an oplock break has been issued
1938 * and the readraw request croses on the wire, we must
1939 * return a zero length response here.
1942 if(global_oplock_break)
1944 _smb_setlen(header,0);
1945 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1946 DEBUG(5,("readbraw - oplock break finished\n"));
1947 END_PROFILE(SMBreadbraw);
1951 fsp = file_fsp(inbuf,smb_vwv0);
1953 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1955 * fsp could be NULL here so use the value from the packet. JRA.
1957 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1958 _smb_setlen(header,0);
1959 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1960 END_PROFILE(SMBreadbraw);
1964 CHECK_FSP(fsp,conn);
1966 flush_write_cache(fsp, READRAW_FLUSH);
1968 startpos = IVAL(inbuf,smb_vwv1);
1969 if(CVAL(inbuf,smb_wct) == 10) {
1971 * This is a large offset (64 bit) read.
1973 #ifdef LARGE_SMB_OFF_T
1975 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1977 #else /* !LARGE_SMB_OFF_T */
1980 * Ensure we haven't been sent a >32 bit offset.
1983 if(IVAL(inbuf,smb_vwv8) != 0) {
1984 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1985 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1986 _smb_setlen(header,0);
1987 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1988 END_PROFILE(SMBreadbraw);
1992 #endif /* LARGE_SMB_OFF_T */
1995 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1996 (double)startpos ));
1997 _smb_setlen(header,0);
1998 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1999 END_PROFILE(SMBreadbraw);
2003 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2004 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2006 /* ensure we don't overrun the packet size */
2007 maxcount = MIN(65535,maxcount);
2008 maxcount = MAX(mincount,maxcount);
2010 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False))
2012 SMB_OFF_T size = fsp->size;
2013 SMB_OFF_T sizeneeded = startpos + maxcount;
2015 if (size < sizeneeded)
2018 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2020 if (!fsp->can_write)
2024 nread = MIN(maxcount,(size - startpos));
2027 if (nread < mincount)
2030 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2031 fsp->fnum, (double)startpos,
2032 (int)maxcount, (int)mincount, (int)nread ) );
2036 BOOL seek_fail = False;
2038 _smb_setlen(header,nread);
2040 if ((nread-predict) > 0) {
2041 if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
2042 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2049 ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
2050 (SMB_OFF_T)(nread-predict),header,4+predict,
2055 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2056 fsp->fsp_name,startpos,nread,ret));
2058 #else /* UNSAFE_READRAW */
2059 ret = read_file(fsp,header+4,startpos,nread);
2060 if (ret < mincount) ret = 0;
2062 _smb_setlen(header,ret);
2063 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2064 #endif /* UNSAFE_READRAW */
2066 DEBUG(5,("readbraw finished\n"));
2067 END_PROFILE(SMBreadbraw);
2072 /****************************************************************************
2073 reply to a lockread (core+ protocol)
2074 ****************************************************************************/
2075 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2084 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2085 START_PROFILE(SMBlockread);
2087 CHECK_FSP(fsp,conn);
2091 release_level_2_oplocks_on_change(fsp);
2093 numtoread = SVAL(inbuf,smb_vwv1);
2094 startpos = IVAL(inbuf,smb_vwv2);
2096 outsize = set_message(outbuf,5,3,True);
2097 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2098 data = smb_buf(outbuf) + 3;
2101 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2102 * protocol request that predates the read/write lock concept.
2103 * Thus instead of asking for a read lock here we need to ask
2104 * for a write lock. JRA.
2107 if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2108 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2110 * A blocking lock was requested. Package up
2111 * this smb into a queued request and push it
2112 * onto the blocking lock queue.
2114 if(push_blocking_lock_request(inbuf, length, -1, 0))
2115 END_PROFILE(SMBlockread);
2118 END_PROFILE(SMBlockread);
2119 return (ERROR(eclass,ecode));
2122 nread = read_file(fsp,data,startpos,numtoread);
2125 END_PROFILE(SMBlockread);
2126 return(UNIXERROR(ERRDOS,ERRnoaccess));
2130 SSVAL(outbuf,smb_vwv0,nread);
2131 SSVAL(outbuf,smb_vwv5,nread+3);
2132 SSVAL(smb_buf(outbuf),1,nread);
2134 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2135 fsp->fnum, (int)numtoread, (int)nread ) );
2137 END_PROFILE(SMBlockread);
2142 /****************************************************************************
2144 ****************************************************************************/
2146 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2153 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2154 START_PROFILE(SMBread);
2156 CHECK_FSP(fsp,conn);
2160 numtoread = SVAL(inbuf,smb_vwv1);
2161 startpos = IVAL(inbuf,smb_vwv2);
2163 outsize = set_message(outbuf,5,3,True);
2164 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2165 data = smb_buf(outbuf) + 3;
2167 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2168 END_PROFILE(SMBread);
2169 return(ERROR(ERRDOS,ERRlock));
2173 nread = read_file(fsp,data,startpos,numtoread);
2176 END_PROFILE(SMBread);
2177 return(UNIXERROR(ERRDOS,ERRnoaccess));
2181 SSVAL(outbuf,smb_vwv0,nread);
2182 SSVAL(outbuf,smb_vwv5,nread+3);
2183 CVAL(smb_buf(outbuf),0) = 1;
2184 SSVAL(smb_buf(outbuf),1,nread);
2186 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2187 fsp->fnum, (int)numtoread, (int)nread ) );
2189 END_PROFILE(SMBread);
2194 /****************************************************************************
2195 reply to a read and X
2196 ****************************************************************************/
2197 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2199 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2200 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2201 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2202 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2205 START_PROFILE(SMBreadX);
2207 /* If it's an IPC, pass off the pipe handler. */
2209 END_PROFILE(SMBreadX);
2210 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2213 CHECK_FSP(fsp,conn);
2217 set_message(outbuf,12,0,True);
2218 data = smb_buf(outbuf);
2220 if(CVAL(inbuf,smb_wct) == 12) {
2221 #ifdef LARGE_SMB_OFF_T
2223 * This is a large offset (64 bit) read.
2225 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2227 #else /* !LARGE_SMB_OFF_T */
2230 * Ensure we haven't been sent a >32 bit offset.
2233 if(IVAL(inbuf,smb_vwv10) != 0) {
2234 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2235 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2236 END_PROFILE(SMBreadX);
2237 return(ERROR(ERRDOS,ERRbadaccess));
2240 #endif /* LARGE_SMB_OFF_T */
2244 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2245 END_PROFILE(SMBreadX);
2246 return(ERROR(ERRDOS,ERRlock));
2248 nread = read_file(fsp,data,startpos,smb_maxcnt);
2251 END_PROFILE(SMBreadX);
2252 return(UNIXERROR(ERRDOS,ERRnoaccess));
2255 SSVAL(outbuf,smb_vwv5,nread);
2256 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2257 SSVAL(smb_buf(outbuf),-2,nread);
2259 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2260 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2262 END_PROFILE(SMBreadX);
2263 return chain_reply(inbuf,outbuf,length,bufsize);
2266 /****************************************************************************
2267 reply to a writebraw (core+ or LANMAN1.0 protocol)
2268 ****************************************************************************/
2270 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2273 ssize_t total_written=0;
2274 size_t numtowrite=0;
2279 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2281 START_PROFILE(SMBwritebraw);
2283 CHECK_FSP(fsp,conn);
2287 tcount = IVAL(inbuf,smb_vwv1);
2288 startpos = IVAL(inbuf,smb_vwv3);
2289 write_through = BITSETW(inbuf+smb_vwv7,0);
2291 /* We have to deal with slightly different formats depending
2292 on whether we are using the core+ or lanman1.0 protocol */
2293 if(Protocol <= PROTOCOL_COREPLUS) {
2294 numtowrite = SVAL(smb_buf(inbuf),-2);
2295 data = smb_buf(inbuf);
2297 numtowrite = SVAL(inbuf,smb_vwv10);
2298 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2301 /* force the error type */
2302 CVAL(inbuf,smb_com) = SMBwritec;
2303 CVAL(outbuf,smb_com) = SMBwritec;
2305 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2306 END_PROFILE(SMBwritebraw);
2307 return(ERROR(ERRDOS,ERRlock));
2311 nwritten = write_file(fsp,data,startpos,numtowrite);
2313 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2314 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2316 if (nwritten < numtowrite) {
2317 END_PROFILE(SMBwritebraw);
2318 return(UNIXERROR(ERRHRD,ERRdiskfull));
2321 total_written = nwritten;
2323 /* Return a message to the redirector to tell it
2324 to send more bytes */
2325 CVAL(outbuf,smb_com) = SMBwritebraw;
2326 SSVALS(outbuf,smb_vwv0,-1);
2327 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2328 if (!send_smb(smbd_server_fd(),outbuf))
2329 exit_server("reply_writebraw: send_smb failed.\n");
2331 /* Now read the raw data into the buffer and write it */
2332 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2333 exit_server("secondary writebraw failed");
2336 /* Even though this is not an smb message, smb_len
2337 returns the generic length of an smb message */
2338 numtowrite = smb_len(inbuf);
2340 if (tcount > nwritten+numtowrite) {
2341 DEBUG(3,("Client overestimated the write %d %d %d\n",
2342 (int)tcount,(int)nwritten,(int)numtowrite));
2345 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2346 (SMB_OFF_T)numtowrite,NULL,0,
2348 total_written += nwritten;
2350 /* Set up outbuf to return the correct return */
2351 outsize = set_message(outbuf,1,0,True);
2352 CVAL(outbuf,smb_com) = SMBwritec;
2353 SSVAL(outbuf,smb_vwv0,total_written);
2355 if (nwritten < (ssize_t)numtowrite) {
2356 CVAL(outbuf,smb_rcls) = ERRHRD;
2357 SSVAL(outbuf,smb_err,ERRdiskfull);
2360 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2361 lp_strict_sync(SNUM(conn)))
2362 sync_file(conn,fsp);
2364 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2365 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2367 /* we won't return a status if write through is not selected - this
2368 follows what WfWg does */
2369 END_PROFILE(SMBwritebraw);
2370 if (!write_through && total_written==tcount) {
2372 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2373 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2375 if (!send_keepalive(smbd_server_fd()))
2376 exit_server("reply_writebraw: send of keepalive failed");
2383 /****************************************************************************
2384 reply to a writeunlock (core+)
2385 ****************************************************************************/
2387 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2389 ssize_t nwritten = -1;
2395 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2397 START_PROFILE(SMBwriteunlock);
2399 CHECK_FSP(fsp,conn);
2403 numtowrite = SVAL(inbuf,smb_vwv1);
2404 startpos = IVAL(inbuf,smb_vwv2);
2405 data = smb_buf(inbuf) + 3;
2407 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2408 END_PROFILE(SMBwriteunlock);
2409 return(ERROR(ERRDOS,ERRlock));
2412 /* The special X/Open SMB protocol handling of
2413 zero length writes is *NOT* done for
2418 nwritten = write_file(fsp,data,startpos,numtowrite);
2420 if (lp_syncalways(SNUM(conn)))
2421 sync_file(conn,fsp);
2423 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2424 END_PROFILE(SMBwriteunlock);
2425 return(UNIXERROR(ERRDOS,ERRnoaccess));
2428 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) {
2429 END_PROFILE(SMBwriteunlock);
2430 return(ERROR(eclass,ecode));
2433 outsize = set_message(outbuf,1,0,True);
2435 SSVAL(outbuf,smb_vwv0,nwritten);
2437 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2438 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2440 END_PROFILE(SMBwriteunlock);
2444 /****************************************************************************
2445 Return correct error for space allocation fail.
2446 ****************************************************************************/
2448 int allocate_space_error(char *inbuf,char *outbuf, int errno_val)
2451 if (!(global_client_caps & CAP_STATUS32))
2452 return (UNIXERROR(ERRHRD,ERRdiskfull));
2454 /* Use more specific WNT/W2K error codes. */
2456 if (errno_val == ENOSPC || errno_val == EDQUOT) {
2458 if (errno_val == ENOSPC) {
2460 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
2461 return(ERROR(0,NT_STATUS_DISK_FULL));
2464 return (UNIXERROR(ERRHRD,ERRdiskfull));
2467 /****************************************************************************
2469 ****************************************************************************/
2471 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2474 ssize_t nwritten = -1;
2477 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2479 START_PROFILE(SMBwrite);
2481 /* If it's an IPC, pass off the pipe handler. */
2483 END_PROFILE(SMBwrite);
2484 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2487 CHECK_FSP(fsp,conn);
2491 numtowrite = SVAL(inbuf,smb_vwv1);
2492 startpos = IVAL(inbuf,smb_vwv2);
2493 data = smb_buf(inbuf) + 3;
2495 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2496 END_PROFILE(SMBwrite);
2497 return(ERROR(ERRDOS,ERRlock));
2500 /* X/Open SMB protocol says that if smb_vwv1 is
2501 zero then the file size should be extended or
2502 truncated to the size given in smb_vwv[2-3] */
2503 if(numtowrite == 0) {
2504 /* This is actually an allocate call, not set EOF. JRA */
2505 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2507 int ret = allocate_space_error(inbuf, outbuf, errno);
2508 END_PROFILE(SMBwrite);
2512 nwritten = write_file(fsp,data,startpos,numtowrite);
2514 if (lp_syncalways(SNUM(conn)))
2515 sync_file(conn,fsp);
2517 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2518 END_PROFILE(SMBwrite);
2519 return(UNIXERROR(ERRDOS,ERRnoaccess));
2522 outsize = set_message(outbuf,1,0,True);
2524 SSVAL(outbuf,smb_vwv0,nwritten);
2526 if (nwritten < (ssize_t)numtowrite) {
2527 CVAL(outbuf,smb_rcls) = ERRHRD;
2528 SSVAL(outbuf,smb_err,ERRdiskfull);
2531 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2532 fsp->fnum, (int)numtowrite, (int)nwritten));
2534 END_PROFILE(SMBwrite);
2539 /****************************************************************************
2540 reply to a write and X
2541 ****************************************************************************/
2542 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2544 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2545 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2546 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2547 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2548 ssize_t nwritten = -1;
2549 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2550 unsigned int smblen = smb_len(inbuf);
2552 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2553 START_PROFILE(SMBwriteX);
2555 /* If it's an IPC, pass off the pipe handler. */
2557 END_PROFILE(SMBwriteX);
2558 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2561 CHECK_FSP(fsp,conn);
2565 /* Deal with possible LARGE_WRITEX */
2567 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2569 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2570 END_PROFILE(SMBwriteX);
2571 return(ERROR(ERRDOS,ERRbadmem));
2574 data = smb_base(inbuf) + smb_doff;
2576 if(CVAL(inbuf,smb_wct) == 14) {
2577 #ifdef LARGE_SMB_OFF_T
2579 * This is a large offset (64 bit) write.
2581 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2583 #else /* !LARGE_SMB_OFF_T */
2586 * Ensure we haven't been sent a >32 bit offset.
2589 if(IVAL(inbuf,smb_vwv12) != 0) {
2590 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2591 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2592 END_PROFILE(SMBwriteX);
2593 return(ERROR(ERRDOS,ERRbadaccess));
2596 #endif /* LARGE_SMB_OFF_T */
2599 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2600 END_PROFILE(SMBwriteX);
2601 return(ERROR(ERRDOS,ERRlock));
2604 /* X/Open SMB protocol says that, unlike SMBwrite
2605 if the length is zero then NO truncation is
2606 done, just a write of zero. To truncate a file,
2611 nwritten = write_file(fsp,data,startpos,numtowrite);
2613 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2614 END_PROFILE(SMBwriteX);
2615 return(UNIXERROR(ERRDOS,ERRnoaccess));
2618 set_message(outbuf,6,0,True);
2620 SSVAL(outbuf,smb_vwv2,nwritten);
2622 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2624 if (nwritten < (ssize_t)numtowrite) {
2625 CVAL(outbuf,smb_rcls) = ERRHRD;
2626 SSVAL(outbuf,smb_err,ERRdiskfull);
2629 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2630 fsp->fnum, (int)numtowrite, (int)nwritten));
2632 if (lp_syncalways(SNUM(conn)) || write_through)
2633 sync_file(conn,fsp);
2635 END_PROFILE(SMBwriteX);
2636 return chain_reply(inbuf,outbuf,length,bufsize);
2640 /****************************************************************************
2642 ****************************************************************************/
2644 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2650 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2651 START_PROFILE(SMBlseek);
2653 CHECK_FSP(fsp,conn);
2656 flush_write_cache(fsp, SEEK_FLUSH);
2658 mode = SVAL(inbuf,smb_vwv1) & 3;
2659 startpos = IVALS(inbuf,smb_vwv2);
2662 case 0: umode = SEEK_SET; break;
2663 case 1: umode = SEEK_CUR; break;
2664 case 2: umode = SEEK_END; break;
2666 umode = SEEK_SET; break;
2669 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2671 * Check for the special case where a seek before the start
2672 * of the file sets the offset to zero. Added in the CIFS spec,
2676 if(errno == EINVAL) {
2677 SMB_OFF_T current_pos = startpos;
2679 if(umode == SEEK_CUR) {
2681 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2682 END_PROFILE(SMBlseek);
2683 return(UNIXERROR(ERRDOS,ERRnoaccess));
2686 current_pos += startpos;
2688 } else if (umode == SEEK_END) {
2690 SMB_STRUCT_STAT sbuf;
2692 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2693 END_PROFILE(SMBlseek);
2694 return(UNIXERROR(ERRDOS,ERRnoaccess));
2697 current_pos += sbuf.st_size;
2701 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2705 END_PROFILE(SMBlseek);
2706 return(UNIXERROR(ERRDOS,ERRnoaccess));
2712 outsize = set_message(outbuf,2,0,True);
2713 SIVAL(outbuf,smb_vwv0,res);
2715 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2716 fsp->fnum, (double)startpos, (double)res, mode));
2718 END_PROFILE(SMBlseek);
2722 /****************************************************************************
2724 ****************************************************************************/
2726 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2728 int outsize = set_message(outbuf,0,0,True);
2729 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2730 START_PROFILE(SMBflush);
2733 CHECK_FSP(fsp,conn);
2738 file_sync_all(conn);
2740 sync_file(conn,fsp);
2743 DEBUG(3,("flush\n"));
2744 END_PROFILE(SMBflush);
2749 /****************************************************************************
2751 ****************************************************************************/
2752 int reply_exit(connection_struct *conn,
2753 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2756 START_PROFILE(SMBexit);
2757 outsize = set_message(outbuf,0,0,True);
2759 DEBUG(3,("exit\n"));
2761 END_PROFILE(SMBexit);
2766 /****************************************************************************
2767 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2768 ****************************************************************************/
2769 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2774 int32 eclass = 0, err = 0;
2775 files_struct *fsp = NULL;
2776 START_PROFILE(SMBclose);
2778 outsize = set_message(outbuf,0,0,True);
2780 /* If it's an IPC, pass off to the pipe handler. */
2782 END_PROFILE(SMBclose);
2783 return reply_pipe_close(conn, inbuf,outbuf);
2786 fsp = file_fsp(inbuf,smb_vwv0);
2789 * We can only use CHECK_FSP if we know it's not a directory.
2792 if(!fsp || (fsp->conn != conn)) {
2793 END_PROFILE(SMBclose);
2794 return(ERROR(ERRDOS,ERRbadfid));
2797 if(HAS_CACHED_ERROR(fsp)) {
2798 eclass = fsp->wbmpx_ptr->wr_errclass;
2799 err = fsp->wbmpx_ptr->wr_error;
2802 if(fsp->is_directory || fsp->stat_open) {
2804 * Special case - close NT SMB directory or stat file
2807 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2808 close_file(fsp,True);
2811 * Close ordinary file.
2816 * If there was a modify time outstanding,
2817 * try and set it here.
2819 if(fsp->pending_modtime)
2820 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2823 * Now take care of any time sent in the close.
2825 mtime = make_unix_date3(inbuf+smb_vwv1);
2827 /* try and set the date */
2828 set_filetime(conn, fsp->fsp_name,mtime);
2830 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2832 conn->num_files_open));
2835 * close_file() returns the unix errno if an error
2836 * was detected on close - normally this is due to
2837 * a disk full error. If not then it was probably an I/O error.
2840 if((close_err = close_file(fsp,True)) != 0) {
2842 END_PROFILE(SMBclose);
2843 return (UNIXERROR(ERRHRD,ERRgeneral));
2847 /* We have a cached error */
2849 END_PROFILE(SMBclose);
2850 return(ERROR(eclass,err));
2853 END_PROFILE(SMBclose);
2858 /****************************************************************************
2859 reply to a writeclose (Core+ protocol)
2860 ****************************************************************************/
2862 int reply_writeclose(connection_struct *conn,
2863 char *inbuf,char *outbuf, int size, int dum_buffsize)
2866 ssize_t nwritten = -1;
2872 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2873 START_PROFILE(SMBwriteclose);
2875 CHECK_FSP(fsp,conn);
2879 numtowrite = SVAL(inbuf,smb_vwv1);
2880 startpos = IVAL(inbuf,smb_vwv2);
2881 mtime = make_unix_date3(inbuf+smb_vwv4);
2882 data = smb_buf(inbuf) + 1;
2884 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2885 END_PROFILE(SMBwriteclose);
2886 return(ERROR(ERRDOS,ERRlock));
2889 nwritten = write_file(fsp,data,startpos,numtowrite);
2891 set_filetime(conn, fsp->fsp_name,mtime);
2893 close_err = close_file(fsp,True);
2895 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2896 fsp->fnum, (int)numtowrite, (int)nwritten,
2897 conn->num_files_open));
2899 if (nwritten <= 0) {
2900 END_PROFILE(SMBwriteclose);
2901 return(UNIXERROR(ERRDOS,ERRnoaccess));
2904 if(close_err != 0) {
2906 END_PROFILE(SMBwriteclose);
2907 return(UNIXERROR(ERRHRD,ERRgeneral));
2910 outsize = set_message(outbuf,1,0,True);
2912 SSVAL(outbuf,smb_vwv0,nwritten);
2913 END_PROFILE(SMBwriteclose);
2918 /****************************************************************************
2920 ****************************************************************************/
2921 int reply_lock(connection_struct *conn,
2922 char *inbuf,char *outbuf, int length, int dum_buffsize)
2924 int outsize = set_message(outbuf,0,0,True);
2925 SMB_BIG_UINT count,offset;
2928 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2929 START_PROFILE(SMBlock);
2931 CHECK_FSP(fsp,conn);
2934 release_level_2_oplocks_on_change(fsp);
2936 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2937 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2939 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2940 fsp->fd, fsp->fnum, (double)offset, (double)count));
2942 if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &eclass, &ecode)) {
2943 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2945 * A blocking lock was requested. Package up
2946 * this smb into a queued request and push it
2947 * onto the blocking lock queue.
2949 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2950 END_PROFILE(SMBlock);
2954 END_PROFILE(SMBlock);
2955 return (ERROR(eclass,ecode));
2958 END_PROFILE(SMBlock);
2963 /****************************************************************************
2965 ****************************************************************************/
2966 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2968 int outsize = set_message(outbuf,0,0,True);
2969 SMB_BIG_UINT count,offset;
2972 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2973 START_PROFILE(SMBunlock);
2975 CHECK_FSP(fsp,conn);
2978 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2979 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2981 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, &eclass, &ecode)) {
2982 END_PROFILE(SMBunlock);
2983 return (ERROR(eclass,ecode));
2986 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2987 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2989 END_PROFILE(SMBunlock);
2994 /****************************************************************************
2996 ****************************************************************************/
2997 int reply_tdis(connection_struct *conn,
2998 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3000 int outsize = set_message(outbuf,0,0,True);
3002 START_PROFILE(SMBtdis);
3004 vuid = SVAL(inbuf,smb_uid);
3007 DEBUG(4,("Invalid connection in tdis\n"));
3008 END_PROFILE(SMBtdis);
3009 return(ERROR(ERRSRV,ERRinvnid));
3014 close_cnum(conn,vuid);
3016 END_PROFILE(SMBtdis);
3022 /****************************************************************************
3024 ****************************************************************************/
3025 int reply_echo(connection_struct *conn,
3026 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3028 int smb_reverb = SVAL(inbuf,smb_vwv0);
3030 unsigned int data_len = smb_buflen(inbuf);
3031 int outsize = set_message(outbuf,1,data_len,True);
3032 START_PROFILE(SMBecho);
3034 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3036 /* copy any incoming data back out */
3038 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3040 if (smb_reverb > 100) {
3041 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3045 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3046 SSVAL(outbuf,smb_vwv0,seq_num);
3048 smb_setlen(outbuf,outsize - 4);
3050 if (!send_smb(smbd_server_fd(),outbuf))
3051 exit_server("reply_echo: send_smb failed.\n");
3054 DEBUG(3,("echo %d times\n", smb_reverb));
3058 END_PROFILE(SMBecho);
3063 /****************************************************************************
3064 reply to a printopen
3065 ****************************************************************************/
3066 int reply_printopen(connection_struct *conn,
3067 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3071 START_PROFILE(SMBsplopen);
3073 if (!CAN_PRINT(conn)) {
3074 END_PROFILE(SMBsplopen);
3075 return(ERROR(ERRDOS,ERRnoaccess));
3078 /* Open for exclusive use, write only. */
3079 fsp = print_fsp_open(conn);
3082 END_PROFILE(SMBsplopen);
3083 return(UNIXERROR(ERRDOS,ERRnoaccess));
3086 outsize = set_message(outbuf,1,0,True);
3087 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3089 DEBUG(3,("openprint fd=%d fnum=%d\n",
3090 fsp->fd, fsp->fnum));
3092 END_PROFILE(SMBsplopen);
3097 /****************************************************************************
3098 reply to a printclose
3099 ****************************************************************************/
3100 int reply_printclose(connection_struct *conn,
3101 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3103 int outsize = set_message(outbuf,0,0,True);
3104 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3106 START_PROFILE(SMBsplclose);
3108 CHECK_FSP(fsp,conn);
3111 if (!CAN_PRINT(conn)) {
3112 END_PROFILE(SMBsplclose);
3113 return(ERROR(ERRDOS,ERRnoaccess));
3116 DEBUG(3,("printclose fd=%d fnum=%d\n",
3117 fsp->fd,fsp->fnum));
3119 close_err = close_file(fsp,True);
3121 if(close_err != 0) {
3123 END_PROFILE(SMBsplclose);
3124 return(UNIXERROR(ERRHRD,ERRgeneral));
3127 END_PROFILE(SMBsplclose);
3132 /****************************************************************************
3133 reply to a printqueue
3134 ****************************************************************************/
3135 int reply_printqueue(connection_struct *conn,
3136 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3138 int outsize = set_message(outbuf,2,3,True);
3139 int max_count = SVAL(inbuf,smb_vwv0);
3140 int start_index = SVAL(inbuf,smb_vwv1);
3141 START_PROFILE(SMBsplretq);
3143 /* we used to allow the client to get the cnum wrong, but that
3144 is really quite gross and only worked when there was only
3145 one printer - I think we should now only accept it if they
3146 get it right (tridge) */
3147 if (!CAN_PRINT(conn)) {
3148 END_PROFILE(SMBsplretq);
3149 return(ERROR(ERRDOS,ERRnoaccess));
3152 SSVAL(outbuf,smb_vwv0,0);
3153 SSVAL(outbuf,smb_vwv1,0);
3154 CVAL(smb_buf(outbuf),0) = 1;
3155 SSVAL(smb_buf(outbuf),1,0);
3157 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3158 start_index, max_count));
3161 print_queue_struct *queue = NULL;
3162 char *p = smb_buf(outbuf) + 3;
3163 int count = print_queue_status(SNUM(conn), &queue,NULL);
3164 int num_to_get = ABS(max_count);
3165 int first = (max_count>0?start_index:start_index+max_count+1);
3171 num_to_get = MIN(num_to_get,count-first);
3174 for (i=first;i<first+num_to_get;i++) {
3175 put_dos_date2(p,0,queue[i].time);
3176 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3177 SSVAL(p,5, queue[i].job);
3178 SIVAL(p,7,queue[i].size);
3180 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII);
3185 outsize = set_message(outbuf,2,28*count+3,False);
3186 SSVAL(outbuf,smb_vwv0,count);
3187 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3188 CVAL(smb_buf(outbuf),0) = 1;
3189 SSVAL(smb_buf(outbuf),1,28*count);
3192 if (queue) free(queue);
3194 DEBUG(3,("%d entries returned in queue\n",count));
3197 END_PROFILE(SMBsplretq);
3202 /****************************************************************************
3203 reply to a printwrite
3204 ****************************************************************************/
3205 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3208 int outsize = set_message(outbuf,0,0,True);
3210 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3211 START_PROFILE(SMBsplwr);
3213 if (!CAN_PRINT(conn)) {
3214 END_PROFILE(SMBsplwr);
3215 return(ERROR(ERRDOS,ERRnoaccess));
3218 CHECK_FSP(fsp,conn);
3222 numtowrite = SVAL(smb_buf(inbuf),1);
3223 data = smb_buf(inbuf) + 3;
3225 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3226 END_PROFILE(SMBsplwr);
3227 return(UNIXERROR(ERRDOS,ERRnoaccess));
3230 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3232 END_PROFILE(SMBsplwr);
3237 /****************************************************************************
3238 The guts of the mkdir command, split out so it may be called by the NT SMB
3240 ****************************************************************************/
3241 int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
3243 BOOL bad_path = False;
3244 SMB_STRUCT_STAT sbuf;
3247 unix_convert(directory,conn,0,&bad_path,&sbuf);
3249 if (check_name(directory, conn))
3250 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3254 if((errno == ENOENT) && bad_path)
3256 unix_ERR_class = ERRDOS;
3257 unix_ERR_code = ERRbadpath;
3259 return(UNIXERROR(ERRDOS,ERRnoaccess));
3265 /****************************************************************************
3267 ****************************************************************************/
3268 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3272 START_PROFILE(SMBmkdir);
3274 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3276 outsize=mkdir_internal(conn, inbuf, outbuf, directory);
3278 outsize = set_message(outbuf,0,0,True);
3280 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3282 END_PROFILE(SMBmkdir);
3286 /****************************************************************************
3287 Static function used by reply_rmdir to delete an entire directory
3289 ****************************************************************************/
3291 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3295 void *dirptr = OpenDir(NULL, directory, False);
3300 while((dname = ReadDirName(dirptr)))
3305 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3308 /* Construct the full name. */
3309 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3315 pstrcpy(fullname, directory);
3316 pstrcat(fullname, "/");
3317 pstrcat(fullname, dname);
3319 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3325 if(st.st_mode & S_IFDIR)
3327 if(recursive_rmdir(conn, fullname)!=0)
3332 if(vfs_rmdir(conn,fullname) != 0)
3338 else if(vfs_unlink(conn,fullname) != 0)
3348 /****************************************************************************
3349 The internals of the rmdir code - called elsewhere.
3350 ****************************************************************************/
3352 BOOL rmdir_internals(connection_struct *conn, char *directory)
3356 ok = (vfs_rmdir(conn,directory) == 0);
3357 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3360 * Check to see if the only thing in this directory are
3361 * vetoed files/directories. If so then delete them and
3362 * retry. If we fail to delete any of them (and we *don't*
3363 * do a recursive delete) then fail the rmdir.
3365 BOOL all_veto_files = True;
3367 void *dirptr = OpenDir(conn, directory, False);
3371 int dirpos = TellDir(dirptr);
3372 while ((dname = ReadDirName(dirptr)))
3374 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3376 if(!IS_VETO_PATH(conn, dname))
3378 all_veto_files = False;
3384 SeekDir(dirptr,dirpos);
3385 while ((dname = ReadDirName(dirptr)))
3390 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3393 /* Construct the full name. */
3394 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3399 pstrcpy(fullname, directory);
3400 pstrcat(fullname, "/");
3401 pstrcat(fullname, dname);
3403 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3405 if(st.st_mode & S_IFDIR)
3407 if(lp_recursive_veto_delete(SNUM(conn)))
3409 if(recursive_rmdir(conn, fullname) != 0)
3412 if(vfs_rmdir(conn,fullname) != 0)
3415 else if(vfs_unlink(conn,fullname) != 0)
3419 /* Retry the rmdir */
3420 ok = (vfs_rmdir(conn,directory) == 0);
3430 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3431 directory,strerror(errno)));
3436 /****************************************************************************
3438 ****************************************************************************/
3440 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3445 BOOL bad_path = False;
3446 SMB_STRUCT_STAT sbuf;
3447 START_PROFILE(SMBrmdir);
3449 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3451 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3453 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3455 if (check_name(directory,conn))
3457 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3458 ok = rmdir_internals(conn, directory);
3463 if((errno == ENOENT) && bad_path)
3465 unix_ERR_class = ERRDOS;
3466 unix_ERR_code = ERRbadpath;
3468 END_PROFILE(SMBrmdir);
3469 return(UNIXERROR(ERRDOS,ERRbadpath));
3472 outsize = set_message(outbuf,0,0,True);
3474 DEBUG( 3, ( "rmdir %s\n", directory ) );
3476 END_PROFILE(SMBrmdir);
3481 /*******************************************************************
3482 resolve wildcards in a filename rename
3483 ********************************************************************/
3484 static BOOL resolve_wildcards(char *name1,char *name2)
3486 fstring root1,root2;
3490 name1 = strrchr_m(name1,'/');
3491 name2 = strrchr_m(name2,'/');
3493 if (!name1 || !name2) return(False);
3495 fstrcpy(root1,name1);
3496 fstrcpy(root2,name2);
3497 p = strrchr_m(root1,'.');
3504 p = strrchr_m(root2,'.');
3536 pstrcpy(name2,root2);
3539 pstrcat(name2,ext2);
3545 /*******************************************************************
3546 check if a user is allowed to rename a file
3547 ********************************************************************/
3548 static BOOL can_rename(char *fname,connection_struct *conn)
3550 SMB_STRUCT_STAT sbuf;
3552 if (!CAN_WRITE(conn)) return(False);
3554 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
3555 if (!check_file_sharing(conn,fname,True)) return(False);
3559 /****************************************************************************
3560 The guts of the rename command, split out so it may be called by the NT SMB
3562 ****************************************************************************/
3563 int rename_internals(connection_struct *conn,
3564 char *inbuf, char *outbuf, char *name,
3565 char *newname, BOOL replace_if_exists)
3569 pstring newname_last_component;
3572 BOOL bad_path1 = False;
3573 BOOL bad_path2 = False;
3575 int error = ERRnoaccess;
3578 SMB_STRUCT_STAT sbuf1, sbuf2;
3580 *directory = *mask = 0;
3582 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3583 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3586 * Split the old name into directory and last component
3587 * strings. Note that unix_convert may have stripped off a
3588 * leading ./ from both name and newname if the rename is
3589 * at the root of the share. We need to make sure either both
3590 * name and newname contain a / character or neither of them do
3591 * as this is checked in resolve_wildcards().
3594 p = strrchr_m(name,'/');
3596 pstrcpy(directory,".");
3600 pstrcpy(directory,name);
3602 *p = '/'; /* Replace needed for exceptional test below. */
3606 * We should only check the mangled cache
3607 * here if unix_convert failed. This means
3608 * that the path in 'mask' doesn't exist
3609 * on the file system and so we need to look
3610 * for a possible mangle. This patch from
3611 * Tine Smukavec <valentin.smukavec@hermes.si>.
3614 if (!rc && is_mangled(mask))
3615 check_mangled_cache( mask );
3617 has_wild = ms_has_wild(mask);
3621 * No wildcards - just process the one file.
3623 BOOL is_short_name = is_8_3(name, True);
3625 /* Add a terminating '/' to the directory name. */
3626 pstrcat(directory,"/");
3627 pstrcat(directory,mask);
3629 /* Ensure newname contains a '/' also */
3630 if(strrchr_m(newname,'/') == 0) {
3633 pstrcpy(tmpstr, "./");
3634 pstrcat(tmpstr, newname);
3635 pstrcpy(newname, tmpstr);
3638 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",
3639 case_sensitive, case_preserve, short_case_preserve, directory,
3640 newname, newname_last_component, is_short_name));
3643 * Check for special case with case preserving and not
3644 * case sensitive, if directory and newname are identical,
3645 * and the old last component differs from the original
3646 * last component only by case, then we should allow
3647 * the rename (user is trying to change the case of the
3650 if((case_sensitive == False) &&
3651 (((case_preserve == True) &&
3652 (is_short_name == False)) ||
3653 ((short_case_preserve == True) &&
3654 (is_short_name == True))) &&
3655 strcsequal(directory, newname)) {
3656 pstring newname_modified_last_component;
3659 * Get the last component of the modified name.
3660 * Note that we guarantee that newname contains a '/'
3663 p = strrchr_m(newname,'/');
3664 pstrcpy(newname_modified_last_component,p+1);
3666 if(strcsequal(newname_modified_last_component,
3667 newname_last_component) == False) {
3669 * Replace the modified last component with
3672 pstrcpy(p+1, newname_last_component);
3676 if(replace_if_exists) {
3678 * NT SMB specific flag - rename can overwrite
3679 * file with the same name so don't check for
3683 if(resolve_wildcards(directory,newname) &&
3684 can_rename(directory,conn) &&
3685 !conn->vfs_ops.rename(conn,directory,newname))
3688 if (resolve_wildcards(directory,newname) &&
3689 can_rename(directory,conn) &&
3690 !vfs_file_exist(conn,newname,NULL) &&
3691 !conn->vfs_ops.rename(conn,directory,newname))
3695 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3696 directory,newname));
3698 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3699 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3705 * Wildcards - process each file that matches.
3707 void *dirptr = NULL;
3711 if (check_name(directory,conn))
3712 dirptr = OpenDir(conn, directory, True);
3717 if (strequal(mask,"????????.???"))
3720 while ((dname = ReadDirName(dirptr))) {
3723 pstrcpy(fname,dname);
3725 if(!mask_match(fname, mask, case_sensitive))
3728 error = ERRnoaccess;
3729 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3730 if (!can_rename(fname,conn)) {
3731 DEBUG(6,("rename %s refused\n", fname));
3734 pstrcpy(destname,newname);
3736 if (!resolve_wildcards(fname,destname)) {
3737 DEBUG(6,("resolve_wildcards %s %s failed\n",
3742 if (!replace_if_exists &&
3743 vfs_file_exist(conn,destname, NULL)) {
3744 DEBUG(6,("file_exist %s\n", destname));
3749 if (!conn->vfs_ops.rename(conn,fname,destname))
3751 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3759 return(ERROR(ERRDOS,error));
3761 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3762 unix_ERR_class = ERRDOS;
3763 unix_ERR_code = ERRbadpath;
3765 return(UNIXERROR(ERRDOS,error));
3772 /****************************************************************************
3774 ****************************************************************************/
3776 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3783 START_PROFILE(SMBmv);
3785 p = smb_buf(inbuf) + 1;
3786 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3788 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3790 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3791 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3793 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3795 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3799 * Win2k needs a changenotify request response before it will
3800 * update after a rename..
3803 process_pending_change_notify_queue((time_t)0);
3805 outsize = set_message(outbuf,0,0,True);
3812 /*******************************************************************
3813 copy a file as part of a reply_copy
3814 ******************************************************************/
3816 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3817 int count,BOOL target_is_directory, int *err_ret)
3820 SMB_STRUCT_STAT src_sbuf, sbuf2;
3822 files_struct *fsp1,*fsp2;
3827 pstrcpy(dest,dest1);
3828 if (target_is_directory) {
3829 char *p = strrchr_m(src,'/');
3838 if (!vfs_file_exist(conn,src,&src_sbuf))
3841 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3842 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3848 if (!target_is_directory && count)
3849 ofun = FILE_EXISTS_OPEN;
3851 vfs_stat(conn,dest,&sbuf2);
3852 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3853 ofun,src_sbuf.st_mode,0,&Access,&action);
3856 close_file(fsp1,False);
3860 if ((ofun&3) == 1) {
3861 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3862 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3865 * Stop the copy from occurring.
3868 src_sbuf.st_size = 0;
3872 if (src_sbuf.st_size)
3873 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
3875 close_file(fsp1,False);
3877 * As we are opening fsp1 read-only we only expect
3878 * an error on close on fsp2 if we are out of space.
3879 * Thus we don't look at the error return from the
3882 *err_ret = close_file(fsp2,False);
3884 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3889 /****************************************************************************
3890 reply to a file copy.
3891 ****************************************************************************/
3892 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3897 pstring mask,newname;
3900 int error = ERRnoaccess;
3904 int tid2 = SVAL(inbuf,smb_vwv0);
3905 int ofun = SVAL(inbuf,smb_vwv1);
3906 int flags = SVAL(inbuf,smb_vwv2);
3907 BOOL target_is_directory=False;
3908 BOOL bad_path1 = False;
3909 BOOL bad_path2 = False;
3911 SMB_STRUCT_STAT sbuf1, sbuf2;
3912 START_PROFILE(SMBcopy);
3914 *directory = *mask = 0;
3917 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3918 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3920 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3922 if (tid2 != conn->cnum) {
3923 /* can't currently handle inter share copies XXXX */
3924 DEBUG(3,("Rejecting inter-share copy\n"));
3925 END_PROFILE(SMBcopy);
3926 return(ERROR(ERRSRV,ERRinvdevice));
3929 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3930 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3932 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3933 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3935 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3937 if ((flags&1) && target_is_directory) {
3938 END_PROFILE(SMBcopy);
3939 return(ERROR(ERRDOS,ERRbadfile));
3942 if ((flags&2) && !target_is_directory) {
3943 END_PROFILE(SMBcopy);
3944 return(ERROR(ERRDOS,ERRbadpath));
3947 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3948 /* wants a tree copy! XXXX */
3949 DEBUG(3,("Rejecting tree copy\n"));
3950 END_PROFILE(SMBcopy);
3951 return(ERROR(ERRSRV,ERRerror));
3954 p = strrchr_m(name,'/');
3956 pstrcpy(directory,"./");
3960 pstrcpy(directory,name);
3965 * We should only check the mangled cache
3966 * here if unix_convert failed. This means
3967 * that the path in 'mask' doesn't exist
3968 * on the file system and so we need to look
3969 * for a possible mangle. This patch from
3970 * Tine Smukavec <valentin.smukavec@hermes.si>.
3973 if (!rc && is_mangled(mask))
3974 check_mangled_cache( mask );
3976 has_wild = ms_has_wild(mask);
3979 pstrcat(directory,"/");
3980 pstrcat(directory,mask);
3981 if (resolve_wildcards(directory,newname) &&
3982 copy_file(directory,newname,conn,ofun,
3983 count,target_is_directory,&err)) count++;
3986 END_PROFILE(SMBcopy);
3987 return(UNIXERROR(ERRHRD,ERRgeneral));
3989 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3991 void *dirptr = NULL;
3995 if (check_name(directory,conn))
3996 dirptr = OpenDir(conn, directory, True);
4001 if (strequal(mask,"????????.???"))
4004 while ((dname = ReadDirName(dirptr))) {
4006 pstrcpy(fname,dname);
4008 if(!mask_match(fname, mask, case_sensitive))
4011 error = ERRnoaccess;
4012 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4013 pstrcpy(destname,newname);
4014 if (resolve_wildcards(fname,destname) &&
4015 copy_file(fname,destname,conn,ofun,
4016 count,target_is_directory,&err)) count++;
4017 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4025 /* Error on close... */
4027 END_PROFILE(SMBcopy);
4028 return(UNIXERROR(ERRHRD,ERRgeneral));
4032 END_PROFILE(SMBcopy);
4033 return(ERROR(ERRDOS,error));
4036 if((errno == ENOENT) && (bad_path1 || bad_path2))
4038 unix_ERR_class = ERRDOS;
4039 unix_ERR_code = ERRbadpath;
4041 END_PROFILE(SMBcopy);
4042 return(UNIXERROR(ERRDOS,error));
4046 outsize = set_message(outbuf,1,0,True);
4047 SSVAL(outbuf,smb_vwv0,count);
4049 END_PROFILE(SMBcopy);
4053 /****************************************************************************
4055 ****************************************************************************/
4056 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4062 START_PROFILE(pathworks_setdir);
4065 if (!CAN_SETDIR(snum)) {
4066 END_PROFILE(pathworks_setdir);
4067 return(ERROR(ERRDOS,ERRnoaccess));
4070 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
4072 if (strlen(newdir) == 0) {
4075 ok = vfs_directory_exist(conn,newdir,NULL);
4077 string_set(&conn->connectpath,newdir);
4082 END_PROFILE(pathworks_setdir);
4083 return(ERROR(ERRDOS,ERRbadpath));
4086 outsize = set_message(outbuf,0,0,True);
4087 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4089 DEBUG(3,("setdir %s\n", newdir));
4091 END_PROFILE(pathworks_setdir);
4095 /****************************************************************************
4096 Get a lock pid, dealing with large count requests.
4097 ****************************************************************************/
4099 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4101 if(!large_file_format)
4102 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4104 return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
4107 /****************************************************************************
4108 Get a lock count, dealing with large count requests.
4109 ****************************************************************************/
4111 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4113 SMB_BIG_UINT count = 0;
4115 if(!large_file_format) {
4116 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4119 #if defined(HAVE_LONGLONG)
4120 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4121 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4122 #else /* HAVE_LONGLONG */
4125 * NT4.x seems to be broken in that it sends large file (64 bit)
4126 * lockingX calls even if the CAP_LARGE_FILES was *not*
4127 * negotiated. For boxes without large unsigned ints truncate the
4128 * lock count by dropping the top 32 bits.
4131 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4132 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4133 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4134 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4135 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4138 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4139 #endif /* HAVE_LONGLONG */
4145 /****************************************************************************
4146 Get a lock offset, dealing with large offset requests.
4147 ****************************************************************************/
4149 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4151 SMB_BIG_UINT offset = 0;
4155 if(!large_file_format) {
4156 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4159 #if defined(HAVE_LONGLONG)
4160 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4161 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4162 #else /* HAVE_LONGLONG */
4165 * NT4.x seems to be broken in that it sends large file (64 bit)
4166 * lockingX calls even if the CAP_LARGE_FILES was *not*
4167 * negotiated. For boxes without large unsigned ints mangle the
4168 * lock offset by mapping the top 32 bits onto the lower 32.
4171 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4172 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4173 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4176 if((new_low = map_lock_offset(high, low)) == 0) {
4178 return (SMB_BIG_UINT)-1;
4181 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4182 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4183 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4184 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4187 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4188 #endif /* HAVE_LONGLONG */
4194 /****************************************************************************
4195 reply to a lockingX request
4196 ****************************************************************************/
4198 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4200 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4201 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4202 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4203 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4204 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4205 SMB_BIG_UINT count = 0, offset = 0;
4207 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4210 uint32 ecode=0, dummy2;
4211 int eclass=0, dummy1;
4212 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4214 START_PROFILE(SMBlockingX);
4216 CHECK_FSP(fsp,conn);
4219 data = smb_buf(inbuf);
4221 /* Check if this is an oplock break on a file
4222 we have granted an oplock on.
4224 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4226 /* Client can insist on breaking to none. */
4227 BOOL break_to_none = (oplocklevel == 0);
4229 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4230 (unsigned int)oplocklevel, fsp->fnum ));
4233 * Make sure we have granted an exclusive or batch oplock on this file.
4236 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4238 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4239 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4241 /* if this is a pure oplock break request then don't send a reply */
4242 if (num_locks == 0 && num_ulocks == 0) {
4243 END_PROFILE(SMBlockingX);
4246 END_PROFILE(SMBlockingX);
4247 return ERROR(ERRDOS,ERRlock);
4251 if (remove_oplock(fsp, break_to_none) == False) {
4252 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4256 /* if this is a pure oplock break request then don't send a reply */
4257 if (num_locks == 0 && num_ulocks == 0)
4259 /* Sanity check - ensure a pure oplock break is not a
4261 if(CVAL(inbuf,smb_vwv0) != 0xff)
4262 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4263 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4264 END_PROFILE(SMBlockingX);
4270 * We do this check *after* we have checked this is not a oplock break
4271 * response message. JRA.
4274 release_level_2_oplocks_on_change(fsp);
4276 /* Data now points at the beginning of the list
4277 of smb_unlkrng structs */
4278 for(i = 0; i < (int)num_ulocks; i++) {
4279 lock_pid = get_lock_pid( data, i, large_file_format);
4280 count = get_lock_count( data, i, large_file_format);
4281 offset = get_lock_offset( data, i, large_file_format, &err);
4284 * There is no error code marked "stupid client bug".... :-).
4287 END_PROFILE(SMBlockingX);
4288 return ERROR(ERRDOS,ERRnoaccess);
4291 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4292 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4294 if(!do_unlock(fsp,conn,lock_pid,count,offset, &eclass, &ecode)) {
4295 END_PROFILE(SMBlockingX);
4296 return ERROR(eclass,ecode);
4300 /* Setup the timeout in seconds. */
4301 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4303 /* Now do any requested locks */
4304 data += ((large_file_format ? 20 : 10)*num_ulocks);
4306 /* Data now points at the beginning of the list
4307 of smb_lkrng structs */
4309 for(i = 0; i < (int)num_locks; i++) {
4310 lock_pid = get_lock_pid( data, i, large_file_format);
4311 count = get_lock_count( data, i, large_file_format);
4312 offset = get_lock_offset( data, i, large_file_format, &err);
4315 * There is no error code marked "stupid client bug".... :-).
4318 END_PROFILE(SMBlockingX);
4319 return ERROR(ERRDOS,ERRnoaccess);
4322 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
4323 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4325 if(!do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4327 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4329 * A blocking lock was requested. Package up
4330 * this smb into a queued request and push it
4331 * onto the blocking lock queue.
4333 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4334 END_PROFILE(SMBlockingX);
4342 /* If any of the above locks failed, then we must unlock
4343 all of the previous locks (X/Open spec). */
4344 if(i != num_locks && num_locks != 0) {
4346 * Ensure we don't do a remove on the lock that just failed,
4347 * as under POSIX rules, if we have a lock already there, we
4348 * will delete it (and we shouldn't) .....
4350 for(i--; i >= 0; i--) {
4351 lock_pid = get_lock_pid( data, i, large_file_format);
4352 count = get_lock_count( data, i, large_file_format);
4353 offset = get_lock_offset( data, i, large_file_format, &err);
4356 * There is no error code marked "stupid client bug".... :-).
4359 END_PROFILE(SMBlockingX);
4360 return ERROR(ERRDOS,ERRnoaccess);
4363 do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2);
4365 END_PROFILE(SMBlockingX);
4366 return ERROR(eclass,ecode);
4369 set_message(outbuf,2,0,True);
4371 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4372 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4374 END_PROFILE(SMBlockingX);
4375 return chain_reply(inbuf,outbuf,length,bufsize);
4379 /****************************************************************************
4380 reply to a SMBreadbmpx (read block multiplex) request
4381 ****************************************************************************/
4382 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4393 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4394 START_PROFILE(SMBreadBmpx);
4396 /* this function doesn't seem to work - disable by default */
4397 if (!lp_readbmpx()) {
4398 END_PROFILE(SMBreadBmpx);
4399 return(ERROR(ERRSRV,ERRuseSTD));
4402 outsize = set_message(outbuf,8,0,True);
4404 CHECK_FSP(fsp,conn);
4408 startpos = IVAL(inbuf,smb_vwv1);
4409 maxcount = SVAL(inbuf,smb_vwv3);
4411 data = smb_buf(outbuf);
4412 pad = ((long)data)%4;
4413 if (pad) pad = 4 - pad;
4416 max_per_packet = bufsize-(outsize+pad);
4420 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4421 END_PROFILE(SMBreadBmpx);
4422 return(ERROR(ERRDOS,ERRlock));
4427 size_t N = MIN(max_per_packet,tcount-total_read);
4429 nread = read_file(fsp,data,startpos,N);
4431 if (nread <= 0) nread = 0;
4433 if (nread < (ssize_t)N)
4434 tcount = total_read + nread;
4436 set_message(outbuf,8,nread,False);
4437 SIVAL(outbuf,smb_vwv0,startpos);
4438 SSVAL(outbuf,smb_vwv2,tcount);
4439 SSVAL(outbuf,smb_vwv6,nread);
4440 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4442 if (!send_smb(smbd_server_fd(),outbuf))
4443 exit_server("reply_readbmpx: send_smb failed.\n");
4445 total_read += nread;
4448 while (total_read < (ssize_t)tcount);
4450 END_PROFILE(SMBreadBmpx);
4454 /****************************************************************************
4455 reply to a SMBwritebmpx (write block multiplex primary) request
4456 ****************************************************************************/
4458 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4461 ssize_t nwritten = -1;
4468 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4469 START_PROFILE(SMBwriteBmpx);
4471 CHECK_FSP(fsp,conn);
4475 tcount = SVAL(inbuf,smb_vwv1);
4476 startpos = IVAL(inbuf,smb_vwv3);
4477 write_through = BITSETW(inbuf+smb_vwv7,0);
4478 numtowrite = SVAL(inbuf,smb_vwv10);
4479 smb_doff = SVAL(inbuf,smb_vwv11);
4481 data = smb_base(inbuf) + smb_doff;
4483 /* If this fails we need to send an SMBwriteC response,
4484 not an SMBwritebmpx - set this up now so we don't forget */
4485 CVAL(outbuf,smb_com) = SMBwritec;
4487 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4488 END_PROFILE(SMBwriteBmpx);
4489 return(ERROR(ERRDOS,ERRlock));
4492 nwritten = write_file(fsp,data,startpos,numtowrite);
4494 if(lp_syncalways(SNUM(conn)) || write_through)
4495 sync_file(conn,fsp);
4497 if(nwritten < (ssize_t)numtowrite) {
4498 END_PROFILE(SMBwriteBmpx);
4499 return(UNIXERROR(ERRHRD,ERRdiskfull));
4502 /* If the maximum to be written to this file
4503 is greater than what we just wrote then set
4504 up a secondary struct to be attached to this
4505 fd, we will use this to cache error messages etc. */
4506 if((ssize_t)tcount > nwritten)
4508 write_bmpx_struct *wbms;
4509 if(fsp->wbmpx_ptr != NULL)
4510 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4512 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4515 DEBUG(0,("Out of memory in reply_readmpx\n"));
4516 END_PROFILE(SMBwriteBmpx);
4517 return(ERROR(ERRSRV,ERRnoresource));
4519 wbms->wr_mode = write_through;
4520 wbms->wr_discard = False; /* No errors yet */
4521 wbms->wr_total_written = nwritten;
4522 wbms->wr_errclass = 0;
4524 fsp->wbmpx_ptr = wbms;
4527 /* We are returning successfully, set the message type back to
4529 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4531 outsize = set_message(outbuf,1,0,True);
4533 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4535 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4536 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4538 if (write_through && tcount==nwritten) {
4539 /* we need to send both a primary and a secondary response */
4540 smb_setlen(outbuf,outsize - 4);
4541 if (!send_smb(smbd_server_fd(),outbuf))
4542 exit_server("reply_writebmpx: send_smb failed.\n");
4544 /* now the secondary */
4545 outsize = set_message(outbuf,1,0,True);
4546 CVAL(outbuf,smb_com) = SMBwritec;
4547 SSVAL(outbuf,smb_vwv0,nwritten);
4550 END_PROFILE(SMBwriteBmpx);
4555 /****************************************************************************
4556 reply to a SMBwritebs (write block multiplex secondary) request
4557 ****************************************************************************/
4558 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4561 ssize_t nwritten = -1;
4568 write_bmpx_struct *wbms;
4569 BOOL send_response = False;
4570 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4571 START_PROFILE(SMBwriteBs);
4573 CHECK_FSP(fsp,conn);
4576 tcount = SVAL(inbuf,smb_vwv1);
4577 startpos = IVAL(inbuf,smb_vwv2);
4578 numtowrite = SVAL(inbuf,smb_vwv6);
4579 smb_doff = SVAL(inbuf,smb_vwv7);
4581 data = smb_base(inbuf) + smb_doff;
4583 /* We need to send an SMBwriteC response, not an SMBwritebs */
4584 CVAL(outbuf,smb_com) = SMBwritec;
4586 /* This fd should have an auxiliary struct attached,
4587 check that it does */
4588 wbms = fsp->wbmpx_ptr;
4590 END_PROFILE(SMBwriteBs);
4594 /* If write through is set we can return errors, else we must
4596 write_through = wbms->wr_mode;
4598 /* Check for an earlier error */
4599 if(wbms->wr_discard) {
4600 END_PROFILE(SMBwriteBs);
4601 return -1; /* Just discard the packet */
4604 nwritten = write_file(fsp,data,startpos,numtowrite);
4606 if(lp_syncalways(SNUM(conn)) || write_through)
4607 sync_file(conn,fsp);
4609 if (nwritten < (ssize_t)numtowrite)
4613 /* We are returning an error - we can delete the aux struct */
4614 if (wbms) free((char *)wbms);
4615 fsp->wbmpx_ptr = NULL;
4616 END_PROFILE(SMBwriteBs);
4617 return(ERROR(ERRHRD,ERRdiskfull));
4619 END_PROFILE(SMBwriteBs);
4620 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4623 /* Increment the total written, if this matches tcount
4624 we can discard the auxiliary struct (hurrah !) and return a writeC */
4625 wbms->wr_total_written += nwritten;
4626 if(wbms->wr_total_written >= tcount)
4630 outsize = set_message(outbuf,1,0,True);
4631 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4632 send_response = True;
4636 fsp->wbmpx_ptr = NULL;
4640 END_PROFILE(SMBwriteBs);
4644 END_PROFILE(SMBwriteBs);
4649 /****************************************************************************
4650 reply to a SMBsetattrE
4651 ****************************************************************************/
4653 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4655 struct utimbuf unix_times;
4657 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4658 START_PROFILE(SMBsetattrE);
4660 outsize = set_message(outbuf,0,0,True);
4662 CHECK_FSP(fsp,conn);
4665 /* Convert the DOS times into unix times. Ignore create
4666 time as UNIX can't set this.
4668 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4669 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4672 * Patch from Ray Frush <frush@engr.colostate.edu>
4673 * Sometimes times are sent as zero - ignore them.
4676 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4678 /* Ignore request */
4681 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4682 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4684 END_PROFILE(SMBsetattrE);
4687 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4689 /* set modify time = to access time if modify time was 0 */
4690 unix_times.modtime = unix_times.actime;
4693 /* Set the date on this file */
4694 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4695 END_PROFILE(SMBsetattrE);
4696 return(ERROR(ERRDOS,ERRnoaccess));
4699 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4700 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4702 END_PROFILE(SMBsetattrE);
4707 /****************************************************************************
4708 reply to a SMBgetattrE
4709 ****************************************************************************/
4711 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4713 SMB_STRUCT_STAT sbuf;
4716 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4717 START_PROFILE(SMBgetattrE);
4719 outsize = set_message(outbuf,11,0,True);
4721 CHECK_FSP(fsp,conn);
4724 /* Do an fstat on this file */
4725 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4726 END_PROFILE(SMBgetattrE);
4727 return(UNIXERROR(ERRDOS,ERRnoaccess));
4730 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4732 /* Convert the times into dos times. Set create
4733 date to be last modify date as UNIX doesn't save
4735 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4736 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4737 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4740 SIVAL(outbuf,smb_vwv6,0);
4741 SIVAL(outbuf,smb_vwv8,0);
4745 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4746 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4748 SSVAL(outbuf,smb_vwv10, mode);
4750 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4752 END_PROFILE(SMBgetattrE);