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 int global_oplock_break;
41 uint32 global_client_caps = 0;
42 unsigned int smb_echo_count = 0;
44 /****************************************************************************
45 report a possible attack via the password buffer overflow bug
46 ****************************************************************************/
48 static void overflow_attack(int len)
51 dbgtext( "ERROR: Invalid password length %d.\n", len );
52 dbgtext( "Your machine may be under attack by someone " );
53 dbgtext( "attempting to exploit an old bug.\n" );
54 dbgtext( "Attack was from IP = %s.\n", client_addr() );
59 /****************************************************************************
60 reply to an special message
61 ****************************************************************************/
63 int reply_special(char *inbuf,char *outbuf)
66 int msg_type = CVAL(inbuf,0);
67 int msg_flags = CVAL(inbuf,1);
69 extern fstring remote_machine;
70 extern fstring local_machine;
76 memset(outbuf,'\0',smb_size);
81 case 0x81: /* session request */
82 CVAL(outbuf,0) = 0x82;
84 if (name_len(inbuf+4) > 50 ||
85 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
86 DEBUG(0,("Invalid name length in session request\n"));
89 name_extract(inbuf,4,name1);
90 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
91 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
94 fstrcpy(remote_machine,name2);
95 remote_machine[15] = 0;
96 trim_string(remote_machine," "," ");
97 strlower(remote_machine);
98 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
100 fstrcpy(local_machine,name1);
101 len = strlen(local_machine);
103 name_type = local_machine[15];
104 local_machine[15] = 0;
106 trim_string(local_machine," "," ");
107 strlower(local_machine);
108 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
110 DEBUG(2,("netbios connect: local=%s remote=%s\n",
111 local_machine, remote_machine ));
113 if (name_type == 'R') {
114 /* We are being asked for a pathworks session ---
116 CVAL(outbuf, 0) = 0x83;
120 /* only add the client's machine name to the list
121 of possibly valid usernames if we are operating
122 in share mode security */
123 if (lp_security() == SEC_SHARE) {
124 add_session_user(remote_machine);
127 reload_services(True);
130 claim_connection(NULL,"",MAXSTATUS,True);
134 case 0x89: /* session keepalive request
135 (some old clients produce this?) */
136 CVAL(outbuf,0) = 0x85;
140 case 0x82: /* positive session response */
141 case 0x83: /* negative session response */
142 case 0x84: /* retarget session response */
143 DEBUG(0,("Unexpected session response\n"));
146 case 0x85: /* session keepalive */
151 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
152 msg_type, msg_flags));
158 /*******************************************************************
159 work out what error to give to a failed connection
160 ********************************************************************/
162 static int connection_error(char *inbuf,char *outbuf,int ecode)
164 if (ecode == ERRnoipc || ecode == ERRnosuchshare)
165 return(ERROR(ERRDOS,ecode));
167 return(ERROR(ERRSRV,ecode));
171 /****************************************************************************
173 ****************************************************************************/
175 int reply_tcon(connection_struct *conn,
176 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
183 uint16 vuid = SVAL(inbuf,smb_uid);
188 START_PROFILE(SMBtcon);
190 *service = *user = *password = *dev = 0;
192 p = smb_buf(inbuf)+1;
193 p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1;
194 p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
195 p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1;
198 p = strchr_m(service,'%');
204 p = strrchr_m(service,'\\');
206 pstrcpy(service, p+1);
210 * If the vuid is valid, we should be using that....
213 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
214 pstrcpy(user,validated_username(vuid));
218 * Pass the user through the NT -> unix user mapping
222 (void)map_username(user);
225 * Do any UNIX username case mangling.
227 (void)Get_Pwnam( user, True);
230 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
233 END_PROFILE(SMBtcon);
234 return(connection_error(inbuf,outbuf,ecode));
237 outsize = set_message(outbuf,2,0,True);
238 SSVAL(outbuf,smb_vwv0,max_recv);
239 SSVAL(outbuf,smb_vwv1,conn->cnum);
240 SSVAL(outbuf,smb_tid,conn->cnum);
242 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
243 service, user, conn->cnum));
245 END_PROFILE(SMBtcon);
249 /****************************************************************************
250 Reply to a tcon and X.
251 ****************************************************************************/
253 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
260 uint16 vuid = SVAL(inbuf,smb_uid);
261 int passlen = SVAL(inbuf,smb_vwv3);
264 START_PROFILE(SMBtconX);
266 *service = *user = *password = *devicename = 0;
268 /* we might have to close an old one */
269 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
270 close_cnum(conn,vuid);
273 if (passlen > MAX_PASS_LEN) {
274 overflow_attack(passlen);
275 return(ERROR(ERRDOS,ERRbuftoosmall));
278 memcpy(password,smb_buf(inbuf),passlen);
280 p = smb_buf(inbuf) + passlen;
281 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
284 if (strequal(password," "))
286 passlen = strlen(password);
291 * the service name can be either: \\server\share
292 * or share directly like on the DELL PowerVault 705
295 q = strchr_m(path+2,'\\');
297 END_PROFILE(SMBtconX);
298 return(ERROR(ERRDOS,ERRnosuchshare));
300 fstrcpy(service,q+1);
303 fstrcpy(service,path);
305 q = strchr_m(service,'%');
310 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
312 DEBUG(4,("Got device type %s\n",devicename));
315 * If the vuid is valid, we should be using that....
318 if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
319 pstrcpy(user,validated_username(vuid));
323 * Pass the user through the NT -> unix user mapping
327 (void)map_username(user);
330 * Do any UNIX username case mangling.
332 (void)Get_Pwnam(user, True);
336 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
339 END_PROFILE(SMBtconX);
340 return(connection_error(inbuf,outbuf,ecode));
343 if (Protocol < PROTOCOL_NT1) {
344 set_message(outbuf,2,0,True);
346 p += srvstr_push(outbuf, p, devicename, -1,
347 STR_TERMINATE|STR_ASCII);
348 set_message_end(outbuf,p);
350 /* NT sets the fstype of IPC$ to the null string */
351 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
353 set_message(outbuf,3,0,True);
356 p += srvstr_push(outbuf, p, devicename, -1,
357 STR_TERMINATE|STR_ASCII);
358 p += srvstr_push(outbuf, p, fsname, -1,
361 set_message_end(outbuf,p);
363 /* what does setting this bit do? It is set by NT4 and
364 may affect the ability to autorun mounted cdroms */
365 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
367 init_dfsroot(conn, inbuf, outbuf);
371 DEBUG(3,("tconX service=%s user=%s\n",
374 /* set the incoming and outgoing tid to the just created one */
375 SSVAL(inbuf,smb_tid,conn->cnum);
376 SSVAL(outbuf,smb_tid,conn->cnum);
378 END_PROFILE(SMBtconX);
379 return chain_reply(inbuf,outbuf,length,bufsize);
383 /****************************************************************************
384 reply to an unknown type
385 ****************************************************************************/
386 int reply_unknown(char *inbuf,char *outbuf)
389 type = CVAL(inbuf,smb_com);
391 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
392 smb_fn_name(type), type, type));
394 return(ERROR(ERRSRV,ERRunknownsmb));
398 /****************************************************************************
400 ****************************************************************************/
401 int reply_ioctl(connection_struct *conn,
402 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
404 uint16 device = SVAL(inbuf,smb_vwv1);
405 uint16 function = SVAL(inbuf,smb_vwv2);
406 uint32 ioctl_code = (device << 16) + function;
407 int replysize, outsize;
409 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
410 START_PROFILE(SMBioctl);
412 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
416 case IOCTL_QUERY_JOB_INFO:
420 END_PROFILE(SMBioctl);
421 return(ERROR(ERRSRV,ERRnosupport));
424 outsize = set_message(outbuf,8,replysize+1,True);
425 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
426 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
427 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
428 p = smb_buf(outbuf) + 1; /* Allow for alignment */
432 case IOCTL_QUERY_JOB_INFO:
433 SSVAL(p,0,fsp->print_jobid); /* Job number */
434 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
435 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
439 END_PROFILE(SMBioctl);
443 /****************************************************************************
444 This function breaks the authentication split. It needs sorting out.
445 I can't see why we can't hadle this INSIDE the check_password, as in then
446 end all it does it spit out an nt_status code.
447 ****************************************************************************/
448 /****************************************************************************
449 always return an error: it's just a matter of which one...
450 ****************************************************************************/
451 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
452 char *smb_passwd, int smb_passlen,
453 char *smb_nt_passwd, int smb_nt_passlen)
455 /* check if trust account exists */
456 SAM_ACCOUNT *sam_trust_acct = NULL;
459 auth_usersupplied_info user_info;
460 auth_serversupplied_info server_info;
461 AUTH_STR domain, smb_username, wksta_name;
463 ZERO_STRUCT(user_info);
464 ZERO_STRUCT(server_info);
466 ZERO_STRUCT(smb_username);
467 ZERO_STRUCT(wksta_name);
469 domain.str = lp_workgroup();
470 domain.len = strlen(domain.str);
472 user_info.requested_domain = domain;
473 user_info.domain = domain;
475 smb_username.str = user;
476 smb_username.len = strlen(smb_username.str);
478 user_info.requested_username = smb_username; /* For the time-being */
479 user_info.smb_username = smb_username;
481 user_info.wksta_name = wksta_name;
483 user_info.lm_resp.buffer = (uint8 *)smb_passwd;
484 user_info.lm_resp.len = smb_passlen;
485 user_info.nt_resp.buffer = (uint8 *)smb_nt_passwd;
486 user_info.nt_resp.len = smb_nt_passlen;
488 if (!last_challenge(user_info.chal)) {
489 DEBUG(1,("smb_password_ok: no challenge done - password failed\n"));
490 return NT_STATUS_LOGON_FAILURE;
493 pdb_init_sam(&sam_trust_acct);
495 if (lp_security() == SEC_USER) {
496 ret = pdb_getsampwnam(sam_trust_acct, user);
498 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
499 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
500 pdb_free_sam(sam_trust_acct);
501 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
505 /* lkclXXXX: workstation entry doesn't exist */
506 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
507 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
508 pdb_free_sam(sam_trust_acct);
509 return(ERROR(0, NT_STATUS_NO_SUCH_USER));
511 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
512 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\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 if (!smb_password_ok(sam_trust_acct, &user_info, &server_info)) {
519 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
520 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
521 pdb_free_sam(sam_trust_acct);
522 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
525 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
526 pdb_free_sam(sam_trust_acct);
527 if (acct_ctrl & ACB_DOMTRUST) {
528 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
529 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
530 return(ERROR(0, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
533 if (acct_ctrl & ACB_SVRTRUST) {
534 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
535 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
536 return(ERROR(0, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
539 if (acct_ctrl & ACB_WSTRUST) {
540 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
541 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
542 return(ERROR(0, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
546 /* don't know what to do: indicate logon failure */
547 SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
548 return(ERROR(0, NT_STATUS_LOGON_FAILURE));
551 /****************************************************************************
552 Return a bad password error configured for the correct client type.
553 ****************************************************************************/
555 static int bad_password_error(char *inbuf,char *outbuf)
558 if (global_client_caps & CAP_STATUS32) {
559 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
560 return(ERROR(0,NT_STATUS_LOGON_FAILURE));
563 return(ERROR(ERRSRV,ERRbadpw));
566 /****************************************************************************
567 reply to a session setup command
568 ****************************************************************************/
570 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
577 int smb_apasslen = 0;
579 int smb_ntpasslen = 0;
580 pstring smb_ntpasswd;
581 BOOL valid_password = False;
586 fstring native_lanman;
588 static BOOL done_sesssetup = False;
589 BOOL doencrypt = SMBENCRYPT();
590 START_PROFILE(SMBsesssetupX);
595 smb_bufsize = SVAL(inbuf,smb_vwv2);
597 if (Protocol < PROTOCOL_NT1) {
598 smb_apasslen = SVAL(inbuf,smb_vwv7);
599 if (smb_apasslen > MAX_PASS_LEN) {
600 overflow_attack(smb_apasslen);
601 return(ERROR(ERRDOS,ERRbuftoosmall));
604 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
605 srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE);
607 if (!doencrypt && (lp_security() != SEC_SERVER)) {
608 smb_apasslen = strlen(smb_apasswd);
611 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
612 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
613 enum remote_arch_types ra_type = get_remote_arch();
614 char *p = smb_buf(inbuf);
616 if(global_client_caps == 0)
617 global_client_caps = IVAL(inbuf,smb_vwv11);
619 /* client_caps is used as final determination if client is NT or Win95.
620 This is needed to return the correct error codes in some
624 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
625 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
626 set_remote_arch( RA_WIN95);
630 if (passlen1 != 24 && passlen2 != 24)
633 if (passlen1 > MAX_PASS_LEN) {
634 overflow_attack(passlen1);
635 return(ERROR(ERRDOS,ERRbuftoosmall));
638 passlen1 = MIN(passlen1, MAX_PASS_LEN);
639 passlen2 = MIN(passlen2, MAX_PASS_LEN);
642 /* both Win95 and WinNT stuff up the password lengths for
643 non-encrypting systems. Uggh.
645 if passlen1==24 its a win95 system, and its setting the
646 password length incorrectly. Luckily it still works with the
647 default code because Win95 will null terminate the password
650 if passlen1>0 and passlen2>0 then maybe its a NT box and its
651 setting passlen2 to some random value which really stuffs
652 things up. we need to fix that one. */
654 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
658 if (lp_restrict_anonymous()) {
659 /* there seems to be no reason behind the differences in MS clients formatting
660 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
661 * in particular seems to have an extra null byte between the username and the
662 * domain, or the password length calculation is wrong, which throws off the
663 * string extraction routines below. This makes the value of domain be the
664 * empty string, which fails the restrict anonymous check further down.
665 * This compensates for that, and allows browsing to work in mixed NT and
666 * win95 environments even when restrict anonymous is true. AAB
668 dump_data(100, p, 0x70);
669 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
670 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
671 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
672 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
673 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
678 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
679 /* Save the lanman2 password and the NT md4 password. */
680 smb_apasslen = passlen1;
681 memcpy(smb_apasswd,p,smb_apasslen);
682 smb_apasswd[smb_apasslen] = 0;
683 smb_ntpasslen = passlen2;
684 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
685 smb_ntpasswd[smb_ntpasslen] = 0;
687 /* we use the first password that they gave */
688 smb_apasslen = passlen1;
689 StrnCpy(smb_apasswd,p,smb_apasslen);
691 /* trim the password */
692 smb_apasslen = strlen(smb_apasswd);
694 /* wfwg sometimes uses a space instead of a null */
695 if (strequal(smb_apasswd," ")) {
701 p += passlen1 + passlen2;
702 p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
705 * Incoming user and domain are in DOS codepage format. Convert
708 p += srvstr_pull(inbuf, domain, p, sizeof(domain),
710 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
712 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
714 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
715 domain,native_os,native_lanman));
718 /* don't allow for weird usernames or domains */
719 alpha_strcpy(user, user, ". _-$", sizeof(user));
720 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
721 if (strstr(user, "..") || strstr(domain,"..")) {
722 return bad_password_error(inbuf, outbuf);
725 if (lp_security() == SEC_SHARE) {
726 /* in share level we should ignore any passwords */
733 DEBUG(3,("sesssetupX:name=[%s]\n",user));
735 /* If name ends in $ then I think it's asking about whether a */
736 /* computer with that name (minus the $) has access. For now */
737 /* say yes to everything ending in $. */
739 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
740 END_PROFILE(SMBsesssetupX);
741 return session_trust_account(conn, inbuf, outbuf, user,
742 smb_apasswd, smb_apasslen,
743 smb_ntpasswd, smb_ntpasslen);
746 if (done_sesssetup && lp_restrict_anonymous()) {
747 /* tests show that even if browsing is done over already validated connections
748 * without a username and password the domain is still provided, which it
749 * wouldn't be if it was a purely anonymous connection. So, in order to
750 * restrict anonymous, we only deny connections that have no session
751 * information. If a domain has been provided, then it's not a purely
752 * anonymous connection. AAB
754 if (!*user && !*smb_apasswd && !*domain) {
755 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
756 END_PROFILE(SMBsesssetupX);
757 return(ERROR(ERRDOS,ERRnoaccess));
761 /* If no username is sent use the guest account */
763 pstrcpy(user,lp_guestaccount(-1));
767 pstrcpy(current_user_info.smb_name,user);
769 reload_services(True);
772 * Save the username before mapping. We will use
773 * the original username sent to us for security=server
774 * and security=domain checking.
777 pstrcpy( orig_user, user);
780 * Always try the "DOMAIN\user" lookup first, as this is the most
781 * specific case. If this fails then try the simple "user" lookup.
782 * But don't do this for guests, as this is always a local user.
788 /* Work out who's who */
790 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
791 domain, lp_winbind_separator(), user);
793 if (sys_getpwnam(dom_user) != NULL) {
794 pstrcpy(user, dom_user);
795 DEBUG(3,("Using unix username %s\n", dom_user));
799 * Pass the user through the NT -> unix user mapping
803 (void)map_username(user);
806 * Do any UNIX username case mangling.
808 smb_getpwnam(user, True);
811 add_session_user(user);
814 valid_password = (pass_check_smb(user, domain,
815 smb_apasswd, smb_apasslen,
816 smb_ntpasswd, smb_ntpasslen) == NT_STATUS_NOPROBLEMO);
818 /* The true branch will be executed if
819 (1) the NT password failed (or was not tried), and
820 (2) LanMan authentication failed (or was disabled)
824 if (lp_security() >= SEC_USER)
826 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
828 DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
829 END_PROFILE(SMBsesssetupX);
830 return bad_password_error(inbuf,outbuf);
833 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
835 if (smb_getpwnam(user,True))
837 DEBUG(1,("Rejecting user '%s': bad password\n", user));
838 END_PROFILE(SMBsesssetupX);
839 return bad_password_error(inbuf,outbuf);
844 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
845 * Then always map to guest account - as done below.
849 if (*smb_apasswd || !smb_getpwnam(user,True))
850 pstrcpy(user,lp_guestaccount(-1));
851 DEBUG(3,("Registered username %s for guest access\n",user));
856 if (!smb_getpwnam(user,True)) {
857 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
858 pstrcpy(user,lp_guestaccount(-1));
862 if (!strequal(user,lp_guestaccount(-1)) &&
863 lp_servicenumber(user) < 0)
865 add_home_service(user,get_user_home_dir(user));
869 /* it's ok - setup a reply */
870 if (Protocol < PROTOCOL_NT1) {
871 set_message(outbuf,3,0,True);
874 set_message(outbuf,3,0,True);
876 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
877 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
878 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
879 set_message_end(outbuf,p);
880 /* perhaps grab OS version here?? */
883 /* Set the correct uid in the outgoing and incoming packets
884 We will use this on future requests to determine which
885 user we should become.
888 const struct passwd *pw = smb_getpwnam(user,False);
890 DEBUG(1,("Username %s is invalid on this system\n",user));
891 END_PROFILE(SMBsesssetupX);
892 return bad_password_error(inbuf,outbuf);
896 full_name = pw->pw_gecos;
900 SSVAL(outbuf,smb_vwv2,1);
902 /* register the name and uid as being validated, so further connections
903 to a uid can get through without a password, on the same VC */
905 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest, full_name);
907 if (sess_vuid == -1) {
908 return(ERROR(ERRDOS,ERRnoaccess));
912 SSVAL(outbuf,smb_uid,sess_vuid);
913 SSVAL(inbuf,smb_uid,sess_vuid);
916 max_send = MIN(max_send,smb_bufsize);
918 DEBUG(6,("Client requested max send size of %d\n", max_send));
920 done_sesssetup = True;
922 END_PROFILE(SMBsesssetupX);
923 return chain_reply(inbuf,outbuf,length,bufsize);
926 /****************************************************************************
928 ****************************************************************************/
929 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
935 BOOL bad_path = False;
936 SMB_STRUCT_STAT sbuf;
937 START_PROFILE(SMBchkpth);
939 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
941 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
943 unix_convert(name,conn,0,&bad_path,&sbuf);
945 mode = SVAL(inbuf,smb_vwv0);
947 if (check_name(name,conn)) {
948 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
949 ok = S_ISDIR(sbuf.st_mode);
954 /* We special case this - as when a Windows machine
955 is parsing a path is steps through the components
956 one at a time - if a component fails it expects
957 ERRbadpath, not ERRbadfile.
961 unix_ERR_class = ERRDOS;
962 unix_ERR_code = ERRbadpath;
966 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
967 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
968 (get_remote_arch() == RA_WINNT))
970 unix_ERR_class = ERRDOS;
971 unix_ERR_code = ERRbaddirectory;
975 return(UNIXERROR(ERRDOS,ERRbadpath));
978 outsize = set_message(outbuf,0,0,True);
980 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
982 END_PROFILE(SMBchkpth);
987 /****************************************************************************
989 ****************************************************************************/
990 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
994 SMB_STRUCT_STAT sbuf;
999 BOOL bad_path = False;
1001 START_PROFILE(SMBgetatr);
1003 p = smb_buf(inbuf) + 1;
1004 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1006 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1008 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1009 under WfWg - weird! */
1012 mode = aHIDDEN | aDIR;
1013 if (!CAN_WRITE(conn)) mode |= aRONLY;
1020 unix_convert(fname,conn,0,&bad_path,&sbuf);
1021 if (check_name(fname,conn))
1023 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
1025 mode = dos_mode(conn,fname,&sbuf);
1026 size = sbuf.st_size;
1027 mtime = sbuf.st_mtime;
1033 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
1039 if((errno == ENOENT) && bad_path)
1041 unix_ERR_class = ERRDOS;
1042 unix_ERR_code = ERRbadpath;
1045 END_PROFILE(SMBgetatr);
1046 return(UNIXERROR(ERRDOS,ERRbadfile));
1049 outsize = set_message(outbuf,10,0,True);
1051 SSVAL(outbuf,smb_vwv0,mode);
1052 if(lp_dos_filetime_resolution(SNUM(conn)) )
1053 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
1055 put_dos_date3(outbuf,smb_vwv1,mtime);
1056 SIVAL(outbuf,smb_vwv3,(uint32)size);
1058 if (Protocol >= PROTOCOL_NT1) {
1059 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1062 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
1064 END_PROFILE(SMBgetatr);
1069 /****************************************************************************
1071 ****************************************************************************/
1072 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1079 SMB_STRUCT_STAT sbuf;
1080 BOOL bad_path = False;
1083 START_PROFILE(SMBsetatr);
1085 p = smb_buf(inbuf) + 1;
1086 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
1087 unix_convert(fname,conn,0,&bad_path,&sbuf);
1089 mode = SVAL(inbuf,smb_vwv0);
1090 mtime = make_unix_date3(inbuf+smb_vwv1);
1092 if (VALID_STAT_OF_DIR(sbuf))
1094 if (check_name(fname,conn))
1095 ok = (file_chmod(conn,fname,mode,NULL) == 0);
1097 ok = set_filetime(conn,fname,mtime);
1101 if((errno == ENOENT) && bad_path)
1103 unix_ERR_class = ERRDOS;
1104 unix_ERR_code = ERRbadpath;
1107 END_PROFILE(SMBsetatr);
1108 return(UNIXERROR(ERRDOS,ERRnoaccess));
1111 outsize = set_message(outbuf,0,0,True);
1113 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1115 END_PROFILE(SMBsetatr);
1120 /****************************************************************************
1122 ****************************************************************************/
1123 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1126 SMB_BIG_UINT dfree,dsize,bsize;
1127 START_PROFILE(SMBdskattr);
1129 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1131 outsize = set_message(outbuf,5,0,True);
1133 SSVAL(outbuf,smb_vwv0,dsize);
1134 SSVAL(outbuf,smb_vwv1,bsize/512);
1135 SSVAL(outbuf,smb_vwv2,512);
1136 SSVAL(outbuf,smb_vwv3,dfree);
1138 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1140 END_PROFILE(SMBdskattr);
1145 /****************************************************************************
1147 Can be called from SMBsearch, SMBffirst or SMBfunique.
1148 ****************************************************************************/
1149 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1160 BOOL finished = False;
1169 BOOL check_descend = False;
1170 BOOL expect_close = False;
1171 BOOL can_open = True;
1172 BOOL bad_path = False;
1173 START_PROFILE(SMBsearch);
1175 *mask = *directory = *fname = 0;
1177 /* If we were called as SMBffirst then we must expect close. */
1178 if(CVAL(inbuf,smb_com) == SMBffirst)
1179 expect_close = True;
1181 outsize = set_message(outbuf,1,3,True);
1182 maxentries = SVAL(inbuf,smb_vwv0);
1183 dirtype = SVAL(inbuf,smb_vwv1);
1184 p = smb_buf(inbuf) + 1;
1185 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1187 status_len = SVAL(p, 0);
1190 /* dirtype &= ~aDIR; */
1192 if (status_len == 0)
1194 SMB_STRUCT_STAT sbuf;
1197 pstrcpy(directory,path);
1199 unix_convert(directory,conn,0,&bad_path,&sbuf);
1202 if (!check_name(directory,conn))
1205 p = strrchr_m(dir2,'/');
1217 p = strrchr_m(directory,'/');
1223 if (strlen(directory) == 0)
1224 pstrcpy(directory,"./");
1225 memset((char *)status,'\0',21);
1226 CVAL(status,0) = dirtype;
1230 memcpy(status,p,21);
1231 dirtype = CVAL(status,0) & 0x1F;
1232 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1235 string_set(&conn->dirpath,dptr_path(dptr_num));
1236 fstrcpy(mask, dptr_wcard(dptr_num));
1241 p = smb_buf(outbuf) + 3;
1245 if (status_len == 0)
1247 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1252 if((errno == ENOENT) && bad_path)
1254 unix_ERR_class = ERRDOS;
1255 unix_ERR_code = ERRbadpath;
1257 END_PROFILE(SMBsearch);
1258 return (UNIXERROR(ERRDOS,ERRnofids));
1260 END_PROFILE(SMBsearch);
1261 return(ERROR(ERRDOS,ERRnofids));
1263 dptr_set_wcard(dptr_num, strdup(mask));
1266 DEBUG(4,("dptr_num is %d\n",dptr_num));
1270 if ((dirtype&0x1F) == aVOLID)
1272 memcpy(p,status,21);
1273 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1274 dptr_fill(p+12,dptr_num);
1275 if (dptr_zero(p+12) && (status_len==0))
1279 p += DIR_STRUCT_SIZE;
1283 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1284 conn->dirpath,lp_dontdescend(SNUM(conn))));
1285 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1286 check_descend = True;
1288 for (i=numentries;(i<maxentries) && !finished;i++)
1291 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1294 memcpy(p,status,21);
1295 make_dir_struct(p,mask,fname,size,mode,date);
1296 dptr_fill(p+12,dptr_num);
1299 p += DIR_STRUCT_SIZE;
1308 if (numentries == 0 || !ok)
1310 CVAL(outbuf,smb_rcls) = ERRDOS;
1311 SSVAL(outbuf,smb_err,ERRnofiles);
1312 dptr_close(&dptr_num);
1315 /* If we were called as SMBffirst with smb_search_id == NULL
1316 and no entries were found then return error and close dirptr
1319 if(ok && expect_close && numentries == 0 && status_len == 0)
1321 CVAL(outbuf,smb_rcls) = ERRDOS;
1322 SSVAL(outbuf,smb_err,ERRnofiles);
1323 /* Also close the dptr - we know it's gone */
1324 dptr_close(&dptr_num);
1327 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1328 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1329 dptr_close(&dptr_num);
1331 SSVAL(outbuf,smb_vwv0,numentries);
1332 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1333 CVAL(smb_buf(outbuf),0) = 5;
1334 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1336 if (Protocol >= PROTOCOL_NT1) {
1337 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1340 outsize += DIR_STRUCT_SIZE*numentries;
1341 smb_setlen(outbuf,outsize - 4);
1343 if ((! *directory) && dptr_path(dptr_num))
1344 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1346 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1347 smb_fn_name(CVAL(inbuf,smb_com)),
1348 mask, directory, dirtype, numentries, maxentries ) );
1350 END_PROFILE(SMBsearch);
1355 /****************************************************************************
1356 reply to a fclose (stop directory search)
1357 ****************************************************************************/
1358 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1367 START_PROFILE(SMBfclose);
1369 outsize = set_message(outbuf,1,0,True);
1370 p = smb_buf(inbuf) + 1;
1371 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1373 status_len = SVAL(p,0);
1376 if (status_len == 0) {
1377 END_PROFILE(SMBfclose);
1378 return(ERROR(ERRSRV,ERRsrverror));
1381 memcpy(status,p,21);
1383 if(dptr_fetch(status+12,&dptr_num)) {
1384 /* Close the dptr - we know it's gone */
1385 dptr_close(&dptr_num);
1388 SSVAL(outbuf,smb_vwv0,0);
1390 DEBUG(3,("search close\n"));
1392 END_PROFILE(SMBfclose);
1397 /****************************************************************************
1399 ****************************************************************************/
1401 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1411 SMB_STRUCT_STAT sbuf;
1412 BOOL bad_path = False;
1414 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1415 START_PROFILE(SMBopen);
1417 share_mode = SVAL(inbuf,smb_vwv0);
1419 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1421 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1423 unix_convert(fname,conn,0,&bad_path,&sbuf);
1425 unixmode = unix_mode(conn,aARCH,fname);
1427 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1428 unixmode, oplock_request,&rmode,NULL);
1432 if((errno == ENOENT) && bad_path)
1434 unix_ERR_class = ERRDOS;
1435 unix_ERR_code = ERRbadpath;
1437 END_PROFILE(SMBopen);
1438 return(UNIXERROR(ERRDOS,ERRnoaccess));
1441 size = sbuf.st_size;
1442 fmode = dos_mode(conn,fname,&sbuf);
1443 mtime = sbuf.st_mtime;
1446 DEBUG(3,("attempt to open a directory %s\n",fname));
1447 close_file(fsp,False);
1448 END_PROFILE(SMBopen);
1449 return(ERROR(ERRDOS,ERRnoaccess));
1452 outsize = set_message(outbuf,7,0,True);
1453 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1454 SSVAL(outbuf,smb_vwv1,fmode);
1455 if(lp_dos_filetime_resolution(SNUM(conn)) )
1456 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1458 put_dos_date3(outbuf,smb_vwv2,mtime);
1459 SIVAL(outbuf,smb_vwv4,(uint32)size);
1460 SSVAL(outbuf,smb_vwv6,rmode);
1462 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1463 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1466 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1467 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1468 END_PROFILE(SMBopen);
1473 /****************************************************************************
1474 reply to an open and X
1475 ****************************************************************************/
1476 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1479 int smb_mode = SVAL(inbuf,smb_vwv3);
1480 int smb_attr = SVAL(inbuf,smb_vwv5);
1481 /* Breakout the oplock request bits so we can set the
1482 reply bits separately. */
1483 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1484 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1485 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1487 int open_flags = SVAL(inbuf,smb_vwv2);
1488 int smb_sattr = SVAL(inbuf,smb_vwv4);
1489 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1491 int smb_ofun = SVAL(inbuf,smb_vwv8);
1494 int fmode=0,mtime=0,rmode=0;
1495 SMB_STRUCT_STAT sbuf;
1497 BOOL bad_path = False;
1499 START_PROFILE(SMBopenX);
1501 /* If it's an IPC, pass off the pipe handler. */
1503 if (lp_nt_pipe_support()) {
1504 END_PROFILE(SMBopenX);
1505 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1507 END_PROFILE(SMBopenX);
1508 return (ERROR(ERRSRV,ERRaccess));
1512 /* XXXX we need to handle passed times, sattr and flags */
1513 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1515 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1517 unix_convert(fname,conn,0,&bad_path,&sbuf);
1519 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1521 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1522 oplock_request, &rmode,&smb_action);
1526 if((errno == ENOENT) && bad_path)
1528 unix_ERR_class = ERRDOS;
1529 unix_ERR_code = ERRbadpath;
1531 END_PROFILE(SMBopenX);
1532 return(UNIXERROR(ERRDOS,ERRnoaccess));
1535 size = sbuf.st_size;
1536 fmode = dos_mode(conn,fname,&sbuf);
1537 mtime = sbuf.st_mtime;
1539 close_file(fsp,False);
1540 END_PROFILE(SMBopenX);
1541 return(ERROR(ERRDOS,ERRnoaccess));
1544 /* If the caller set the extended oplock request bit
1545 and we granted one (by whatever means) - set the
1546 correct bit for extended oplock reply.
1549 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1550 smb_action |= EXTENDED_OPLOCK_GRANTED;
1553 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1554 smb_action |= EXTENDED_OPLOCK_GRANTED;
1557 /* If the caller set the core oplock request bit
1558 and we granted one (by whatever means) - set the
1559 correct bit for core oplock reply.
1562 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1563 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1566 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1567 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1570 set_message(outbuf,15,0,True);
1571 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1572 SSVAL(outbuf,smb_vwv3,fmode);
1573 if(lp_dos_filetime_resolution(SNUM(conn)) )
1574 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1576 put_dos_date3(outbuf,smb_vwv4,mtime);
1577 SIVAL(outbuf,smb_vwv6,(uint32)size);
1578 SSVAL(outbuf,smb_vwv8,rmode);
1579 SSVAL(outbuf,smb_vwv11,smb_action);
1581 END_PROFILE(SMBopenX);
1582 return chain_reply(inbuf,outbuf,length,bufsize);
1586 /****************************************************************************
1587 reply to a SMBulogoffX
1588 ****************************************************************************/
1589 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1591 uint16 vuid = SVAL(inbuf,smb_uid);
1592 user_struct *vuser = get_valid_user_struct(vuid);
1593 START_PROFILE(SMBulogoffX);
1596 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1599 /* in user level security we are supposed to close any files
1600 open by this user */
1601 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1602 file_close_user(vuid);
1605 invalidate_vuid(vuid);
1607 set_message(outbuf,2,0,True);
1609 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1611 END_PROFILE(SMBulogoffX);
1612 return chain_reply(inbuf,outbuf,length,bufsize);
1616 /****************************************************************************
1617 reply to a mknew or a create
1618 ****************************************************************************/
1619 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1627 BOOL bad_path = False;
1629 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1630 SMB_STRUCT_STAT sbuf;
1631 START_PROFILE(SMBcreate);
1633 com = SVAL(inbuf,smb_com);
1635 createmode = SVAL(inbuf,smb_vwv0);
1636 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1638 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1640 unix_convert(fname,conn,0,&bad_path,&sbuf);
1642 if (createmode & aVOLID) {
1643 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1646 unixmode = unix_mode(conn,createmode,fname);
1650 /* We should fail if file exists. */
1651 ofun = FILE_CREATE_IF_NOT_EXIST;
1655 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1656 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1659 /* Open file in dos compatibility share mode. */
1660 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1661 ofun, unixmode, oplock_request, NULL, NULL);
1665 if((errno == ENOENT) && bad_path)
1667 unix_ERR_class = ERRDOS;
1668 unix_ERR_code = ERRbadpath;
1670 END_PROFILE(SMBcreate);
1671 return(UNIXERROR(ERRDOS,ERRnoaccess));
1674 outsize = set_message(outbuf,1,0,True);
1675 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1677 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1678 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1681 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1682 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1684 DEBUG( 2, ( "new file %s\n", fname ) );
1685 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1686 fname, fsp->fd, createmode, (int)unixmode ) );
1688 END_PROFILE(SMBcreate);
1693 /****************************************************************************
1694 reply to a create temporary file
1695 ****************************************************************************/
1696 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1702 BOOL bad_path = False;
1704 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1706 SMB_STRUCT_STAT sbuf;
1709 START_PROFILE(SMBctemp);
1711 createmode = SVAL(inbuf,smb_vwv0);
1712 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1713 pstrcat(fname,"/TMXXXXXX");
1715 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1717 unix_convert(fname,conn,0,&bad_path,&sbuf);
1719 unixmode = unix_mode(conn,createmode,fname);
1721 tmpfd = smb_mkstemp(fname);
1723 END_PROFILE(SMBctemp);
1724 return(UNIXERROR(ERRDOS,ERRnoaccess));
1727 vfs_stat(conn,fname,&sbuf);
1729 /* Open file in dos compatibility share mode. */
1730 /* We should fail if file does not exist. */
1731 fsp = open_file_shared(conn,fname,&sbuf,
1732 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1733 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1734 unixmode, oplock_request, NULL, NULL);
1736 /* close fd from smb_mkstemp() */
1741 if((errno == ENOENT) && bad_path)
1743 unix_ERR_class = ERRDOS;
1744 unix_ERR_code = ERRbadpath;
1746 END_PROFILE(SMBctemp);
1747 return(UNIXERROR(ERRDOS,ERRnoaccess));
1750 outsize = set_message(outbuf,1,0,True);
1751 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1752 CVAL(smb_buf(outbuf),0) = 4;
1753 p = smb_buf(outbuf) + 1;
1754 p += srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1755 set_message_end(outbuf, p);
1757 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1758 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1761 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1762 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1764 DEBUG( 2, ( "created temp file %s\n", fname ) );
1765 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1766 fname, fsp->fd, createmode, (int)unixmode ) );
1768 END_PROFILE(SMBctemp);
1773 /*******************************************************************
1774 check if a user is allowed to delete a file
1775 ********************************************************************/
1776 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1778 SMB_STRUCT_STAT sbuf;
1781 if (!CAN_WRITE(conn)) return(False);
1783 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
1784 fmode = dos_mode(conn,fname,&sbuf);
1785 if (fmode & aDIR) return(False);
1786 if (!lp_delete_readonly(SNUM(conn))) {
1787 if (fmode & aRONLY) return(False);
1789 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1791 if (!check_file_sharing(conn,fname,False)) return(False);
1795 /****************************************************************************
1796 The guts of the unlink command, split out so it may be called by the NT SMB
1798 ****************************************************************************/
1800 int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
1801 int dirtype, char *name)
1807 int error = ERRnoaccess;
1810 BOOL bad_path = False;
1812 SMB_STRUCT_STAT sbuf;
1814 *directory = *mask = 0;
1816 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1818 p = strrchr_m(name,'/');
1820 pstrcpy(directory,"./");
1824 pstrcpy(directory,name);
1829 * We should only check the mangled cache
1830 * here if unix_convert failed. This means
1831 * that the path in 'mask' doesn't exist
1832 * on the file system and so we need to look
1833 * for a possible mangle. This patch from
1834 * Tine Smukavec <valentin.smukavec@hermes.si>.
1837 if (!rc && is_mangled(mask))
1838 check_mangled_cache( mask );
1840 has_wild = ms_has_wild(mask);
1843 pstrcat(directory,"/");
1844 pstrcat(directory,mask);
1845 if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory))
1848 exists = vfs_file_exist(conn,directory,&sbuf);
1850 void *dirptr = NULL;
1853 if (check_name(directory,conn))
1854 dirptr = OpenDir(conn, directory, True);
1856 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1857 the pattern matches against the long name, otherwise the short name
1858 We don't implement this yet XXXX
1865 if (strequal(mask,"????????.???"))
1868 while ((dname = ReadDirName(dirptr)))
1871 pstrcpy(fname,dname);
1873 if(!mask_match(fname, mask, case_sensitive)) continue;
1875 error = ERRnoaccess;
1876 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1877 if (!can_delete(fname,conn,dirtype)) continue;
1878 if (!vfs_unlink(conn,fname)) count++;
1879 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1887 return(ERROR(ERRDOS,error));
1889 if((errno == ENOENT) && bad_path) {
1890 unix_ERR_class = ERRDOS;
1891 unix_ERR_code = ERRbadpath;
1893 return(UNIXERROR(ERRDOS,error));
1900 /****************************************************************************
1902 ****************************************************************************/
1904 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1909 START_PROFILE(SMBunlink);
1911 dirtype = SVAL(inbuf,smb_vwv0);
1913 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1915 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1917 DEBUG(3,("reply_unlink : %s\n",name));
1919 outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
1923 * Win2k needs a changenotify request response before it will
1924 * update after a rename..
1927 process_pending_change_notify_queue((time_t)0);
1929 outsize = set_message(outbuf,0,0,True);
1932 END_PROFILE(SMBunlink);
1937 /****************************************************************************
1938 reply to a readbraw (core+ protocol)
1939 ****************************************************************************/
1941 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1943 size_t maxcount,mincount;
1946 char *header = outbuf;
1949 START_PROFILE(SMBreadbraw);
1952 * Special check if an oplock break has been issued
1953 * and the readraw request croses on the wire, we must
1954 * return a zero length response here.
1957 if(global_oplock_break)
1959 _smb_setlen(header,0);
1960 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1961 DEBUG(5,("readbraw - oplock break finished\n"));
1962 END_PROFILE(SMBreadbraw);
1966 fsp = file_fsp(inbuf,smb_vwv0);
1968 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1970 * fsp could be NULL here so use the value from the packet. JRA.
1972 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1973 _smb_setlen(header,0);
1974 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
1975 END_PROFILE(SMBreadbraw);
1979 CHECK_FSP(fsp,conn);
1981 flush_write_cache(fsp, READRAW_FLUSH);
1983 startpos = IVAL(inbuf,smb_vwv1);
1984 if(CVAL(inbuf,smb_wct) == 10) {
1986 * This is a large offset (64 bit) read.
1988 #ifdef LARGE_SMB_OFF_T
1990 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1992 #else /* !LARGE_SMB_OFF_T */
1995 * Ensure we haven't been sent a >32 bit offset.
1998 if(IVAL(inbuf,smb_vwv8) != 0) {
1999 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2000 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2001 _smb_setlen(header,0);
2002 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2003 END_PROFILE(SMBreadbraw);
2007 #endif /* LARGE_SMB_OFF_T */
2010 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2011 (double)startpos ));
2012 _smb_setlen(header,0);
2013 transfer_file(0,smbd_server_fd(),(SMB_OFF_T)0,header,4,0);
2014 END_PROFILE(SMBreadbraw);
2018 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2019 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2021 /* ensure we don't overrun the packet size */
2022 maxcount = MIN(65535,maxcount);
2023 maxcount = MAX(mincount,maxcount);
2025 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False))
2027 SMB_OFF_T size = fsp->size;
2028 SMB_OFF_T sizeneeded = startpos + maxcount;
2030 if (size < sizeneeded)
2033 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
2035 if (!fsp->can_write)
2039 nread = MIN(maxcount,(size - startpos));
2042 if (nread < mincount)
2045 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2046 fsp->fnum, (double)startpos,
2047 (int)maxcount, (int)mincount, (int)nread ) );
2051 BOOL seek_fail = False;
2053 _smb_setlen(header,nread);
2055 if ((nread-predict) > 0) {
2056 if(conn->vfs_ops.seek(fsp,fsp->fd,startpos + predict) == -1) {
2057 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
2064 ret = (ssize_t)vfs_transfer_file(-1, fsp, fsp->fd, Client, NULL,
2065 (SMB_OFF_T)(nread-predict),header,4+predict,
2070 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2071 fsp->fsp_name,startpos,nread,ret));
2073 #else /* UNSAFE_READRAW */
2074 ret = read_file(fsp,header+4,startpos,nread);
2075 if (ret < mincount) ret = 0;
2077 _smb_setlen(header,ret);
2078 transfer_file(0,smbd_server_fd(),0,header,4+ret,0);
2079 #endif /* UNSAFE_READRAW */
2081 DEBUG(5,("readbraw finished\n"));
2082 END_PROFILE(SMBreadbraw);
2087 /****************************************************************************
2088 reply to a lockread (core+ protocol)
2089 ****************************************************************************/
2090 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2099 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2100 START_PROFILE(SMBlockread);
2102 CHECK_FSP(fsp,conn);
2106 release_level_2_oplocks_on_change(fsp);
2108 numtoread = SVAL(inbuf,smb_vwv1);
2109 startpos = IVAL(inbuf,smb_vwv2);
2111 outsize = set_message(outbuf,5,3,True);
2112 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2113 data = smb_buf(outbuf) + 3;
2116 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2117 * protocol request that predates the read/write lock concept.
2118 * Thus instead of asking for a read lock here we need to ask
2119 * for a write lock. JRA.
2122 if(!do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &eclass, &ecode)) {
2123 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2125 * A blocking lock was requested. Package up
2126 * this smb into a queued request and push it
2127 * onto the blocking lock queue.
2129 if(push_blocking_lock_request(inbuf, length, -1, 0))
2130 END_PROFILE(SMBlockread);
2133 END_PROFILE(SMBlockread);
2134 return (ERROR(eclass,ecode));
2137 nread = read_file(fsp,data,startpos,numtoread);
2140 END_PROFILE(SMBlockread);
2141 return(UNIXERROR(ERRDOS,ERRnoaccess));
2145 SSVAL(outbuf,smb_vwv0,nread);
2146 SSVAL(outbuf,smb_vwv5,nread+3);
2147 SSVAL(smb_buf(outbuf),1,nread);
2149 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
2150 fsp->fnum, (int)numtoread, (int)nread ) );
2152 END_PROFILE(SMBlockread);
2157 /****************************************************************************
2159 ****************************************************************************/
2161 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2168 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2169 START_PROFILE(SMBread);
2171 CHECK_FSP(fsp,conn);
2175 numtoread = SVAL(inbuf,smb_vwv1);
2176 startpos = IVAL(inbuf,smb_vwv2);
2178 outsize = set_message(outbuf,5,3,True);
2179 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2180 data = smb_buf(outbuf) + 3;
2182 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2183 END_PROFILE(SMBread);
2184 return(ERROR(ERRDOS,ERRlock));
2188 nread = read_file(fsp,data,startpos,numtoread);
2191 END_PROFILE(SMBread);
2192 return(UNIXERROR(ERRDOS,ERRnoaccess));
2196 SSVAL(outbuf,smb_vwv0,nread);
2197 SSVAL(outbuf,smb_vwv5,nread+3);
2198 CVAL(smb_buf(outbuf),0) = 1;
2199 SSVAL(smb_buf(outbuf),1,nread);
2201 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2202 fsp->fnum, (int)numtoread, (int)nread ) );
2204 END_PROFILE(SMBread);
2209 /****************************************************************************
2210 reply to a read and X
2211 ****************************************************************************/
2212 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2214 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2215 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2216 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2217 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2220 START_PROFILE(SMBreadX);
2222 /* If it's an IPC, pass off the pipe handler. */
2224 END_PROFILE(SMBreadX);
2225 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2228 CHECK_FSP(fsp,conn);
2232 set_message(outbuf,12,0,True);
2233 data = smb_buf(outbuf);
2235 if(CVAL(inbuf,smb_wct) == 12) {
2236 #ifdef LARGE_SMB_OFF_T
2238 * This is a large offset (64 bit) read.
2240 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2242 #else /* !LARGE_SMB_OFF_T */
2245 * Ensure we haven't been sent a >32 bit offset.
2248 if(IVAL(inbuf,smb_vwv10) != 0) {
2249 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2250 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2251 END_PROFILE(SMBreadX);
2252 return(ERROR(ERRDOS,ERRbadaccess));
2255 #endif /* LARGE_SMB_OFF_T */
2259 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2260 END_PROFILE(SMBreadX);
2261 return(ERROR(ERRDOS,ERRlock));
2263 nread = read_file(fsp,data,startpos,smb_maxcnt);
2266 END_PROFILE(SMBreadX);
2267 return(UNIXERROR(ERRDOS,ERRnoaccess));
2270 SSVAL(outbuf,smb_vwv5,nread);
2271 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2272 SSVAL(smb_buf(outbuf),-2,nread);
2274 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2275 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2277 END_PROFILE(SMBreadX);
2278 return chain_reply(inbuf,outbuf,length,bufsize);
2281 /****************************************************************************
2282 reply to a writebraw (core+ or LANMAN1.0 protocol)
2283 ****************************************************************************/
2285 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2288 ssize_t total_written=0;
2289 size_t numtowrite=0;
2294 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2296 START_PROFILE(SMBwritebraw);
2298 CHECK_FSP(fsp,conn);
2302 tcount = IVAL(inbuf,smb_vwv1);
2303 startpos = IVAL(inbuf,smb_vwv3);
2304 write_through = BITSETW(inbuf+smb_vwv7,0);
2306 /* We have to deal with slightly different formats depending
2307 on whether we are using the core+ or lanman1.0 protocol */
2308 if(Protocol <= PROTOCOL_COREPLUS) {
2309 numtowrite = SVAL(smb_buf(inbuf),-2);
2310 data = smb_buf(inbuf);
2312 numtowrite = SVAL(inbuf,smb_vwv10);
2313 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2316 /* force the error type */
2317 CVAL(inbuf,smb_com) = SMBwritec;
2318 CVAL(outbuf,smb_com) = SMBwritec;
2320 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2321 END_PROFILE(SMBwritebraw);
2322 return(ERROR(ERRDOS,ERRlock));
2326 nwritten = write_file(fsp,data,startpos,numtowrite);
2328 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2329 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2331 if (nwritten < numtowrite) {
2332 END_PROFILE(SMBwritebraw);
2333 return(UNIXERROR(ERRHRD,ERRdiskfull));
2336 total_written = nwritten;
2338 /* Return a message to the redirector to tell it
2339 to send more bytes */
2340 CVAL(outbuf,smb_com) = SMBwritebraw;
2341 SSVALS(outbuf,smb_vwv0,-1);
2342 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2343 if (!send_smb(smbd_server_fd(),outbuf))
2344 exit_server("reply_writebraw: send_smb failed.\n");
2346 /* Now read the raw data into the buffer and write it */
2347 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2348 exit_server("secondary writebraw failed");
2351 /* Even though this is not an smb message, smb_len
2352 returns the generic length of an smb message */
2353 numtowrite = smb_len(inbuf);
2355 if (tcount > nwritten+numtowrite) {
2356 DEBUG(3,("Client overestimated the write %d %d %d\n",
2357 (int)tcount,(int)nwritten,(int)numtowrite));
2360 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2361 (SMB_OFF_T)numtowrite,NULL,0,
2363 total_written += nwritten;
2365 /* Set up outbuf to return the correct return */
2366 outsize = set_message(outbuf,1,0,True);
2367 CVAL(outbuf,smb_com) = SMBwritec;
2368 SSVAL(outbuf,smb_vwv0,total_written);
2370 if (nwritten < (ssize_t)numtowrite) {
2371 CVAL(outbuf,smb_rcls) = ERRHRD;
2372 SSVAL(outbuf,smb_err,ERRdiskfull);
2375 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2376 lp_strict_sync(SNUM(conn)))
2377 sync_file(conn,fsp);
2379 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2380 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2382 /* we won't return a status if write through is not selected - this
2383 follows what WfWg does */
2384 END_PROFILE(SMBwritebraw);
2385 if (!write_through && total_written==tcount) {
2387 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2388 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2390 if (!send_keepalive(smbd_server_fd()))
2391 exit_server("reply_writebraw: send of keepalive failed");
2398 /****************************************************************************
2399 reply to a writeunlock (core+)
2400 ****************************************************************************/
2402 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2404 ssize_t nwritten = -1;
2410 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2412 START_PROFILE(SMBwriteunlock);
2414 CHECK_FSP(fsp,conn);
2418 numtowrite = SVAL(inbuf,smb_vwv1);
2419 startpos = IVAL(inbuf,smb_vwv2);
2420 data = smb_buf(inbuf) + 3;
2422 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2423 END_PROFILE(SMBwriteunlock);
2424 return(ERROR(ERRDOS,ERRlock));
2427 /* The special X/Open SMB protocol handling of
2428 zero length writes is *NOT* done for
2433 nwritten = write_file(fsp,data,startpos,numtowrite);
2435 if (lp_syncalways(SNUM(conn)))
2436 sync_file(conn,fsp);
2438 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2439 END_PROFILE(SMBwriteunlock);
2440 return(UNIXERROR(ERRDOS,ERRnoaccess));
2443 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, (SMB_BIG_UINT)startpos, &eclass, &ecode)) {
2444 END_PROFILE(SMBwriteunlock);
2445 return(ERROR(eclass,ecode));
2448 outsize = set_message(outbuf,1,0,True);
2450 SSVAL(outbuf,smb_vwv0,nwritten);
2452 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2453 fsp->fnum, (int)numtowrite, (int)nwritten ) );
2455 END_PROFILE(SMBwriteunlock);
2459 /****************************************************************************
2460 Return correct error for space allocation fail.
2461 ****************************************************************************/
2463 int allocate_space_error(char *inbuf,char *outbuf, int errno_val)
2466 if (!(global_client_caps & CAP_STATUS32))
2467 return (UNIXERROR(ERRHRD,ERRdiskfull));
2469 /* Use more specific WNT/W2K error codes. */
2471 if (errno_val == ENOSPC || errno_val == EDQUOT) {
2473 if (errno_val == ENOSPC) {
2475 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
2476 return(ERROR(0,NT_STATUS_DISK_FULL));
2479 return (UNIXERROR(ERRHRD,ERRdiskfull));
2482 /****************************************************************************
2484 ****************************************************************************/
2486 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2489 ssize_t nwritten = -1;
2492 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2494 START_PROFILE(SMBwrite);
2496 /* If it's an IPC, pass off the pipe handler. */
2498 END_PROFILE(SMBwrite);
2499 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2502 CHECK_FSP(fsp,conn);
2506 numtowrite = SVAL(inbuf,smb_vwv1);
2507 startpos = IVAL(inbuf,smb_vwv2);
2508 data = smb_buf(inbuf) + 3;
2510 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2511 END_PROFILE(SMBwrite);
2512 return(ERROR(ERRDOS,ERRlock));
2515 /* X/Open SMB protocol says that if smb_vwv1 is
2516 zero then the file size should be extended or
2517 truncated to the size given in smb_vwv[2-3] */
2518 if(numtowrite == 0) {
2519 /* This is actually an allocate call, not set EOF. JRA */
2520 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2522 int ret = allocate_space_error(inbuf, outbuf, errno);
2523 END_PROFILE(SMBwrite);
2527 nwritten = write_file(fsp,data,startpos,numtowrite);
2529 if (lp_syncalways(SNUM(conn)))
2530 sync_file(conn,fsp);
2532 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2533 END_PROFILE(SMBwrite);
2534 return(UNIXERROR(ERRDOS,ERRnoaccess));
2537 outsize = set_message(outbuf,1,0,True);
2539 SSVAL(outbuf,smb_vwv0,nwritten);
2541 if (nwritten < (ssize_t)numtowrite) {
2542 CVAL(outbuf,smb_rcls) = ERRHRD;
2543 SSVAL(outbuf,smb_err,ERRdiskfull);
2546 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2547 fsp->fnum, (int)numtowrite, (int)nwritten));
2549 END_PROFILE(SMBwrite);
2554 /****************************************************************************
2555 reply to a write and X
2556 ****************************************************************************/
2557 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2559 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2560 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2561 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2562 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2563 ssize_t nwritten = -1;
2564 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2565 unsigned int smblen = smb_len(inbuf);
2567 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2568 START_PROFILE(SMBwriteX);
2570 /* If it's an IPC, pass off the pipe handler. */
2572 END_PROFILE(SMBwriteX);
2573 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2576 CHECK_FSP(fsp,conn);
2580 /* Deal with possible LARGE_WRITEX */
2582 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2584 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2585 END_PROFILE(SMBwriteX);
2586 return(ERROR(ERRDOS,ERRbadmem));
2589 data = smb_base(inbuf) + smb_doff;
2591 if(CVAL(inbuf,smb_wct) == 14) {
2592 #ifdef LARGE_SMB_OFF_T
2594 * This is a large offset (64 bit) write.
2596 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2598 #else /* !LARGE_SMB_OFF_T */
2601 * Ensure we haven't been sent a >32 bit offset.
2604 if(IVAL(inbuf,smb_vwv12) != 0) {
2605 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2606 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2607 END_PROFILE(SMBwriteX);
2608 return(ERROR(ERRDOS,ERRbadaccess));
2611 #endif /* LARGE_SMB_OFF_T */
2614 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2615 END_PROFILE(SMBwriteX);
2616 return(ERROR(ERRDOS,ERRlock));
2619 /* X/Open SMB protocol says that, unlike SMBwrite
2620 if the length is zero then NO truncation is
2621 done, just a write of zero. To truncate a file,
2626 nwritten = write_file(fsp,data,startpos,numtowrite);
2628 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2629 END_PROFILE(SMBwriteX);
2630 return(UNIXERROR(ERRDOS,ERRnoaccess));
2633 set_message(outbuf,6,0,True);
2635 SSVAL(outbuf,smb_vwv2,nwritten);
2637 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2639 if (nwritten < (ssize_t)numtowrite) {
2640 CVAL(outbuf,smb_rcls) = ERRHRD;
2641 SSVAL(outbuf,smb_err,ERRdiskfull);
2644 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2645 fsp->fnum, (int)numtowrite, (int)nwritten));
2647 if (lp_syncalways(SNUM(conn)) || write_through)
2648 sync_file(conn,fsp);
2650 END_PROFILE(SMBwriteX);
2651 return chain_reply(inbuf,outbuf,length,bufsize);
2655 /****************************************************************************
2657 ****************************************************************************/
2659 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2665 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2666 START_PROFILE(SMBlseek);
2668 CHECK_FSP(fsp,conn);
2671 flush_write_cache(fsp, SEEK_FLUSH);
2673 mode = SVAL(inbuf,smb_vwv1) & 3;
2674 startpos = IVALS(inbuf,smb_vwv2);
2677 case 0: umode = SEEK_SET; break;
2678 case 1: umode = SEEK_CUR; break;
2679 case 2: umode = SEEK_END; break;
2681 umode = SEEK_SET; break;
2684 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2686 * Check for the special case where a seek before the start
2687 * of the file sets the offset to zero. Added in the CIFS spec,
2691 if(errno == EINVAL) {
2692 SMB_OFF_T current_pos = startpos;
2694 if(umode == SEEK_CUR) {
2696 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2697 END_PROFILE(SMBlseek);
2698 return(UNIXERROR(ERRDOS,ERRnoaccess));
2701 current_pos += startpos;
2703 } else if (umode == SEEK_END) {
2705 SMB_STRUCT_STAT sbuf;
2707 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2708 END_PROFILE(SMBlseek);
2709 return(UNIXERROR(ERRDOS,ERRnoaccess));
2712 current_pos += sbuf.st_size;
2716 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2720 END_PROFILE(SMBlseek);
2721 return(UNIXERROR(ERRDOS,ERRnoaccess));
2727 outsize = set_message(outbuf,2,0,True);
2728 SIVAL(outbuf,smb_vwv0,res);
2730 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2731 fsp->fnum, (double)startpos, (double)res, mode));
2733 END_PROFILE(SMBlseek);
2737 /****************************************************************************
2739 ****************************************************************************/
2741 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2743 int outsize = set_message(outbuf,0,0,True);
2744 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2745 START_PROFILE(SMBflush);
2747 CHECK_FSP(fsp,conn);
2753 file_sync_all(conn);
2755 sync_file(conn,fsp);
2758 DEBUG(3,("flush\n"));
2759 END_PROFILE(SMBflush);
2764 /****************************************************************************
2766 ****************************************************************************/
2767 int reply_exit(connection_struct *conn,
2768 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2771 START_PROFILE(SMBexit);
2772 outsize = set_message(outbuf,0,0,True);
2774 DEBUG(3,("exit\n"));
2776 END_PROFILE(SMBexit);
2781 /****************************************************************************
2782 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2783 ****************************************************************************/
2784 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2789 int32 eclass = 0, err = 0;
2790 files_struct *fsp = NULL;
2791 START_PROFILE(SMBclose);
2793 outsize = set_message(outbuf,0,0,True);
2795 /* If it's an IPC, pass off to the pipe handler. */
2797 END_PROFILE(SMBclose);
2798 return reply_pipe_close(conn, inbuf,outbuf);
2801 fsp = file_fsp(inbuf,smb_vwv0);
2804 * We can only use CHECK_FSP if we know it's not a directory.
2807 if(!fsp || (fsp->conn != conn)) {
2808 END_PROFILE(SMBclose);
2809 return(ERROR(ERRDOS,ERRbadfid));
2812 if(HAS_CACHED_ERROR(fsp)) {
2813 eclass = fsp->wbmpx_ptr->wr_errclass;
2814 err = fsp->wbmpx_ptr->wr_error;
2817 if(fsp->is_directory || fsp->stat_open) {
2819 * Special case - close NT SMB directory or stat file
2822 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2823 close_file(fsp,True);
2826 * Close ordinary file.
2831 * If there was a modify time outstanding,
2832 * try and set it here.
2834 if(fsp->pending_modtime)
2835 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2838 * Now take care of any time sent in the close.
2840 mtime = make_unix_date3(inbuf+smb_vwv1);
2842 /* try and set the date */
2843 set_filetime(conn, fsp->fsp_name,mtime);
2845 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2847 conn->num_files_open));
2850 * close_file() returns the unix errno if an error
2851 * was detected on close - normally this is due to
2852 * a disk full error. If not then it was probably an I/O error.
2855 if((close_err = close_file(fsp,True)) != 0) {
2857 END_PROFILE(SMBclose);
2858 return (UNIXERROR(ERRHRD,ERRgeneral));
2862 /* We have a cached error */
2864 END_PROFILE(SMBclose);
2865 return(ERROR(eclass,err));
2868 END_PROFILE(SMBclose);
2873 /****************************************************************************
2874 reply to a writeclose (Core+ protocol)
2875 ****************************************************************************/
2877 int reply_writeclose(connection_struct *conn,
2878 char *inbuf,char *outbuf, int size, int dum_buffsize)
2881 ssize_t nwritten = -1;
2887 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2888 START_PROFILE(SMBwriteclose);
2890 CHECK_FSP(fsp,conn);
2894 numtowrite = SVAL(inbuf,smb_vwv1);
2895 startpos = IVAL(inbuf,smb_vwv2);
2896 mtime = make_unix_date3(inbuf+smb_vwv4);
2897 data = smb_buf(inbuf) + 1;
2899 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2900 END_PROFILE(SMBwriteclose);
2901 return(ERROR(ERRDOS,ERRlock));
2904 nwritten = write_file(fsp,data,startpos,numtowrite);
2906 set_filetime(conn, fsp->fsp_name,mtime);
2908 close_err = close_file(fsp,True);
2910 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2911 fsp->fnum, (int)numtowrite, (int)nwritten,
2912 conn->num_files_open));
2914 if (nwritten <= 0) {
2915 END_PROFILE(SMBwriteclose);
2916 return(UNIXERROR(ERRDOS,ERRnoaccess));
2919 if(close_err != 0) {
2921 END_PROFILE(SMBwriteclose);
2922 return(UNIXERROR(ERRHRD,ERRgeneral));
2925 outsize = set_message(outbuf,1,0,True);
2927 SSVAL(outbuf,smb_vwv0,nwritten);
2928 END_PROFILE(SMBwriteclose);
2933 /****************************************************************************
2935 ****************************************************************************/
2936 int reply_lock(connection_struct *conn,
2937 char *inbuf,char *outbuf, int length, int dum_buffsize)
2939 int outsize = set_message(outbuf,0,0,True);
2940 SMB_BIG_UINT count,offset;
2943 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2944 START_PROFILE(SMBlock);
2946 CHECK_FSP(fsp,conn);
2949 release_level_2_oplocks_on_change(fsp);
2951 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2952 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2954 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2955 fsp->fd, fsp->fnum, (double)offset, (double)count));
2957 if (!do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &eclass, &ecode)) {
2958 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2960 * A blocking lock was requested. Package up
2961 * this smb into a queued request and push it
2962 * onto the blocking lock queue.
2964 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2965 END_PROFILE(SMBlock);
2969 END_PROFILE(SMBlock);
2970 return (ERROR(eclass,ecode));
2973 END_PROFILE(SMBlock);
2978 /****************************************************************************
2980 ****************************************************************************/
2981 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2983 int outsize = set_message(outbuf,0,0,True);
2984 SMB_BIG_UINT count,offset;
2987 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2988 START_PROFILE(SMBunlock);
2990 CHECK_FSP(fsp,conn);
2993 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2994 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2996 if(!do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, &eclass, &ecode)) {
2997 END_PROFILE(SMBunlock);
2998 return (ERROR(eclass,ecode));
3001 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3002 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3004 END_PROFILE(SMBunlock);
3009 /****************************************************************************
3011 ****************************************************************************/
3012 int reply_tdis(connection_struct *conn,
3013 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3015 int outsize = set_message(outbuf,0,0,True);
3017 START_PROFILE(SMBtdis);
3019 vuid = SVAL(inbuf,smb_uid);
3022 DEBUG(4,("Invalid connection in tdis\n"));
3023 END_PROFILE(SMBtdis);
3024 return(ERROR(ERRSRV,ERRinvnid));
3029 close_cnum(conn,vuid);
3031 END_PROFILE(SMBtdis);
3037 /****************************************************************************
3039 ****************************************************************************/
3040 int reply_echo(connection_struct *conn,
3041 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3043 int smb_reverb = SVAL(inbuf,smb_vwv0);
3045 unsigned int data_len = smb_buflen(inbuf);
3046 int outsize = set_message(outbuf,1,data_len,True);
3047 START_PROFILE(SMBecho);
3049 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3051 /* copy any incoming data back out */
3053 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3055 if (smb_reverb > 100) {
3056 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3060 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3061 SSVAL(outbuf,smb_vwv0,seq_num);
3063 smb_setlen(outbuf,outsize - 4);
3065 if (!send_smb(smbd_server_fd(),outbuf))
3066 exit_server("reply_echo: send_smb failed.\n");
3069 DEBUG(3,("echo %d times\n", smb_reverb));
3073 END_PROFILE(SMBecho);
3078 /****************************************************************************
3079 reply to a printopen
3080 ****************************************************************************/
3081 int reply_printopen(connection_struct *conn,
3082 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3086 START_PROFILE(SMBsplopen);
3088 if (!CAN_PRINT(conn)) {
3089 END_PROFILE(SMBsplopen);
3090 return(ERROR(ERRDOS,ERRnoaccess));
3093 /* Open for exclusive use, write only. */
3094 fsp = print_fsp_open(conn);
3097 END_PROFILE(SMBsplopen);
3098 return(UNIXERROR(ERRDOS,ERRnoaccess));
3101 outsize = set_message(outbuf,1,0,True);
3102 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3104 DEBUG(3,("openprint fd=%d fnum=%d\n",
3105 fsp->fd, fsp->fnum));
3107 END_PROFILE(SMBsplopen);
3112 /****************************************************************************
3113 reply to a printclose
3114 ****************************************************************************/
3115 int reply_printclose(connection_struct *conn,
3116 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3118 int outsize = set_message(outbuf,0,0,True);
3119 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3121 START_PROFILE(SMBsplclose);
3123 CHECK_FSP(fsp,conn);
3126 if (!CAN_PRINT(conn)) {
3127 END_PROFILE(SMBsplclose);
3128 return(ERROR(ERRDOS,ERRnoaccess));
3131 DEBUG(3,("printclose fd=%d fnum=%d\n",
3132 fsp->fd,fsp->fnum));
3134 close_err = close_file(fsp,True);
3136 if(close_err != 0) {
3138 END_PROFILE(SMBsplclose);
3139 return(UNIXERROR(ERRHRD,ERRgeneral));
3142 END_PROFILE(SMBsplclose);
3147 /****************************************************************************
3148 reply to a printqueue
3149 ****************************************************************************/
3150 int reply_printqueue(connection_struct *conn,
3151 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3153 int outsize = set_message(outbuf,2,3,True);
3154 int max_count = SVAL(inbuf,smb_vwv0);
3155 int start_index = SVAL(inbuf,smb_vwv1);
3156 START_PROFILE(SMBsplretq);
3158 /* we used to allow the client to get the cnum wrong, but that
3159 is really quite gross and only worked when there was only
3160 one printer - I think we should now only accept it if they
3161 get it right (tridge) */
3162 if (!CAN_PRINT(conn)) {
3163 END_PROFILE(SMBsplretq);
3164 return(ERROR(ERRDOS,ERRnoaccess));
3167 SSVAL(outbuf,smb_vwv0,0);
3168 SSVAL(outbuf,smb_vwv1,0);
3169 CVAL(smb_buf(outbuf),0) = 1;
3170 SSVAL(smb_buf(outbuf),1,0);
3172 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3173 start_index, max_count));
3176 print_queue_struct *queue = NULL;
3177 char *p = smb_buf(outbuf) + 3;
3178 int count = print_queue_status(SNUM(conn), &queue,NULL);
3179 int num_to_get = ABS(max_count);
3180 int first = (max_count>0?start_index:start_index+max_count+1);
3186 num_to_get = MIN(num_to_get,count-first);
3189 for (i=first;i<first+num_to_get;i++) {
3190 put_dos_date2(p,0,queue[i].time);
3191 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3192 SSVAL(p,5, queue[i].job);
3193 SIVAL(p,7,queue[i].size);
3195 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII);
3200 outsize = set_message(outbuf,2,28*count+3,False);
3201 SSVAL(outbuf,smb_vwv0,count);
3202 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3203 CVAL(smb_buf(outbuf),0) = 1;
3204 SSVAL(smb_buf(outbuf),1,28*count);
3207 if (queue) free(queue);
3209 DEBUG(3,("%d entries returned in queue\n",count));
3212 END_PROFILE(SMBsplretq);
3217 /****************************************************************************
3218 reply to a printwrite
3219 ****************************************************************************/
3220 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3223 int outsize = set_message(outbuf,0,0,True);
3225 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3226 START_PROFILE(SMBsplwr);
3228 if (!CAN_PRINT(conn)) {
3229 END_PROFILE(SMBsplwr);
3230 return(ERROR(ERRDOS,ERRnoaccess));
3233 CHECK_FSP(fsp,conn);
3237 numtowrite = SVAL(smb_buf(inbuf),1);
3238 data = smb_buf(inbuf) + 3;
3240 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3241 END_PROFILE(SMBsplwr);
3242 return(UNIXERROR(ERRDOS,ERRnoaccess));
3245 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3247 END_PROFILE(SMBsplwr);
3252 /****************************************************************************
3253 The guts of the mkdir command, split out so it may be called by the NT SMB
3255 ****************************************************************************/
3256 int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory)
3258 BOOL bad_path = False;
3259 SMB_STRUCT_STAT sbuf;
3262 unix_convert(directory,conn,0,&bad_path,&sbuf);
3264 if (check_name(directory, conn))
3265 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3269 if((errno == ENOENT) && bad_path)
3271 unix_ERR_class = ERRDOS;
3272 unix_ERR_code = ERRbadpath;
3274 return(UNIXERROR(ERRDOS,ERRnoaccess));
3280 /****************************************************************************
3282 ****************************************************************************/
3283 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3287 START_PROFILE(SMBmkdir);
3289 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3291 outsize=mkdir_internal(conn, inbuf, outbuf, directory);
3293 outsize = set_message(outbuf,0,0,True);
3295 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3297 END_PROFILE(SMBmkdir);
3301 /****************************************************************************
3302 Static function used by reply_rmdir to delete an entire directory
3304 ****************************************************************************/
3306 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3310 void *dirptr = OpenDir(NULL, directory, False);
3315 while((dname = ReadDirName(dirptr)))
3320 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3323 /* Construct the full name. */
3324 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3330 pstrcpy(fullname, directory);
3331 pstrcat(fullname, "/");
3332 pstrcat(fullname, dname);
3334 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3340 if(st.st_mode & S_IFDIR)
3342 if(recursive_rmdir(conn, fullname)!=0)
3347 if(vfs_rmdir(conn,fullname) != 0)
3353 else if(vfs_unlink(conn,fullname) != 0)
3363 /****************************************************************************
3364 The internals of the rmdir code - called elsewhere.
3365 ****************************************************************************/
3367 BOOL rmdir_internals(connection_struct *conn, char *directory)
3371 ok = (vfs_rmdir(conn,directory) == 0);
3372 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn)))
3375 * Check to see if the only thing in this directory are
3376 * vetoed files/directories. If so then delete them and
3377 * retry. If we fail to delete any of them (and we *don't*
3378 * do a recursive delete) then fail the rmdir.
3380 BOOL all_veto_files = True;
3382 void *dirptr = OpenDir(conn, directory, False);
3386 int dirpos = TellDir(dirptr);
3387 while ((dname = ReadDirName(dirptr)))
3389 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3391 if(!IS_VETO_PATH(conn, dname))
3393 all_veto_files = False;
3399 SeekDir(dirptr,dirpos);
3400 while ((dname = ReadDirName(dirptr)))
3405 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3408 /* Construct the full name. */
3409 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3414 pstrcpy(fullname, directory);
3415 pstrcat(fullname, "/");
3416 pstrcat(fullname, dname);
3418 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3420 if(st.st_mode & S_IFDIR)
3422 if(lp_recursive_veto_delete(SNUM(conn)))
3424 if(recursive_rmdir(conn, fullname) != 0)
3427 if(vfs_rmdir(conn,fullname) != 0)
3430 else if(vfs_unlink(conn,fullname) != 0)
3434 /* Retry the rmdir */
3435 ok = (vfs_rmdir(conn,directory) == 0);
3445 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n",
3446 directory,strerror(errno)));
3451 /****************************************************************************
3453 ****************************************************************************/
3455 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3460 BOOL bad_path = False;
3461 SMB_STRUCT_STAT sbuf;
3462 START_PROFILE(SMBrmdir);
3464 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3466 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3468 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3470 if (check_name(directory,conn))
3472 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3473 ok = rmdir_internals(conn, directory);
3478 if((errno == ENOENT) && bad_path)
3480 unix_ERR_class = ERRDOS;
3481 unix_ERR_code = ERRbadpath;
3483 END_PROFILE(SMBrmdir);
3484 return(UNIXERROR(ERRDOS,ERRbadpath));
3487 outsize = set_message(outbuf,0,0,True);
3489 DEBUG( 3, ( "rmdir %s\n", directory ) );
3491 END_PROFILE(SMBrmdir);
3496 /*******************************************************************
3497 resolve wildcards in a filename rename
3498 ********************************************************************/
3499 static BOOL resolve_wildcards(char *name1,char *name2)
3501 fstring root1,root2;
3505 name1 = strrchr_m(name1,'/');
3506 name2 = strrchr_m(name2,'/');
3508 if (!name1 || !name2) return(False);
3510 fstrcpy(root1,name1);
3511 fstrcpy(root2,name2);
3512 p = strrchr_m(root1,'.');
3519 p = strrchr_m(root2,'.');
3551 pstrcpy(name2,root2);
3554 pstrcat(name2,ext2);
3560 /*******************************************************************
3561 check if a user is allowed to rename a file
3562 ********************************************************************/
3563 static BOOL can_rename(char *fname,connection_struct *conn)
3565 SMB_STRUCT_STAT sbuf;
3567 if (!CAN_WRITE(conn)) return(False);
3569 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
3570 if (!check_file_sharing(conn,fname,True)) return(False);
3574 /****************************************************************************
3575 The guts of the rename command, split out so it may be called by the NT SMB
3577 ****************************************************************************/
3578 int rename_internals(connection_struct *conn,
3579 char *inbuf, char *outbuf, char *name,
3580 char *newname, BOOL replace_if_exists)
3584 pstring newname_last_component;
3587 BOOL bad_path1 = False;
3588 BOOL bad_path2 = False;
3590 int error = ERRnoaccess;
3593 SMB_STRUCT_STAT sbuf1, sbuf2;
3595 *directory = *mask = 0;
3597 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3598 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3601 * Split the old name into directory and last component
3602 * strings. Note that unix_convert may have stripped off a
3603 * leading ./ from both name and newname if the rename is
3604 * at the root of the share. We need to make sure either both
3605 * name and newname contain a / character or neither of them do
3606 * as this is checked in resolve_wildcards().
3609 p = strrchr_m(name,'/');
3611 pstrcpy(directory,".");
3615 pstrcpy(directory,name);
3617 *p = '/'; /* Replace needed for exceptional test below. */
3621 * We should only check the mangled cache
3622 * here if unix_convert failed. This means
3623 * that the path in 'mask' doesn't exist
3624 * on the file system and so we need to look
3625 * for a possible mangle. This patch from
3626 * Tine Smukavec <valentin.smukavec@hermes.si>.
3629 if (!rc && is_mangled(mask))
3630 check_mangled_cache( mask );
3632 has_wild = ms_has_wild(mask);
3636 * No wildcards - just process the one file.
3638 BOOL is_short_name = is_8_3(name, True);
3640 /* Add a terminating '/' to the directory name. */
3641 pstrcat(directory,"/");
3642 pstrcat(directory,mask);
3644 /* Ensure newname contains a '/' also */
3645 if(strrchr_m(newname,'/') == 0) {
3648 pstrcpy(tmpstr, "./");
3649 pstrcat(tmpstr, newname);
3650 pstrcpy(newname, tmpstr);
3653 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",
3654 case_sensitive, case_preserve, short_case_preserve, directory,
3655 newname, newname_last_component, is_short_name));
3658 * Check for special case with case preserving and not
3659 * case sensitive, if directory and newname are identical,
3660 * and the old last component differs from the original
3661 * last component only by case, then we should allow
3662 * the rename (user is trying to change the case of the
3665 if((case_sensitive == False) &&
3666 (((case_preserve == True) &&
3667 (is_short_name == False)) ||
3668 ((short_case_preserve == True) &&
3669 (is_short_name == True))) &&
3670 strcsequal(directory, newname)) {
3671 pstring newname_modified_last_component;
3674 * Get the last component of the modified name.
3675 * Note that we guarantee that newname contains a '/'
3678 p = strrchr_m(newname,'/');
3679 pstrcpy(newname_modified_last_component,p+1);
3681 if(strcsequal(newname_modified_last_component,
3682 newname_last_component) == False) {
3684 * Replace the modified last component with
3687 pstrcpy(p+1, newname_last_component);
3691 if(replace_if_exists) {
3693 * NT SMB specific flag - rename can overwrite
3694 * file with the same name so don't check for
3698 if(resolve_wildcards(directory,newname) &&
3699 can_rename(directory,conn) &&
3700 !conn->vfs_ops.rename(conn,directory,newname))
3703 if (resolve_wildcards(directory,newname) &&
3704 can_rename(directory,conn) &&
3705 !vfs_file_exist(conn,newname,NULL) &&
3706 !conn->vfs_ops.rename(conn,directory,newname))
3710 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3711 directory,newname));
3713 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3714 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3720 * Wildcards - process each file that matches.
3722 void *dirptr = NULL;
3726 if (check_name(directory,conn))
3727 dirptr = OpenDir(conn, directory, True);
3732 if (strequal(mask,"????????.???"))
3735 while ((dname = ReadDirName(dirptr))) {
3738 pstrcpy(fname,dname);
3740 if(!mask_match(fname, mask, case_sensitive))
3743 error = ERRnoaccess;
3744 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3745 if (!can_rename(fname,conn)) {
3746 DEBUG(6,("rename %s refused\n", fname));
3749 pstrcpy(destname,newname);
3751 if (!resolve_wildcards(fname,destname)) {
3752 DEBUG(6,("resolve_wildcards %s %s failed\n",
3757 if (!replace_if_exists &&
3758 vfs_file_exist(conn,destname, NULL)) {
3759 DEBUG(6,("file_exist %s\n", destname));
3764 if (!conn->vfs_ops.rename(conn,fname,destname))
3766 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3774 return(ERROR(ERRDOS,error));
3776 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3777 unix_ERR_class = ERRDOS;
3778 unix_ERR_code = ERRbadpath;
3780 return(UNIXERROR(ERRDOS,error));
3787 /****************************************************************************
3789 ****************************************************************************/
3791 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3798 START_PROFILE(SMBmv);
3800 p = smb_buf(inbuf) + 1;
3801 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3803 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3805 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3806 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3808 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3810 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3814 * Win2k needs a changenotify request response before it will
3815 * update after a rename..
3818 process_pending_change_notify_queue((time_t)0);
3820 outsize = set_message(outbuf,0,0,True);
3827 /*******************************************************************
3828 copy a file as part of a reply_copy
3829 ******************************************************************/
3831 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3832 int count,BOOL target_is_directory, int *err_ret)
3835 SMB_STRUCT_STAT src_sbuf, sbuf2;
3837 files_struct *fsp1,*fsp2;
3842 pstrcpy(dest,dest1);
3843 if (target_is_directory) {
3844 char *p = strrchr_m(src,'/');
3853 if (!vfs_file_exist(conn,src,&src_sbuf))
3856 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3857 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3863 if (!target_is_directory && count)
3864 ofun = FILE_EXISTS_OPEN;
3866 vfs_stat(conn,dest,&sbuf2);
3867 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3868 ofun,src_sbuf.st_mode,0,&Access,&action);
3871 close_file(fsp1,False);
3875 if ((ofun&3) == 1) {
3876 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3877 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3880 * Stop the copy from occurring.
3883 src_sbuf.st_size = 0;
3887 if (src_sbuf.st_size)
3888 ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0);
3890 close_file(fsp1,False);
3892 * As we are opening fsp1 read-only we only expect
3893 * an error on close on fsp2 if we are out of space.
3894 * Thus we don't look at the error return from the
3897 *err_ret = close_file(fsp2,False);
3899 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3904 /****************************************************************************
3905 reply to a file copy.
3906 ****************************************************************************/
3907 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3912 pstring mask,newname;
3915 int error = ERRnoaccess;
3919 int tid2 = SVAL(inbuf,smb_vwv0);
3920 int ofun = SVAL(inbuf,smb_vwv1);
3921 int flags = SVAL(inbuf,smb_vwv2);
3922 BOOL target_is_directory=False;
3923 BOOL bad_path1 = False;
3924 BOOL bad_path2 = False;
3926 SMB_STRUCT_STAT sbuf1, sbuf2;
3927 START_PROFILE(SMBcopy);
3929 *directory = *mask = 0;
3932 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3933 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3935 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3937 if (tid2 != conn->cnum) {
3938 /* can't currently handle inter share copies XXXX */
3939 DEBUG(3,("Rejecting inter-share copy\n"));
3940 END_PROFILE(SMBcopy);
3941 return(ERROR(ERRSRV,ERRinvdevice));
3944 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3945 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3947 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3948 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3950 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3952 if ((flags&1) && target_is_directory) {
3953 END_PROFILE(SMBcopy);
3954 return(ERROR(ERRDOS,ERRbadfile));
3957 if ((flags&2) && !target_is_directory) {
3958 END_PROFILE(SMBcopy);
3959 return(ERROR(ERRDOS,ERRbadpath));
3962 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3963 /* wants a tree copy! XXXX */
3964 DEBUG(3,("Rejecting tree copy\n"));
3965 END_PROFILE(SMBcopy);
3966 return(ERROR(ERRSRV,ERRerror));
3969 p = strrchr_m(name,'/');
3971 pstrcpy(directory,"./");
3975 pstrcpy(directory,name);
3980 * We should only check the mangled cache
3981 * here if unix_convert failed. This means
3982 * that the path in 'mask' doesn't exist
3983 * on the file system and so we need to look
3984 * for a possible mangle. This patch from
3985 * Tine Smukavec <valentin.smukavec@hermes.si>.
3988 if (!rc && is_mangled(mask))
3989 check_mangled_cache( mask );
3991 has_wild = ms_has_wild(mask);
3994 pstrcat(directory,"/");
3995 pstrcat(directory,mask);
3996 if (resolve_wildcards(directory,newname) &&
3997 copy_file(directory,newname,conn,ofun,
3998 count,target_is_directory,&err)) count++;
4001 END_PROFILE(SMBcopy);
4002 return(UNIXERROR(ERRHRD,ERRgeneral));
4004 if (!count) exists = vfs_file_exist(conn,directory,NULL);
4006 void *dirptr = NULL;
4010 if (check_name(directory,conn))
4011 dirptr = OpenDir(conn, directory, True);
4016 if (strequal(mask,"????????.???"))
4019 while ((dname = ReadDirName(dirptr))) {
4021 pstrcpy(fname,dname);
4023 if(!mask_match(fname, mask, case_sensitive))
4026 error = ERRnoaccess;
4027 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4028 pstrcpy(destname,newname);
4029 if (resolve_wildcards(fname,destname) &&
4030 copy_file(fname,destname,conn,ofun,
4031 count,target_is_directory,&err)) count++;
4032 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4040 /* Error on close... */
4042 END_PROFILE(SMBcopy);
4043 return(UNIXERROR(ERRHRD,ERRgeneral));
4047 END_PROFILE(SMBcopy);
4048 return(ERROR(ERRDOS,error));
4051 if((errno == ENOENT) && (bad_path1 || bad_path2))
4053 unix_ERR_class = ERRDOS;
4054 unix_ERR_code = ERRbadpath;
4056 END_PROFILE(SMBcopy);
4057 return(UNIXERROR(ERRDOS,error));
4061 outsize = set_message(outbuf,1,0,True);
4062 SSVAL(outbuf,smb_vwv0,count);
4064 END_PROFILE(SMBcopy);
4068 /****************************************************************************
4070 ****************************************************************************/
4071 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4077 START_PROFILE(pathworks_setdir);
4080 if (!CAN_SETDIR(snum)) {
4081 END_PROFILE(pathworks_setdir);
4082 return(ERROR(ERRDOS,ERRnoaccess));
4085 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
4087 if (strlen(newdir) == 0) {
4090 ok = vfs_directory_exist(conn,newdir,NULL);
4092 string_set(&conn->connectpath,newdir);
4097 END_PROFILE(pathworks_setdir);
4098 return(ERROR(ERRDOS,ERRbadpath));
4101 outsize = set_message(outbuf,0,0,True);
4102 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
4104 DEBUG(3,("setdir %s\n", newdir));
4106 END_PROFILE(pathworks_setdir);
4110 /****************************************************************************
4111 Get a lock pid, dealing with large count requests.
4112 ****************************************************************************/
4114 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4116 if(!large_file_format)
4117 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4119 return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
4122 /****************************************************************************
4123 Get a lock count, dealing with large count requests.
4124 ****************************************************************************/
4126 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4128 SMB_BIG_UINT count = 0;
4130 if(!large_file_format) {
4131 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4134 #if defined(HAVE_LONGLONG)
4135 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4136 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4137 #else /* HAVE_LONGLONG */
4140 * NT4.x seems to be broken in that it sends large file (64 bit)
4141 * lockingX calls even if the CAP_LARGE_FILES was *not*
4142 * negotiated. For boxes without large unsigned ints truncate the
4143 * lock count by dropping the top 32 bits.
4146 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4147 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4148 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4149 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4150 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4153 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4154 #endif /* HAVE_LONGLONG */
4160 /****************************************************************************
4161 Get a lock offset, dealing with large offset requests.
4162 ****************************************************************************/
4164 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4166 SMB_BIG_UINT offset = 0;
4170 if(!large_file_format) {
4171 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4174 #if defined(HAVE_LONGLONG)
4175 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4176 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4177 #else /* HAVE_LONGLONG */
4180 * NT4.x seems to be broken in that it sends large file (64 bit)
4181 * lockingX calls even if the CAP_LARGE_FILES was *not*
4182 * negotiated. For boxes without large unsigned ints mangle the
4183 * lock offset by mapping the top 32 bits onto the lower 32.
4186 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4187 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4188 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4191 if((new_low = map_lock_offset(high, low)) == 0) {
4193 return (SMB_BIG_UINT)-1;
4196 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4197 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4198 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4199 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4202 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4203 #endif /* HAVE_LONGLONG */
4209 /****************************************************************************
4210 reply to a lockingX request
4211 ****************************************************************************/
4213 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4215 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4216 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4217 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4218 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4219 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4220 SMB_BIG_UINT count = 0, offset = 0;
4222 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4225 uint32 ecode=0, dummy2;
4226 int eclass=0, dummy1;
4227 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4229 START_PROFILE(SMBlockingX);
4231 CHECK_FSP(fsp,conn);
4234 data = smb_buf(inbuf);
4236 /* Check if this is an oplock break on a file
4237 we have granted an oplock on.
4239 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4241 /* Client can insist on breaking to none. */
4242 BOOL break_to_none = (oplocklevel == 0);
4244 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4245 (unsigned int)oplocklevel, fsp->fnum ));
4248 * Make sure we have granted an exclusive or batch oplock on this file.
4251 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4253 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4254 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4256 /* if this is a pure oplock break request then don't send a reply */
4257 if (num_locks == 0 && num_ulocks == 0) {
4258 END_PROFILE(SMBlockingX);
4261 END_PROFILE(SMBlockingX);
4262 return ERROR(ERRDOS,ERRlock);
4266 if (remove_oplock(fsp, break_to_none) == False) {
4267 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4271 /* if this is a pure oplock break request then don't send a reply */
4272 if (num_locks == 0 && num_ulocks == 0)
4274 /* Sanity check - ensure a pure oplock break is not a
4276 if(CVAL(inbuf,smb_vwv0) != 0xff)
4277 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4278 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4279 END_PROFILE(SMBlockingX);
4285 * We do this check *after* we have checked this is not a oplock break
4286 * response message. JRA.
4289 release_level_2_oplocks_on_change(fsp);
4291 /* Data now points at the beginning of the list
4292 of smb_unlkrng structs */
4293 for(i = 0; i < (int)num_ulocks; i++) {
4294 lock_pid = get_lock_pid( data, i, large_file_format);
4295 count = get_lock_count( data, i, large_file_format);
4296 offset = get_lock_offset( data, i, large_file_format, &err);
4299 * There is no error code marked "stupid client bug".... :-).
4302 END_PROFILE(SMBlockingX);
4303 return ERROR(ERRDOS,ERRnoaccess);
4306 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4307 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4309 if(!do_unlock(fsp,conn,lock_pid,count,offset, &eclass, &ecode)) {
4310 END_PROFILE(SMBlockingX);
4311 return ERROR(eclass,ecode);
4315 /* Setup the timeout in seconds. */
4316 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4318 /* Now do any requested locks */
4319 data += ((large_file_format ? 20 : 10)*num_ulocks);
4321 /* Data now points at the beginning of the list
4322 of smb_lkrng structs */
4324 for(i = 0; i < (int)num_locks; i++) {
4325 lock_pid = get_lock_pid( data, i, large_file_format);
4326 count = get_lock_count( data, i, large_file_format);
4327 offset = get_lock_offset( data, i, large_file_format, &err);
4330 * There is no error code marked "stupid client bug".... :-).
4333 END_PROFILE(SMBlockingX);
4334 return ERROR(ERRDOS,ERRnoaccess);
4337 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
4338 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4340 if(!do_lock(fsp,conn,lock_pid, count,offset, ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
4342 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4344 * A blocking lock was requested. Package up
4345 * this smb into a queued request and push it
4346 * onto the blocking lock queue.
4348 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4349 END_PROFILE(SMBlockingX);
4357 /* If any of the above locks failed, then we must unlock
4358 all of the previous locks (X/Open spec). */
4359 if(i != num_locks && num_locks != 0) {
4361 * Ensure we don't do a remove on the lock that just failed,
4362 * as under POSIX rules, if we have a lock already there, we
4363 * will delete it (and we shouldn't) .....
4365 for(i--; i >= 0; i--) {
4366 lock_pid = get_lock_pid( data, i, large_file_format);
4367 count = get_lock_count( data, i, large_file_format);
4368 offset = get_lock_offset( data, i, large_file_format, &err);
4371 * There is no error code marked "stupid client bug".... :-).
4374 END_PROFILE(SMBlockingX);
4375 return ERROR(ERRDOS,ERRnoaccess);
4378 do_unlock(fsp,conn,lock_pid,count,offset,&dummy1,&dummy2);
4380 END_PROFILE(SMBlockingX);
4381 return ERROR(eclass,ecode);
4384 set_message(outbuf,2,0,True);
4386 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4387 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4389 END_PROFILE(SMBlockingX);
4390 return chain_reply(inbuf,outbuf,length,bufsize);
4394 /****************************************************************************
4395 reply to a SMBreadbmpx (read block multiplex) request
4396 ****************************************************************************/
4397 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4408 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4409 START_PROFILE(SMBreadBmpx);
4411 /* this function doesn't seem to work - disable by default */
4412 if (!lp_readbmpx()) {
4413 END_PROFILE(SMBreadBmpx);
4414 return(ERROR(ERRSRV,ERRuseSTD));
4417 outsize = set_message(outbuf,8,0,True);
4419 CHECK_FSP(fsp,conn);
4423 startpos = IVAL(inbuf,smb_vwv1);
4424 maxcount = SVAL(inbuf,smb_vwv3);
4426 data = smb_buf(outbuf);
4427 pad = ((long)data)%4;
4428 if (pad) pad = 4 - pad;
4431 max_per_packet = bufsize-(outsize+pad);
4435 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4436 END_PROFILE(SMBreadBmpx);
4437 return(ERROR(ERRDOS,ERRlock));
4442 size_t N = MIN(max_per_packet,tcount-total_read);
4444 nread = read_file(fsp,data,startpos,N);
4446 if (nread <= 0) nread = 0;
4448 if (nread < (ssize_t)N)
4449 tcount = total_read + nread;
4451 set_message(outbuf,8,nread,False);
4452 SIVAL(outbuf,smb_vwv0,startpos);
4453 SSVAL(outbuf,smb_vwv2,tcount);
4454 SSVAL(outbuf,smb_vwv6,nread);
4455 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4457 if (!send_smb(smbd_server_fd(),outbuf))
4458 exit_server("reply_readbmpx: send_smb failed.\n");
4460 total_read += nread;
4463 while (total_read < (ssize_t)tcount);
4465 END_PROFILE(SMBreadBmpx);
4469 /****************************************************************************
4470 reply to a SMBwritebmpx (write block multiplex primary) request
4471 ****************************************************************************/
4473 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4476 ssize_t nwritten = -1;
4483 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4484 START_PROFILE(SMBwriteBmpx);
4486 CHECK_FSP(fsp,conn);
4490 tcount = SVAL(inbuf,smb_vwv1);
4491 startpos = IVAL(inbuf,smb_vwv3);
4492 write_through = BITSETW(inbuf+smb_vwv7,0);
4493 numtowrite = SVAL(inbuf,smb_vwv10);
4494 smb_doff = SVAL(inbuf,smb_vwv11);
4496 data = smb_base(inbuf) + smb_doff;
4498 /* If this fails we need to send an SMBwriteC response,
4499 not an SMBwritebmpx - set this up now so we don't forget */
4500 CVAL(outbuf,smb_com) = SMBwritec;
4502 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4503 END_PROFILE(SMBwriteBmpx);
4504 return(ERROR(ERRDOS,ERRlock));
4507 nwritten = write_file(fsp,data,startpos,numtowrite);
4509 if(lp_syncalways(SNUM(conn)) || write_through)
4510 sync_file(conn,fsp);
4512 if(nwritten < (ssize_t)numtowrite) {
4513 END_PROFILE(SMBwriteBmpx);
4514 return(UNIXERROR(ERRHRD,ERRdiskfull));
4517 /* If the maximum to be written to this file
4518 is greater than what we just wrote then set
4519 up a secondary struct to be attached to this
4520 fd, we will use this to cache error messages etc. */
4521 if((ssize_t)tcount > nwritten)
4523 write_bmpx_struct *wbms;
4524 if(fsp->wbmpx_ptr != NULL)
4525 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4527 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4530 DEBUG(0,("Out of memory in reply_readmpx\n"));
4531 END_PROFILE(SMBwriteBmpx);
4532 return(ERROR(ERRSRV,ERRnoresource));
4534 wbms->wr_mode = write_through;
4535 wbms->wr_discard = False; /* No errors yet */
4536 wbms->wr_total_written = nwritten;
4537 wbms->wr_errclass = 0;
4539 fsp->wbmpx_ptr = wbms;
4542 /* We are returning successfully, set the message type back to
4544 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4546 outsize = set_message(outbuf,1,0,True);
4548 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4550 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4551 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4553 if (write_through && tcount==nwritten) {
4554 /* we need to send both a primary and a secondary response */
4555 smb_setlen(outbuf,outsize - 4);
4556 if (!send_smb(smbd_server_fd(),outbuf))
4557 exit_server("reply_writebmpx: send_smb failed.\n");
4559 /* now the secondary */
4560 outsize = set_message(outbuf,1,0,True);
4561 CVAL(outbuf,smb_com) = SMBwritec;
4562 SSVAL(outbuf,smb_vwv0,nwritten);
4565 END_PROFILE(SMBwriteBmpx);
4570 /****************************************************************************
4571 reply to a SMBwritebs (write block multiplex secondary) request
4572 ****************************************************************************/
4573 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4576 ssize_t nwritten = -1;
4583 write_bmpx_struct *wbms;
4584 BOOL send_response = False;
4585 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4586 START_PROFILE(SMBwriteBs);
4588 CHECK_FSP(fsp,conn);
4591 tcount = SVAL(inbuf,smb_vwv1);
4592 startpos = IVAL(inbuf,smb_vwv2);
4593 numtowrite = SVAL(inbuf,smb_vwv6);
4594 smb_doff = SVAL(inbuf,smb_vwv7);
4596 data = smb_base(inbuf) + smb_doff;
4598 /* We need to send an SMBwriteC response, not an SMBwritebs */
4599 CVAL(outbuf,smb_com) = SMBwritec;
4601 /* This fd should have an auxiliary struct attached,
4602 check that it does */
4603 wbms = fsp->wbmpx_ptr;
4605 END_PROFILE(SMBwriteBs);
4609 /* If write through is set we can return errors, else we must
4611 write_through = wbms->wr_mode;
4613 /* Check for an earlier error */
4614 if(wbms->wr_discard) {
4615 END_PROFILE(SMBwriteBs);
4616 return -1; /* Just discard the packet */
4619 nwritten = write_file(fsp,data,startpos,numtowrite);
4621 if(lp_syncalways(SNUM(conn)) || write_through)
4622 sync_file(conn,fsp);
4624 if (nwritten < (ssize_t)numtowrite)
4628 /* We are returning an error - we can delete the aux struct */
4629 if (wbms) free((char *)wbms);
4630 fsp->wbmpx_ptr = NULL;
4631 END_PROFILE(SMBwriteBs);
4632 return(ERROR(ERRHRD,ERRdiskfull));
4634 END_PROFILE(SMBwriteBs);
4635 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4638 /* Increment the total written, if this matches tcount
4639 we can discard the auxiliary struct (hurrah !) and return a writeC */
4640 wbms->wr_total_written += nwritten;
4641 if(wbms->wr_total_written >= tcount)
4645 outsize = set_message(outbuf,1,0,True);
4646 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4647 send_response = True;
4651 fsp->wbmpx_ptr = NULL;
4655 END_PROFILE(SMBwriteBs);
4659 END_PROFILE(SMBwriteBs);
4664 /****************************************************************************
4665 reply to a SMBsetattrE
4666 ****************************************************************************/
4668 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4670 struct utimbuf unix_times;
4672 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4673 START_PROFILE(SMBsetattrE);
4675 outsize = set_message(outbuf,0,0,True);
4677 CHECK_FSP(fsp,conn);
4680 /* Convert the DOS times into unix times. Ignore create
4681 time as UNIX can't set this.
4683 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4684 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4687 * Patch from Ray Frush <frush@engr.colostate.edu>
4688 * Sometimes times are sent as zero - ignore them.
4691 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4693 /* Ignore request */
4696 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4697 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4699 END_PROFILE(SMBsetattrE);
4702 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4704 /* set modify time = to access time if modify time was 0 */
4705 unix_times.modtime = unix_times.actime;
4708 /* Set the date on this file */
4709 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4710 END_PROFILE(SMBsetattrE);
4711 return(ERROR(ERRDOS,ERRnoaccess));
4714 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4715 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4717 END_PROFILE(SMBsetattrE);
4722 /****************************************************************************
4723 reply to a SMBgetattrE
4724 ****************************************************************************/
4726 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4728 SMB_STRUCT_STAT sbuf;
4731 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4732 START_PROFILE(SMBgetattrE);
4734 outsize = set_message(outbuf,11,0,True);
4736 CHECK_FSP(fsp,conn);
4739 /* Do an fstat on this file */
4740 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4741 END_PROFILE(SMBgetattrE);
4742 return(UNIXERROR(ERRDOS,ERRnoaccess));
4745 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4747 /* Convert the times into dos times. Set create
4748 date to be last modify date as UNIX doesn't save
4750 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4751 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4752 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4755 SIVAL(outbuf,smb_vwv6,0);
4756 SIVAL(outbuf,smb_vwv8,0);
4760 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4761 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4763 SSVAL(outbuf,smb_vwv10, mode);
4765 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4767 END_PROFILE(SMBgetattrE);