2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
6 Copyright (C) Andrew Bartlett 2001
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
30 /* look in server.c for some explanation of these variables */
32 extern int DEBUGLEVEL
;
35 extern char magic_char
;
36 extern BOOL case_sensitive
;
37 extern BOOL case_preserve
;
38 extern BOOL short_case_preserve
;
39 extern userdom_struct current_user_info
;
40 extern pstring global_myname
;
41 extern int global_oplock_break
;
42 uint32 global_client_caps
= 0;
43 unsigned int smb_echo_count
= 0;
45 extern fstring remote_machine
;
47 /****************************************************************************
48 report a possible attack via the password buffer overflow bug
49 ****************************************************************************/
51 static void overflow_attack(int len
)
54 dbgtext( "ERROR: Invalid password length %d.\n", len
);
55 dbgtext( "Your machine may be under attack by someone " );
56 dbgtext( "attempting to exploit an old bug.\n" );
57 dbgtext( "Attack was from IP = %s.\n", client_addr() );
62 /****************************************************************************
63 reply to an special message
64 ****************************************************************************/
66 int reply_special(char *inbuf
,char *outbuf
)
69 int msg_type
= CVAL(inbuf
,0);
70 int msg_flags
= CVAL(inbuf
,1);
73 extern fstring local_machine
;
79 memset(outbuf
,'\0',smb_size
);
84 case 0x81: /* session request */
85 CVAL(outbuf
,0) = 0x82;
87 if (name_len(inbuf
+4) > 50 ||
88 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
89 DEBUG(0,("Invalid name length in session request\n"));
92 name_extract(inbuf
,4,name1
);
93 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
94 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
97 fstrcpy(remote_machine
,name2
);
98 remote_machine
[15] = 0;
99 trim_string(remote_machine
," "," ");
100 strlower(remote_machine
);
101 alpha_strcpy(remote_machine
,remote_machine
,SAFE_NETBIOS_CHARS
,sizeof(remote_machine
)-1);
103 fstrcpy(local_machine
,name1
);
104 len
= strlen(local_machine
);
106 name_type
= local_machine
[15];
107 local_machine
[15] = 0;
109 trim_string(local_machine
," "," ");
110 strlower(local_machine
);
111 alpha_strcpy(local_machine
,local_machine
,SAFE_NETBIOS_CHARS
,sizeof(local_machine
)-1);
113 DEBUG(2,("netbios connect: local=%s remote=%s\n",
114 local_machine
, remote_machine
));
116 if (name_type
== 'R') {
117 /* We are being asked for a pathworks session ---
119 CVAL(outbuf
, 0) = 0x83;
123 /* only add the client's machine name to the list
124 of possibly valid usernames if we are operating
125 in share mode security */
126 if (lp_security() == SEC_SHARE
) {
127 add_session_user(remote_machine
);
130 reload_services(True
);
133 claim_connection(NULL
,"",MAXSTATUS
,True
);
137 case 0x89: /* session keepalive request
138 (some old clients produce this?) */
139 CVAL(outbuf
,0) = 0x85;
143 case 0x82: /* positive session response */
144 case 0x83: /* negative session response */
145 case 0x84: /* retarget session response */
146 DEBUG(0,("Unexpected session response\n"));
149 case 0x85: /* session keepalive */
154 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
155 msg_type
, msg_flags
));
161 /****************************************************************************
163 ****************************************************************************/
165 int reply_tcon(connection_struct
*conn
,
166 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
172 uint16 vuid
= SVAL(inbuf
,smb_uid
);
177 START_PROFILE(SMBtcon
);
179 *service
= *password
= *dev
= 0;
181 p
= smb_buf(inbuf
)+1;
182 p
+= srvstr_pull(inbuf
, service
, p
, sizeof(service
), -1, STR_TERMINATE
) + 1;
183 p
+= srvstr_pull(inbuf
, password
, p
, sizeof(password
), -1, STR_TERMINATE
) + 1;
184 p
+= srvstr_pull(inbuf
, dev
, p
, sizeof(dev
), -1, STR_TERMINATE
) + 1;
186 p
= strrchr_m(service
,'\\');
188 pstrcpy(service
, p
+1);
191 conn
= make_connection(service
,password
,pwlen
,dev
,vuid
,&ecode
);
194 END_PROFILE(SMBtcon
);
195 return ERROR_NT(ecode
);
198 outsize
= set_message(outbuf
,2,0,True
);
199 SSVAL(outbuf
,smb_vwv0
,max_recv
);
200 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
201 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
203 DEBUG(3,("tcon service=%s cnum=%d\n",
204 service
, conn
->cnum
));
206 END_PROFILE(SMBtcon
);
210 /****************************************************************************
211 Reply to a tcon and X.
212 ****************************************************************************/
214 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
220 uint16 vuid
= SVAL(inbuf
,smb_uid
);
221 int passlen
= SVAL(inbuf
,smb_vwv3
);
224 START_PROFILE(SMBtconX
);
226 *service
= *password
= *devicename
= 0;
228 /* we might have to close an old one */
229 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
230 close_cnum(conn
,vuid
);
233 if (passlen
> MAX_PASS_LEN
) {
234 overflow_attack(passlen
);
235 return(ERROR_DOS(ERRDOS
,ERRbuftoosmall
));
238 memcpy(password
,smb_buf(inbuf
),passlen
);
240 p
= smb_buf(inbuf
) + passlen
;
241 p
+= srvstr_pull(inbuf
, path
, p
, sizeof(path
), -1, STR_TERMINATE
);
244 if (strequal(password
," "))
246 passlen
= strlen(password
);
251 * the service name can be either: \\server\share
252 * or share directly like on the DELL PowerVault 705
255 q
= strchr_m(path
+2,'\\');
257 END_PROFILE(SMBtconX
);
258 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
260 fstrcpy(service
,q
+1);
263 fstrcpy(service
,path
);
265 p
+= srvstr_pull(inbuf
, devicename
, p
, sizeof(devicename
), 6, STR_ASCII
);
267 DEBUG(4,("Got device type %s\n",devicename
));
269 conn
= make_connection(service
,password
,passlen
,devicename
,vuid
,&ecode
);
272 END_PROFILE(SMBtconX
);
273 return ERROR_NT(ecode
);
276 if (Protocol
< PROTOCOL_NT1
) {
277 set_message(outbuf
,2,0,True
);
279 p
+= srvstr_push(outbuf
, p
, devicename
, -1,
280 STR_TERMINATE
|STR_ASCII
);
281 set_message_end(outbuf
,p
);
283 /* NT sets the fstype of IPC$ to the null string */
284 char *fsname
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
286 set_message(outbuf
,3,0,True
);
289 p
+= srvstr_push(outbuf
, p
, devicename
, -1,
290 STR_TERMINATE
|STR_ASCII
);
291 p
+= srvstr_push(outbuf
, p
, fsname
, -1,
294 set_message_end(outbuf
,p
);
296 /* what does setting this bit do? It is set by NT4 and
297 may affect the ability to autorun mounted cdroms */
298 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
);
300 init_dfsroot(conn
, inbuf
, outbuf
);
304 DEBUG(3,("tconX service=%s \n",
307 /* set the incoming and outgoing tid to the just created one */
308 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
309 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
311 END_PROFILE(SMBtconX
);
312 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
316 /****************************************************************************
317 reply to an unknown type
318 ****************************************************************************/
319 int reply_unknown(char *inbuf
,char *outbuf
)
322 type
= CVAL(inbuf
,smb_com
);
324 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
325 smb_fn_name(type
), type
, type
));
327 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
331 /****************************************************************************
333 ****************************************************************************/
334 int reply_ioctl(connection_struct
*conn
,
335 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
337 uint16 device
= SVAL(inbuf
,smb_vwv1
);
338 uint16 function
= SVAL(inbuf
,smb_vwv2
);
339 uint32 ioctl_code
= (device
<< 16) + function
;
340 int replysize
, outsize
;
342 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
343 START_PROFILE(SMBioctl
);
345 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
349 case IOCTL_QUERY_JOB_INFO
:
353 END_PROFILE(SMBioctl
);
354 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
357 outsize
= set_message(outbuf
,8,replysize
+1,True
);
358 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
359 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
360 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
361 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
365 case IOCTL_QUERY_JOB_INFO
:
366 SSVAL(p
,0,fsp
->print_jobid
); /* Job number */
367 srvstr_push(outbuf
, p
+2, global_myname
, 15, STR_TERMINATE
|STR_ASCII
);
368 srvstr_push(outbuf
, p
+18, lp_servicename(SNUM(conn
)), 13, STR_TERMINATE
|STR_ASCII
);
372 END_PROFILE(SMBioctl
);
376 /****************************************************************************
377 This function breaks the authentication split. It needs sorting out.
378 I can't see why we can't hadle this INSIDE the check_password, as in then
379 end all it does it spit out an nt_status code.
380 ****************************************************************************/
381 /****************************************************************************
382 always return an error: it's just a matter of which one...
383 ****************************************************************************/
384 static int session_trust_account(connection_struct
*conn
, char *inbuf
, char *outbuf
, char *user
,
385 char *smb_passwd
, int smb_passlen
,
386 char *smb_nt_passwd
, int smb_nt_passlen
)
388 /* check if trust account exists */
389 SAM_ACCOUNT
*sam_trust_acct
= NULL
;
392 auth_usersupplied_info user_info
;
393 auth_serversupplied_info server_info
;
394 AUTH_STR domain
, smb_username
, wksta_name
;
396 ZERO_STRUCT(user_info
);
397 ZERO_STRUCT(server_info
);
399 ZERO_STRUCT(smb_username
);
400 ZERO_STRUCT(wksta_name
);
402 domain
.str
= lp_workgroup();
403 domain
.len
= strlen(domain
.str
);
405 user_info
.requested_domain
= domain
;
406 user_info
.domain
= domain
;
408 smb_username
.str
= user
;
409 smb_username
.len
= strlen(smb_username
.str
);
411 user_info
.unix_username
= smb_username
; /* For the time-being */
412 user_info
.smb_username
= smb_username
;
414 user_info
.wksta_name
= wksta_name
;
416 user_info
.lm_resp
.buffer
= (uint8
*)smb_passwd
;
417 user_info
.lm_resp
.len
= smb_passlen
;
418 user_info
.nt_resp
.buffer
= (uint8
*)smb_nt_passwd
;
419 user_info
.nt_resp
.len
= smb_nt_passlen
;
421 if (!last_challenge(user_info
.chal
)) {
422 DEBUG(1,("smb_password_ok: no challenge done - password failed\n"));
423 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
426 pdb_init_sam(&sam_trust_acct
);
428 if (lp_security() == SEC_USER
) {
429 ret
= pdb_getsampwnam(sam_trust_acct
, user
);
431 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user
));
432 pdb_free_sam(sam_trust_acct
);
433 return(ERROR_NT(NT_STATUS_LOGON_FAILURE
));
437 /* lkclXXXX: workstation entry doesn't exist */
438 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user
));
439 pdb_free_sam(sam_trust_acct
);
440 return(ERROR_NT(NT_STATUS_NO_SUCH_USER
));
442 if ((smb_passlen
!= 24) || (smb_nt_passlen
!= 24)) {
443 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user
));
444 pdb_free_sam(sam_trust_acct
);
445 return(ERROR_NT(NT_STATUS_LOGON_FAILURE
));
448 if (!NT_STATUS_IS_OK(smb_password_ok(sam_trust_acct
, &user_info
, &server_info
))) {
449 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user
));
450 pdb_free_sam(sam_trust_acct
);
451 return(ERROR_NT(NT_STATUS_LOGON_FAILURE
));
454 acct_ctrl
= pdb_get_acct_ctrl(sam_trust_acct
);
455 pdb_free_sam(sam_trust_acct
);
456 if (acct_ctrl
& ACB_DOMTRUST
) {
457 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user
));
458 return(ERROR_NT(NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT
));
461 if (acct_ctrl
& ACB_SVRTRUST
) {
462 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user
));
463 return(ERROR_NT(NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT
));
466 if (acct_ctrl
& ACB_WSTRUST
) {
467 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user
));
468 return(ERROR_NT(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
));
472 /* don't know what to do: indicate logon failure */
473 return(ERROR_NT(NT_STATUS_LOGON_FAILURE
));
477 /****************************************************************************
478 reply to a session setup command
479 ****************************************************************************/
481 int reply_sesssetup_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
488 int smb_apasslen
= 0;
490 int smb_ntpasslen
= 0;
491 pstring smb_ntpasswd
;
496 fstring native_lanman
;
498 static BOOL done_sesssetup
= False
;
499 BOOL doencrypt
= SMBENCRYPT();
500 START_PROFILE(SMBsesssetupX
);
505 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
507 if (Protocol
< PROTOCOL_NT1
) {
508 smb_apasslen
= SVAL(inbuf
,smb_vwv7
);
509 if (smb_apasslen
> MAX_PASS_LEN
) {
510 overflow_attack(smb_apasslen
);
511 return(ERROR_DOS(ERRDOS
,ERRbuftoosmall
));
514 memcpy(smb_apasswd
,smb_buf(inbuf
),smb_apasslen
);
515 srvstr_pull(inbuf
, user
, smb_buf(inbuf
)+smb_apasslen
, sizeof(user
), -1, STR_TERMINATE
);
517 if (!doencrypt
&& (lp_security() != SEC_SERVER
)) {
518 smb_apasslen
= strlen(smb_apasswd
);
521 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
522 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
523 enum remote_arch_types ra_type
= get_remote_arch();
524 char *p
= smb_buf(inbuf
);
526 if(global_client_caps
== 0)
527 global_client_caps
= IVAL(inbuf
,smb_vwv11
);
529 /* client_caps is used as final determination if client is NT or Win95.
530 This is needed to return the correct error codes in some
534 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
|| ra_type
== RA_WIN95
) {
535 if(!(global_client_caps
& (CAP_NT_SMBS
| CAP_STATUS32
))) {
536 set_remote_arch( RA_WIN95
);
540 if (passlen1
!= 24 && passlen2
< 24)
543 if (passlen1
> MAX_PASS_LEN
) {
544 overflow_attack(passlen1
);
545 return ERROR_DOS(ERRDOS
,ERRbuftoosmall
);
548 passlen1
= MIN(passlen1
, MAX_PASS_LEN
);
549 passlen2
= MIN(passlen2
, MAX_PASS_LEN
);
552 /* both Win95 and WinNT stuff up the password lengths for
553 non-encrypting systems. Uggh.
555 if passlen1==24 its a win95 system, and its setting the
556 password length incorrectly. Luckily it still works with the
557 default code because Win95 will null terminate the password
560 if passlen1>0 and passlen2>0 then maybe its a NT box and its
561 setting passlen2 to some random value which really stuffs
562 things up. we need to fix that one. */
564 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 && passlen2
!= 1)
568 if (lp_restrict_anonymous()) {
569 /* there seems to be no reason behind the differences in MS clients formatting
570 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
571 * in particular seems to have an extra null byte between the username and the
572 * domain, or the password length calculation is wrong, which throws off the
573 * string extraction routines below. This makes the value of domain be the
574 * empty string, which fails the restrict anonymous check further down.
575 * This compensates for that, and allows browsing to work in mixed NT and
576 * win95 environments even when restrict anonymous is true. AAB
578 dump_data(100, p
, 0x70);
579 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1
, passlen2
));
580 if (ra_type
== RA_WIN95
&& !passlen1
&& !passlen2
&& p
[0] == 0 && p
[1] == 0) {
581 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
582 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
583 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
588 if(doencrypt
|| ((lp_security() == SEC_SERVER
) || (lp_security() == SEC_DOMAIN
))) {
589 /* Save the lanman2 password and the NT md4 password. */
590 smb_apasslen
= passlen1
;
591 memcpy(smb_apasswd
,p
,smb_apasslen
);
592 smb_apasswd
[smb_apasslen
] = 0;
593 smb_ntpasslen
= passlen2
;
594 memcpy(smb_ntpasswd
,p
+passlen1
,smb_ntpasslen
);
595 smb_ntpasswd
[smb_ntpasslen
] = 0;
597 /* we use the first password that they gave */
598 smb_apasslen
= passlen1
;
599 StrnCpy(smb_apasswd
,p
,smb_apasslen
);
601 /* trim the password */
602 smb_apasslen
= strlen(smb_apasswd
);
604 /* wfwg sometimes uses a space instead of a null */
605 if (strequal(smb_apasswd
," ")) {
611 p
+= passlen1
+ passlen2
;
612 p
+= srvstr_pull(inbuf
, user
, p
, sizeof(user
), -1,
615 * Incoming user and domain are in DOS codepage format. Convert
618 p
+= srvstr_pull(inbuf
, domain
, p
, sizeof(domain
),
620 p
+= srvstr_pull(inbuf
, native_os
, p
, sizeof(native_os
),
622 p
+= srvstr_pull(inbuf
, native_lanman
, p
, sizeof(native_lanman
),
624 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
625 domain
,native_os
,native_lanman
));
628 /* don't allow for weird usernames or domains */
629 alpha_strcpy(user
, user
, ". _-$", sizeof(user
));
630 alpha_strcpy(domain
, domain
, ". _-", sizeof(domain
));
631 if (strstr(user
, "..") || strstr(domain
,"..")) {
632 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
635 if (lp_security() == SEC_SHARE
) {
636 /* in share level we should ignore any passwords */
643 DEBUG(3,("sesssetupX:name=[%s]@[%s]\n",user
, remote_machine
));
645 /* If name ends in $ then I think it's asking about whether a */
646 /* computer with that name (minus the $) has access. For now */
647 /* say yes to everything ending in $. */
649 if (*user
&& (user
[strlen(user
) - 1] == '$') && (smb_apasslen
== 24) && (smb_ntpasslen
== 24)) {
650 END_PROFILE(SMBsesssetupX
);
651 return session_trust_account(conn
, inbuf
, outbuf
, user
,
652 smb_apasswd
, smb_apasslen
,
653 smb_ntpasswd
, smb_ntpasslen
);
656 if (done_sesssetup
&& lp_restrict_anonymous()) {
657 /* tests show that even if browsing is done over already validated connections
658 * without a username and password the domain is still provided, which it
659 * wouldn't be if it was a purely anonymous connection. So, in order to
660 * restrict anonymous, we only deny connections that have no session
661 * information. If a domain has been provided, then it's not a purely
662 * anonymous connection. AAB
664 if (!*user
&& !*smb_apasswd
&& !*domain
) {
665 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
666 END_PROFILE(SMBsesssetupX
);
667 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
671 /* If no username is sent use the guest account */
673 pstrcpy(user
,lp_guestaccount(-1));
677 pstrcpy(current_user_info
.smb_name
,user
);
679 reload_services(True
);
682 * Save the username before mapping. We will use
683 * the original username sent to us for security=server
684 * and security=domain checking.
687 pstrcpy( orig_user
, user
);
690 * Always try the "DOMAIN\user" lookup first, as this is the most
691 * specific case. If this fails then try the simple "user" lookup.
692 * But don't do this for guests, as this is always a local user.
698 /* Work out who's who */
700 slprintf(dom_user
, sizeof(dom_user
) - 1,"%s%s%s",
701 domain
, lp_winbind_separator(), user
);
703 if (sys_getpwnam(dom_user
) != NULL
) {
704 pstrcpy(user
, dom_user
);
705 DEBUG(3,("Using unix username %s\n", dom_user
));
709 * Pass the user through the NT -> unix user mapping
713 (void)map_username(user
);
716 * Do any UNIX username case mangling.
718 smb_getpwnam(user
, True
);
721 add_session_user(user
);
725 nt_status
= pass_check_smb(orig_user
, user
,
726 domain
, remote_machine
,
727 (unsigned char *)smb_apasswd
,
729 (unsigned char *)smb_ntpasswd
,
732 if NT_STATUS_IS_OK(nt_status
) {
734 } else if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NO_SUCH_USER
)
735 && lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER
) {
736 DEBUG(3,("No such user %s [%s] - using guest account\n",user
, domain
));
737 pstrcpy(user
,lp_guestaccount(-1));
740 } else if ((NT_STATUS_EQUAL(nt_status
, NT_STATUS_WRONG_PASSWORD
)
741 || NT_STATUS_EQUAL(nt_status
, NT_STATUS_NO_SUCH_USER
))
742 && (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
)) {
743 pstrcpy(user
,lp_guestaccount(-1));
744 DEBUG(3,("Registered username %s for guest access\n",user
));
748 return ERROR_NT(nt_status
);
752 if (!strequal(user
,lp_guestaccount(-1)) &&
753 lp_servicenumber(user
) < 0)
755 add_home_service(user
,get_user_home_dir(user
));
759 /* it's ok - setup a reply */
760 if (Protocol
< PROTOCOL_NT1
) {
761 set_message(outbuf
,3,0,True
);
764 set_message(outbuf
,3,0,True
);
766 p
+= srvstr_push(outbuf
, p
, "Unix", -1, STR_TERMINATE
);
767 p
+= srvstr_push(outbuf
, p
, "Samba", -1, STR_TERMINATE
);
768 p
+= srvstr_push(outbuf
, p
, lp_workgroup(), -1, STR_TERMINATE
);
769 set_message_end(outbuf
,p
);
770 /* perhaps grab OS version here?? */
773 /* Set the correct uid in the outgoing and incoming packets
774 We will use this on future requests to determine which
775 user we should become.
778 const struct passwd
*pw
= smb_getpwnam(user
,False
);
780 DEBUG(1,("Username %s is invalid on this system\n",user
));
781 END_PROFILE(SMBsesssetupX
);
782 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
786 full_name
= pw
->pw_gecos
;
790 SSVAL(outbuf
,smb_vwv2
,1);
792 /* register the name and uid as being validated, so further connections
793 to a uid can get through without a password, on the same VC */
795 sess_vuid
= register_vuid(uid
,gid
,user
,current_user_info
.smb_name
,domain
,guest
, full_name
);
797 if (sess_vuid
== -1) {
798 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
802 SSVAL(outbuf
,smb_uid
,sess_vuid
);
803 SSVAL(inbuf
,smb_uid
,sess_vuid
);
806 max_send
= MIN(max_send
,smb_bufsize
);
808 DEBUG(6,("Client requested max send size of %d\n", max_send
));
810 done_sesssetup
= True
;
812 END_PROFILE(SMBsesssetupX
);
813 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
816 /****************************************************************************
818 ****************************************************************************/
819 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
825 BOOL bad_path
= False
;
826 SMB_STRUCT_STAT sbuf
;
827 START_PROFILE(SMBchkpth
);
829 srvstr_pull(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), -1, STR_TERMINATE
);
831 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
833 unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
835 mode
= SVAL(inbuf
,smb_vwv0
);
837 if (check_name(name
,conn
)) {
838 if (VALID_STAT(sbuf
) || vfs_stat(conn
,name
,&sbuf
) == 0)
839 ok
= S_ISDIR(sbuf
.st_mode
);
843 /* We special case this - as when a Windows machine
844 is parsing a path is steps through the components
845 one at a time - if a component fails it expects
846 ERRbadpath, not ERRbadfile.
848 if(errno
== ENOENT
) {
849 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
852 return(UNIXERROR(ERRDOS
,ERRbadpath
));
855 outsize
= set_message(outbuf
,0,0,True
);
857 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
859 END_PROFILE(SMBchkpth
);
864 /****************************************************************************
866 ****************************************************************************/
867 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
871 SMB_STRUCT_STAT sbuf
;
876 BOOL bad_path
= False
;
878 START_PROFILE(SMBgetatr
);
880 p
= smb_buf(inbuf
) + 1;
881 p
+= srvstr_pull(inbuf
, fname
, p
, sizeof(fname
), -1, STR_TERMINATE
);
883 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
885 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
886 under WfWg - weird! */
889 mode
= aHIDDEN
| aDIR
;
890 if (!CAN_WRITE(conn
)) mode
|= aRONLY
;
897 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
898 if (check_name(fname
,conn
))
900 if (VALID_STAT(sbuf
) || vfs_stat(conn
,fname
,&sbuf
) == 0)
902 mode
= dos_mode(conn
,fname
,&sbuf
);
904 mtime
= sbuf
.st_mtime
;
910 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
916 if((errno
== ENOENT
) && bad_path
)
918 unix_ERR_class
= ERRDOS
;
919 unix_ERR_code
= ERRbadpath
;
922 END_PROFILE(SMBgetatr
);
923 return(UNIXERROR(ERRDOS
,ERRbadfile
));
926 outsize
= set_message(outbuf
,10,0,True
);
928 SSVAL(outbuf
,smb_vwv0
,mode
);
929 if(lp_dos_filetime_resolution(SNUM(conn
)) )
930 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
932 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
933 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
935 if (Protocol
>= PROTOCOL_NT1
) {
936 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | 0x40); /* IS_LONG_NAME */
939 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
941 END_PROFILE(SMBgetatr
);
946 /****************************************************************************
948 ****************************************************************************/
949 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
956 SMB_STRUCT_STAT sbuf
;
957 BOOL bad_path
= False
;
960 START_PROFILE(SMBsetatr
);
962 p
= smb_buf(inbuf
) + 1;
963 p
+= srvstr_pull(inbuf
, fname
, p
, sizeof(fname
), -1, STR_TERMINATE
);
964 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
966 mode
= SVAL(inbuf
,smb_vwv0
);
967 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
969 if (VALID_STAT_OF_DIR(sbuf
))
971 if (check_name(fname
,conn
))
972 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
974 ok
= set_filetime(conn
,fname
,mtime
);
978 if((errno
== ENOENT
) && bad_path
)
980 unix_ERR_class
= ERRDOS
;
981 unix_ERR_code
= ERRbadpath
;
984 END_PROFILE(SMBsetatr
);
985 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
988 outsize
= set_message(outbuf
,0,0,True
);
990 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
992 END_PROFILE(SMBsetatr
);
997 /****************************************************************************
999 ****************************************************************************/
1000 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1003 SMB_BIG_UINT dfree
,dsize
,bsize
;
1004 START_PROFILE(SMBdskattr
);
1006 conn
->vfs_ops
.disk_free(conn
,".",True
,&bsize
,&dfree
,&dsize
);
1008 outsize
= set_message(outbuf
,5,0,True
);
1010 SSVAL(outbuf
,smb_vwv0
,dsize
);
1011 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
1012 SSVAL(outbuf
,smb_vwv2
,512);
1013 SSVAL(outbuf
,smb_vwv3
,dfree
);
1015 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1017 END_PROFILE(SMBdskattr
);
1022 /****************************************************************************
1024 Can be called from SMBsearch, SMBffirst or SMBfunique.
1025 ****************************************************************************/
1026 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1037 BOOL finished
= False
;
1046 BOOL check_descend
= False
;
1047 BOOL expect_close
= False
;
1048 BOOL can_open
= True
;
1049 BOOL bad_path
= False
;
1050 START_PROFILE(SMBsearch
);
1052 *mask
= *directory
= *fname
= 0;
1054 /* If we were called as SMBffirst then we must expect close. */
1055 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
1056 expect_close
= True
;
1058 outsize
= set_message(outbuf
,1,3,True
);
1059 maxentries
= SVAL(inbuf
,smb_vwv0
);
1060 dirtype
= SVAL(inbuf
,smb_vwv1
);
1061 p
= smb_buf(inbuf
) + 1;
1062 p
+= srvstr_pull(inbuf
, path
, p
, sizeof(path
), -1, STR_TERMINATE
);
1064 status_len
= SVAL(p
, 0);
1067 /* dirtype &= ~aDIR; */
1069 if (status_len
== 0)
1071 SMB_STRUCT_STAT sbuf
;
1074 pstrcpy(directory
,path
);
1076 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
1079 if (!check_name(directory
,conn
))
1082 p
= strrchr_m(dir2
,'/');
1094 p
= strrchr_m(directory
,'/');
1100 if (strlen(directory
) == 0)
1101 pstrcpy(directory
,"./");
1102 memset((char *)status
,'\0',21);
1103 CVAL(status
,0) = dirtype
;
1107 memcpy(status
,p
,21);
1108 dirtype
= CVAL(status
,0) & 0x1F;
1109 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
1112 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
1113 fstrcpy(mask
, dptr_wcard(dptr_num
));
1118 p
= smb_buf(outbuf
) + 3;
1122 if (status_len
== 0)
1124 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
1129 if((errno
== ENOENT
) && bad_path
)
1131 unix_ERR_class
= ERRDOS
;
1132 unix_ERR_code
= ERRbadpath
;
1134 END_PROFILE(SMBsearch
);
1135 return (UNIXERROR(ERRDOS
,ERRnofids
));
1137 END_PROFILE(SMBsearch
);
1138 return ERROR_DOS(ERRDOS
,ERRnofids
);
1140 dptr_set_wcard(dptr_num
, strdup(mask
));
1143 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1147 if ((dirtype
&0x1F) == aVOLID
)
1149 memcpy(p
,status
,21);
1150 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
1151 dptr_fill(p
+12,dptr_num
);
1152 if (dptr_zero(p
+12) && (status_len
==0))
1156 p
+= DIR_STRUCT_SIZE
;
1160 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1161 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
1162 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
1163 check_descend
= True
;
1165 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
1168 !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
1171 memcpy(p
,status
,21);
1172 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
1173 dptr_fill(p
+12,dptr_num
);
1176 p
+= DIR_STRUCT_SIZE
;
1185 if (numentries
== 0 || !ok
)
1187 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1188 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1189 dptr_close(&dptr_num
);
1192 /* If we were called as SMBffirst with smb_search_id == NULL
1193 and no entries were found then return error and close dirptr
1196 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
1198 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1199 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1200 /* Also close the dptr - we know it's gone */
1201 dptr_close(&dptr_num
);
1204 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1205 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
1206 dptr_close(&dptr_num
);
1208 SSVAL(outbuf
,smb_vwv0
,numentries
);
1209 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1210 CVAL(smb_buf(outbuf
),0) = 5;
1211 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1213 if (Protocol
>= PROTOCOL_NT1
) {
1214 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | 0x40); /* IS_LONG_NAME */
1217 outsize
+= DIR_STRUCT_SIZE
*numentries
;
1218 smb_setlen(outbuf
,outsize
- 4);
1220 if ((! *directory
) && dptr_path(dptr_num
))
1221 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
1223 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1224 smb_fn_name(CVAL(inbuf
,smb_com
)),
1225 mask
, directory
, dirtype
, numentries
, maxentries
) );
1227 END_PROFILE(SMBsearch
);
1232 /****************************************************************************
1233 reply to a fclose (stop directory search)
1234 ****************************************************************************/
1235 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1244 START_PROFILE(SMBfclose
);
1246 outsize
= set_message(outbuf
,1,0,True
);
1247 p
= smb_buf(inbuf
) + 1;
1248 p
+= srvstr_pull(inbuf
, path
, p
, sizeof(path
), -1, STR_TERMINATE
);
1250 status_len
= SVAL(p
,0);
1253 if (status_len
== 0) {
1254 END_PROFILE(SMBfclose
);
1255 return ERROR_DOS(ERRSRV
,ERRsrverror
);
1258 memcpy(status
,p
,21);
1260 if(dptr_fetch(status
+12,&dptr_num
)) {
1261 /* Close the dptr - we know it's gone */
1262 dptr_close(&dptr_num
);
1265 SSVAL(outbuf
,smb_vwv0
,0);
1267 DEBUG(3,("search close\n"));
1269 END_PROFILE(SMBfclose
);
1274 /****************************************************************************
1276 ****************************************************************************/
1278 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1288 SMB_STRUCT_STAT sbuf
;
1289 BOOL bad_path
= False
;
1291 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1292 START_PROFILE(SMBopen
);
1294 share_mode
= SVAL(inbuf
,smb_vwv0
);
1296 srvstr_pull(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), -1, STR_TERMINATE
);
1298 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1300 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1302 unixmode
= unix_mode(conn
,aARCH
,fname
);
1304 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1305 unixmode
, oplock_request
,&rmode
,NULL
);
1309 if((errno
== ENOENT
) && bad_path
)
1311 unix_ERR_class
= ERRDOS
;
1312 unix_ERR_code
= ERRbadpath
;
1314 END_PROFILE(SMBopen
);
1315 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1318 size
= sbuf
.st_size
;
1319 fmode
= dos_mode(conn
,fname
,&sbuf
);
1320 mtime
= sbuf
.st_mtime
;
1323 DEBUG(3,("attempt to open a directory %s\n",fname
));
1324 close_file(fsp
,False
);
1325 END_PROFILE(SMBopen
);
1326 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1329 outsize
= set_message(outbuf
,7,0,True
);
1330 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1331 SSVAL(outbuf
,smb_vwv1
,fmode
);
1332 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1333 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
1335 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1336 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
1337 SSVAL(outbuf
,smb_vwv6
,rmode
);
1339 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1340 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1343 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1344 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1345 END_PROFILE(SMBopen
);
1350 /****************************************************************************
1351 reply to an open and X
1352 ****************************************************************************/
1353 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1356 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1357 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1358 /* Breakout the oplock request bits so we can set the
1359 reply bits separately. */
1360 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1361 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1362 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
1364 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1365 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1366 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1368 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1371 int fmode
=0,mtime
=0,rmode
=0;
1372 SMB_STRUCT_STAT sbuf
;
1374 BOOL bad_path
= False
;
1376 START_PROFILE(SMBopenX
);
1378 /* If it's an IPC, pass off the pipe handler. */
1380 if (lp_nt_pipe_support()) {
1381 END_PROFILE(SMBopenX
);
1382 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1384 END_PROFILE(SMBopenX
);
1385 return ERROR_DOS(ERRSRV
,ERRaccess
);
1389 /* XXXX we need to handle passed times, sattr and flags */
1390 srvstr_pull(inbuf
, fname
, smb_buf(inbuf
), sizeof(fname
), -1, STR_TERMINATE
);
1392 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1394 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1396 unixmode
= unix_mode(conn
,smb_attr
| aARCH
, fname
);
1398 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,unixmode
,
1399 oplock_request
, &rmode
,&smb_action
);
1403 if((errno
== ENOENT
) && bad_path
)
1405 unix_ERR_class
= ERRDOS
;
1406 unix_ERR_code
= ERRbadpath
;
1408 END_PROFILE(SMBopenX
);
1409 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1412 size
= sbuf
.st_size
;
1413 fmode
= dos_mode(conn
,fname
,&sbuf
);
1414 mtime
= sbuf
.st_mtime
;
1416 close_file(fsp
,False
);
1417 END_PROFILE(SMBopenX
);
1418 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1421 /* If the caller set the extended oplock request bit
1422 and we granted one (by whatever means) - set the
1423 correct bit for extended oplock reply.
1426 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1427 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1430 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1431 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1434 /* If the caller set the core oplock request bit
1435 and we granted one (by whatever means) - set the
1436 correct bit for core oplock reply.
1439 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1440 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1443 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1444 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1447 set_message(outbuf
,15,0,True
);
1448 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1449 SSVAL(outbuf
,smb_vwv3
,fmode
);
1450 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1451 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1453 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1454 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1455 SSVAL(outbuf
,smb_vwv8
,rmode
);
1456 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1458 END_PROFILE(SMBopenX
);
1459 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1463 /****************************************************************************
1464 reply to a SMBulogoffX
1465 ****************************************************************************/
1466 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1468 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1469 user_struct
*vuser
= get_valid_user_struct(vuid
);
1470 START_PROFILE(SMBulogoffX
);
1473 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1476 /* in user level security we are supposed to close any files
1477 open by this user */
1478 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1479 file_close_user(vuid
);
1482 invalidate_vuid(vuid
);
1484 set_message(outbuf
,2,0,True
);
1486 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1488 END_PROFILE(SMBulogoffX
);
1489 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1493 /****************************************************************************
1494 reply to a mknew or a create
1495 ****************************************************************************/
1496 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1504 BOOL bad_path
= False
;
1506 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1507 SMB_STRUCT_STAT sbuf
;
1508 START_PROFILE(SMBcreate
);
1510 com
= SVAL(inbuf
,smb_com
);
1512 createmode
= SVAL(inbuf
,smb_vwv0
);
1513 srvstr_pull(inbuf
, fname
, smb_buf(inbuf
) + 1, sizeof(fname
), -1, STR_TERMINATE
);
1515 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1517 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1519 if (createmode
& aVOLID
) {
1520 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1523 unixmode
= unix_mode(conn
,createmode
,fname
);
1527 /* We should fail if file exists. */
1528 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1532 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1533 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1536 /* Open file in dos compatibility share mode. */
1537 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1538 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1542 if((errno
== ENOENT
) && bad_path
)
1544 unix_ERR_class
= ERRDOS
;
1545 unix_ERR_code
= ERRbadpath
;
1547 END_PROFILE(SMBcreate
);
1548 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1551 outsize
= set_message(outbuf
,1,0,True
);
1552 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1554 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1555 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1558 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1559 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1561 DEBUG( 2, ( "new file %s\n", fname
) );
1562 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1563 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1565 END_PROFILE(SMBcreate
);
1570 /****************************************************************************
1571 reply to a create temporary file
1572 ****************************************************************************/
1573 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1579 BOOL bad_path
= False
;
1581 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1583 SMB_STRUCT_STAT sbuf
;
1586 START_PROFILE(SMBctemp
);
1588 createmode
= SVAL(inbuf
,smb_vwv0
);
1589 srvstr_pull(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), -1, STR_TERMINATE
);
1590 pstrcat(fname
,"\\TMXXXXXX");
1592 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1594 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1596 unixmode
= unix_mode(conn
,createmode
,fname
);
1598 tmpfd
= smb_mkstemp(fname
);
1600 END_PROFILE(SMBctemp
);
1601 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1604 vfs_stat(conn
,fname
,&sbuf
);
1606 /* Open file in dos compatibility share mode. */
1607 /* We should fail if file does not exist. */
1608 fsp
= open_file_shared(conn
,fname
,&sbuf
,
1609 SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1610 FILE_EXISTS_OPEN
|FILE_FAIL_IF_NOT_EXIST
,
1611 unixmode
, oplock_request
, NULL
, NULL
);
1613 /* close fd from smb_mkstemp() */
1618 if((errno
== ENOENT
) && bad_path
)
1620 unix_ERR_class
= ERRDOS
;
1621 unix_ERR_code
= ERRbadpath
;
1623 END_PROFILE(SMBctemp
);
1624 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1627 outsize
= set_message(outbuf
,1,0,True
);
1628 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1630 /* the returned filename is relative to the directory */
1631 s
= strrchr_m(fname
, '/');
1638 p
= smb_buf(outbuf
);
1639 SSVALS(p
, 0, -1); /* what is this? not in spec */
1640 SSVAL(p
, 2, strlen(s
));
1642 p
+= srvstr_push(outbuf
, p
, s
, -1, STR_ASCII
);
1643 outsize
= set_message_end(outbuf
, p
);
1645 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1646 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1649 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1650 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1652 DEBUG( 2, ( "created temp file %s\n", fname
) );
1653 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1654 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1656 END_PROFILE(SMBctemp
);
1661 /*******************************************************************
1662 check if a user is allowed to delete a file
1663 ********************************************************************/
1664 static BOOL
can_delete(char *fname
,connection_struct
*conn
, int dirtype
)
1666 SMB_STRUCT_STAT sbuf
;
1669 if (!CAN_WRITE(conn
)) return(False
);
1671 if (conn
->vfs_ops
.lstat(conn
,fname
,&sbuf
) != 0) return(False
);
1672 fmode
= dos_mode(conn
,fname
,&sbuf
);
1673 if (fmode
& aDIR
) return(False
);
1674 if (!lp_delete_readonly(SNUM(conn
))) {
1675 if (fmode
& aRONLY
) return(False
);
1677 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1679 if (!check_file_sharing(conn
,fname
,False
)) return(False
);
1683 /****************************************************************************
1684 The guts of the unlink command, split out so it may be called by the NT SMB
1686 ****************************************************************************/
1688 NTSTATUS
unlink_internals(connection_struct
*conn
, int dirtype
, char *name
)
1694 NTSTATUS error
= NT_STATUS_OK
;
1697 BOOL bad_path
= False
;
1699 SMB_STRUCT_STAT sbuf
;
1701 *directory
= *mask
= 0;
1703 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1705 p
= strrchr_m(name
,'/');
1707 pstrcpy(directory
,"./");
1711 pstrcpy(directory
,name
);
1716 * We should only check the mangled cache
1717 * here if unix_convert failed. This means
1718 * that the path in 'mask' doesn't exist
1719 * on the file system and so we need to look
1720 * for a possible mangle. This patch from
1721 * Tine Smukavec <valentin.smukavec@hermes.si>.
1724 if (!rc
&& is_mangled(mask
))
1725 check_mangled_cache( mask
);
1727 has_wild
= ms_has_wild(mask
);
1730 pstrcat(directory
,"/");
1731 pstrcat(directory
,mask
);
1732 if (!can_delete(directory
,conn
,dirtype
)) {
1733 return NT_STATUS_SHARING_VIOLATION
;
1735 if (vfs_unlink(conn
,directory
) == 0) {
1739 exists
= vfs_file_exist(conn
,directory
,&sbuf
);
1741 void *dirptr
= NULL
;
1744 if (check_name(directory
,conn
))
1745 dirptr
= OpenDir(conn
, directory
, True
);
1747 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1748 the pattern matches against the long name, otherwise the short name
1749 We don't implement this yet XXXX
1753 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1755 if (strequal(mask
,"????????.???"))
1758 while ((dname
= ReadDirName(dirptr
))) {
1760 pstrcpy(fname
,dname
);
1762 if(!mask_match(fname
, mask
, case_sensitive
)) continue;
1764 error
= NT_STATUS_ACCESS_DENIED
;
1765 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1766 if (!can_delete(fname
,conn
,dirtype
)) continue;
1767 if (vfs_unlink(conn
,fname
) == 0) count
++;
1768 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
1774 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
1775 error
= map_nt_error_from_unix(errno
);
1781 /****************************************************************************
1783 ****************************************************************************/
1785 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
1792 START_PROFILE(SMBunlink
);
1794 dirtype
= SVAL(inbuf
,smb_vwv0
);
1796 srvstr_pull(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), -1, STR_TERMINATE
);
1798 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
1800 DEBUG(3,("reply_unlink : %s\n",name
));
1802 status
= unlink_internals(conn
, dirtype
, name
);
1803 if (!NT_STATUS_IS_OK(status
)) return ERROR_NT(status
);
1806 * Win2k needs a changenotify request response before it will
1807 * update after a rename..
1809 process_pending_change_notify_queue((time_t)0);
1811 outsize
= set_message(outbuf
,0,0,True
);
1813 END_PROFILE(SMBunlink
);
1817 /****************************************************************************
1819 ****************************************************************************/
1821 void fail_readraw(void)
1824 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)\n",
1826 exit_server(errstr
);
1829 /****************************************************************************
1830 Reply to a readbraw (core+ protocol).
1831 ****************************************************************************/
1833 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1835 size_t maxcount
,mincount
;
1838 char *header
= outbuf
;
1841 START_PROFILE(SMBreadbraw
);
1844 * Special check if an oplock break has been issued
1845 * and the readraw request croses on the wire, we must
1846 * return a zero length response here.
1849 if(global_oplock_break
) {
1850 _smb_setlen(header
,0);
1851 if (write_data(smbd_server_fd(),header
,4) != 4)
1853 DEBUG(5,("readbraw - oplock break finished\n"));
1854 END_PROFILE(SMBreadbraw
);
1858 fsp
= file_fsp(inbuf
,smb_vwv0
);
1860 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1862 * fsp could be NULL here so use the value from the packet. JRA.
1864 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
1865 _smb_setlen(header
,0);
1866 if (write_data(smbd_server_fd(),header
,4) != 4)
1868 END_PROFILE(SMBreadbraw
);
1872 CHECK_FSP(fsp
,conn
);
1874 flush_write_cache(fsp
, READRAW_FLUSH
);
1876 startpos
= IVAL(inbuf
,smb_vwv1
);
1877 if(CVAL(inbuf
,smb_wct
) == 10) {
1879 * This is a large offset (64 bit) read.
1881 #ifdef LARGE_SMB_OFF_T
1883 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
1885 #else /* !LARGE_SMB_OFF_T */
1888 * Ensure we haven't been sent a >32 bit offset.
1891 if(IVAL(inbuf
,smb_vwv8
) != 0) {
1892 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1893 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
1894 _smb_setlen(header
,0);
1895 if (write_data(smbd_server_fd(),header
,4) != 4)
1897 END_PROFILE(SMBreadbraw
);
1901 #endif /* LARGE_SMB_OFF_T */
1904 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
1905 _smb_setlen(header
,0);
1906 if (write_data(smbd_server_fd(),header
,4) != 4)
1908 END_PROFILE(SMBreadbraw
);
1912 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
1913 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
1915 /* ensure we don't overrun the packet size */
1916 maxcount
= MIN(65535,maxcount
);
1917 maxcount
= MAX(mincount
,maxcount
);
1919 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1920 SMB_OFF_T size
= fsp
->size
;
1921 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
1923 if (size
< sizeneeded
) {
1925 if (vfs_fstat(fsp
,fsp
->fd
,&st
) == 0)
1927 if (!fsp
->can_write
)
1931 if (startpos
>= size
)
1934 nread
= MIN(maxcount
,(size
- startpos
));
1937 if (nread
< mincount
)
1940 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp
->fnum
, (double)startpos
,
1941 (int)maxcount
, (int)mincount
, (int)nread
) );
1944 ret
= read_file(fsp
,header
+4,startpos
,nread
);
1949 _smb_setlen(header
,ret
);
1950 if (write_data(smbd_server_fd(),header
,4+ret
) != 4+ret
)
1953 DEBUG(5,("readbraw finished\n"));
1954 END_PROFILE(SMBreadbraw
);
1958 /****************************************************************************
1959 reply to a lockread (core+ protocol)
1960 ****************************************************************************/
1961 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
1969 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1970 START_PROFILE(SMBlockread
);
1972 CHECK_FSP(fsp
,conn
);
1975 release_level_2_oplocks_on_change(fsp
);
1977 numtoread
= SVAL(inbuf
,smb_vwv1
);
1978 startpos
= IVAL(inbuf
,smb_vwv2
);
1980 outsize
= set_message(outbuf
,5,3,True
);
1981 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1982 data
= smb_buf(outbuf
) + 3;
1985 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1986 * protocol request that predates the read/write lock concept.
1987 * Thus instead of asking for a read lock here we need to ask
1988 * for a write lock. JRA.
1991 status
= do_lock(fsp
, conn
, SVAL(inbuf
,smb_pid
),
1992 (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
);
1994 if (NT_STATUS_V(status
)) {
1995 if (lp_blocking_locks(SNUM(conn
))) {
1997 * A blocking lock was requested. Package up
1998 * this smb into a queued request and push it
1999 * onto the blocking lock queue.
2001 if(push_blocking_lock_request(inbuf
, length
, -1, 0))
2002 END_PROFILE(SMBlockread
);
2005 END_PROFILE(SMBlockread
);
2006 return ERROR_NT(status
);
2009 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2012 END_PROFILE(SMBlockread
);
2013 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2017 SSVAL(outbuf
,smb_vwv0
,nread
);
2018 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2019 SSVAL(smb_buf(outbuf
),1,nread
);
2021 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2022 fsp
->fnum
, (int)numtoread
, (int)nread
));
2024 END_PROFILE(SMBlockread
);
2029 /****************************************************************************
2031 ****************************************************************************/
2033 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2040 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2041 START_PROFILE(SMBread
);
2043 CHECK_FSP(fsp
,conn
);
2046 numtoread
= SVAL(inbuf
,smb_vwv1
);
2047 startpos
= IVAL(inbuf
,smb_vwv2
);
2050 outsize
= set_message(outbuf
,5,3,True
);
2051 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
2052 data
= smb_buf(outbuf
) + 3;
2054 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2055 END_PROFILE(SMBread
);
2056 return ERROR_DOS(ERRDOS
,ERRlock
);
2060 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2063 END_PROFILE(SMBread
);
2064 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2068 SSVAL(outbuf
,smb_vwv0
,nread
);
2069 SSVAL(outbuf
,smb_vwv5
,nread
+3);
2070 CVAL(smb_buf(outbuf
),0) = 1;
2071 SSVAL(smb_buf(outbuf
),1,nread
);
2073 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2074 fsp
->fnum
, (int)numtoread
, (int)nread
) );
2076 END_PROFILE(SMBread
);
2081 /****************************************************************************
2082 reply to a read and X
2083 ****************************************************************************/
2084 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2086 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2087 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2088 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
2089 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
2092 START_PROFILE(SMBreadX
);
2094 /* If it's an IPC, pass off the pipe handler. */
2096 END_PROFILE(SMBreadX
);
2097 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
2100 CHECK_FSP(fsp
,conn
);
2103 set_message(outbuf
,12,0,True
);
2104 data
= smb_buf(outbuf
);
2106 if(CVAL(inbuf
,smb_wct
) == 12) {
2107 #ifdef LARGE_SMB_OFF_T
2109 * This is a large offset (64 bit) read.
2111 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
2113 #else /* !LARGE_SMB_OFF_T */
2116 * Ensure we haven't been sent a >32 bit offset.
2119 if(IVAL(inbuf
,smb_vwv10
) != 0) {
2120 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2121 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
2122 END_PROFILE(SMBreadX
);
2123 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2126 #endif /* LARGE_SMB_OFF_T */
2130 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2131 END_PROFILE(SMBreadX
);
2132 return ERROR_DOS(ERRDOS
,ERRlock
);
2134 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
2137 END_PROFILE(SMBreadX
);
2138 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2141 SSVAL(outbuf
,smb_vwv5
,nread
);
2142 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
2143 SSVAL(smb_buf(outbuf
),-2,nread
);
2145 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2146 fsp
->fnum
, (int)smb_mincnt
, (int)smb_maxcnt
, (int)nread
) );
2148 END_PROFILE(SMBreadX
);
2149 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2152 /****************************************************************************
2153 reply to a writebraw (core+ or LANMAN1.0 protocol)
2154 ****************************************************************************/
2156 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2159 ssize_t total_written
=0;
2160 size_t numtowrite
=0;
2165 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2167 START_PROFILE(SMBwritebraw
);
2169 CHECK_FSP(fsp
,conn
);
2172 tcount
= IVAL(inbuf
,smb_vwv1
);
2173 startpos
= IVAL(inbuf
,smb_vwv3
);
2174 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2176 /* We have to deal with slightly different formats depending
2177 on whether we are using the core+ or lanman1.0 protocol */
2179 if(Protocol
<= PROTOCOL_COREPLUS
) {
2180 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2181 data
= smb_buf(inbuf
);
2183 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2184 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2187 /* force the error type */
2188 CVAL(inbuf
,smb_com
) = SMBwritec
;
2189 CVAL(outbuf
,smb_com
) = SMBwritec
;
2191 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2192 END_PROFILE(SMBwritebraw
);
2193 return(ERROR_DOS(ERRDOS
,ERRlock
));
2197 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2199 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2200 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2202 if (nwritten
< numtowrite
) {
2203 END_PROFILE(SMBwritebraw
);
2204 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2207 total_written
= nwritten
;
2209 /* Return a message to the redirector to tell it to send more bytes */
2210 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
2211 SSVALS(outbuf
,smb_vwv0
,-1);
2212 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2213 if (!send_smb(smbd_server_fd(),outbuf
))
2214 exit_server("reply_writebraw: send_smb failed.\n");
2216 /* Now read the raw data into the buffer and write it */
2217 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2218 exit_server("secondary writebraw failed");
2221 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2222 numtowrite
= smb_len(inbuf
);
2224 /* Set up outbuf to return the correct return */
2225 outsize
= set_message(outbuf
,1,0,True
);
2226 CVAL(outbuf
,smb_com
) = SMBwritec
;
2227 SSVAL(outbuf
,smb_vwv0
,total_written
);
2229 if (numtowrite
!= 0) {
2231 if (numtowrite
> BUFFER_SIZE
) {
2232 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2233 (unsigned int)numtowrite
));
2234 exit_server("secondary writebraw failed");
2237 if (tcount
> nwritten
+numtowrite
) {
2238 DEBUG(3,("Client overestimated the write %d %d %d\n",
2239 (int)tcount
,(int)nwritten
,(int)numtowrite
));
2242 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
2243 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2245 exit_server("secondary writebraw failed");
2248 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
2250 if (nwritten
< (ssize_t
)numtowrite
) {
2251 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2252 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2256 total_written
+= nwritten
;
2259 if ((lp_syncalways(SNUM(conn
)) || write_through
) && lp_strict_sync(SNUM(conn
)))
2260 sync_file(conn
,fsp
);
2262 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2263 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
2265 /* we won't return a status if write through is not selected - this follows what WfWg does */
2266 END_PROFILE(SMBwritebraw
);
2267 if (!write_through
&& total_written
==tcount
) {
2269 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2270 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2272 if (!send_keepalive(smbd_server_fd()))
2273 exit_server("reply_writebraw: send of keepalive failed");
2280 /****************************************************************************
2281 reply to a writeunlock (core+)
2282 ****************************************************************************/
2284 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
,
2285 int size
, int dum_buffsize
)
2287 ssize_t nwritten
= -1;
2292 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2294 START_PROFILE(SMBwriteunlock
);
2296 CHECK_FSP(fsp
,conn
);
2299 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2300 startpos
= IVAL(inbuf
,smb_vwv2
);
2301 data
= smb_buf(inbuf
) + 3;
2303 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
,
2304 WRITE_LOCK
,False
)) {
2305 END_PROFILE(SMBwriteunlock
);
2306 return ERROR_DOS(ERRDOS
,ERRlock
);
2309 /* The special X/Open SMB protocol handling of
2310 zero length writes is *NOT* done for
2315 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2317 if (lp_syncalways(SNUM(conn
)))
2318 sync_file(conn
,fsp
);
2320 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2321 END_PROFILE(SMBwriteunlock
);
2322 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2325 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)numtowrite
,
2326 (SMB_BIG_UINT
)startpos
);
2327 if (NT_STATUS_V(status
)) {
2328 END_PROFILE(SMBwriteunlock
);
2329 return ERROR_NT(status
);
2332 outsize
= set_message(outbuf
,1,0,True
);
2334 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2336 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2337 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2339 END_PROFILE(SMBwriteunlock
);
2344 /****************************************************************************
2346 ****************************************************************************/
2348 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2351 ssize_t nwritten
= -1;
2354 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2356 START_PROFILE(SMBwrite
);
2358 /* If it's an IPC, pass off the pipe handler. */
2360 END_PROFILE(SMBwrite
);
2361 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2364 CHECK_FSP(fsp
,conn
);
2367 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2368 startpos
= IVAL(inbuf
,smb_vwv2
);
2369 data
= smb_buf(inbuf
) + 3;
2371 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2372 END_PROFILE(SMBwrite
);
2373 return ERROR_DOS(ERRDOS
,ERRlock
);
2376 /* X/Open SMB protocol says that if smb_vwv1 is
2377 zero then the file size should be extended or
2378 truncated to the size given in smb_vwv[2-3] */
2379 if(numtowrite
== 0) {
2380 /* This is actually an allocate call, not set EOF. JRA */
2381 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2383 END_PROFILE(SMBwrite
);
2384 return ERROR_NT(NT_STATUS_DISK_FULL
);
2387 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2389 if (lp_syncalways(SNUM(conn
)))
2390 sync_file(conn
,fsp
);
2392 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2393 END_PROFILE(SMBwrite
);
2394 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2397 outsize
= set_message(outbuf
,1,0,True
);
2399 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2401 if (nwritten
< (ssize_t
)numtowrite
) {
2402 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2403 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2406 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2407 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2409 END_PROFILE(SMBwrite
);
2414 /****************************************************************************
2415 reply to a write and X
2416 ****************************************************************************/
2417 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2419 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2420 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2421 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2422 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2423 ssize_t nwritten
= -1;
2424 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2425 unsigned int smblen
= smb_len(inbuf
);
2427 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2428 START_PROFILE(SMBwriteX
);
2430 /* If it's an IPC, pass off the pipe handler. */
2432 END_PROFILE(SMBwriteX
);
2433 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2436 CHECK_FSP(fsp
,conn
);
2439 /* Deal with possible LARGE_WRITEX */
2441 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2443 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2444 END_PROFILE(SMBwriteX
);
2445 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2448 data
= smb_base(inbuf
) + smb_doff
;
2450 if(CVAL(inbuf
,smb_wct
) == 14) {
2451 #ifdef LARGE_SMB_OFF_T
2453 * This is a large offset (64 bit) write.
2455 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2457 #else /* !LARGE_SMB_OFF_T */
2460 * Ensure we haven't been sent a >32 bit offset.
2463 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2464 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2465 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2466 END_PROFILE(SMBwriteX
);
2467 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2470 #endif /* LARGE_SMB_OFF_T */
2473 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2474 END_PROFILE(SMBwriteX
);
2475 return ERROR_DOS(ERRDOS
,ERRlock
);
2478 /* X/Open SMB protocol says that, unlike SMBwrite
2479 if the length is zero then NO truncation is
2480 done, just a write of zero. To truncate a file,
2485 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2487 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2488 END_PROFILE(SMBwriteX
);
2489 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2492 set_message(outbuf
,6,0,True
);
2494 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2496 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2498 if (nwritten
< (ssize_t
)numtowrite
) {
2499 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2500 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2503 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2504 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2506 if (lp_syncalways(SNUM(conn
)) || write_through
)
2507 sync_file(conn
,fsp
);
2509 END_PROFILE(SMBwriteX
);
2510 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2514 /****************************************************************************
2516 ****************************************************************************/
2518 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2524 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2525 START_PROFILE(SMBlseek
);
2527 CHECK_FSP(fsp
,conn
);
2529 flush_write_cache(fsp
, SEEK_FLUSH
);
2531 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2532 startpos
= IVALS(inbuf
,smb_vwv2
);
2535 case 0: umode
= SEEK_SET
; break;
2536 case 1: umode
= SEEK_CUR
; break;
2537 case 2: umode
= SEEK_END
; break;
2539 umode
= SEEK_SET
; break;
2542 if((res
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
2544 * Check for the special case where a seek before the start
2545 * of the file sets the offset to zero. Added in the CIFS spec,
2549 if(errno
== EINVAL
) {
2550 SMB_OFF_T current_pos
= startpos
;
2552 if(umode
== SEEK_CUR
) {
2554 if((current_pos
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,0,SEEK_CUR
)) == -1) {
2555 END_PROFILE(SMBlseek
);
2556 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2559 current_pos
+= startpos
;
2561 } else if (umode
== SEEK_END
) {
2563 SMB_STRUCT_STAT sbuf
;
2565 if(vfs_fstat(fsp
,fsp
->fd
, &sbuf
) == -1) {
2566 END_PROFILE(SMBlseek
);
2567 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2570 current_pos
+= sbuf
.st_size
;
2574 res
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,0,SEEK_SET
);
2578 END_PROFILE(SMBlseek
);
2579 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2585 outsize
= set_message(outbuf
,2,0,True
);
2586 SIVAL(outbuf
,smb_vwv0
,res
);
2588 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2589 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
2591 END_PROFILE(SMBlseek
);
2595 /****************************************************************************
2597 ****************************************************************************/
2599 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2601 int outsize
= set_message(outbuf
,0,0,True
);
2602 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2603 START_PROFILE(SMBflush
);
2605 CHECK_FSP(fsp
,conn
);
2608 file_sync_all(conn
);
2610 sync_file(conn
,fsp
);
2613 DEBUG(3,("flush\n"));
2614 END_PROFILE(SMBflush
);
2619 /****************************************************************************
2621 ****************************************************************************/
2622 int reply_exit(connection_struct
*conn
,
2623 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2626 START_PROFILE(SMBexit
);
2627 outsize
= set_message(outbuf
,0,0,True
);
2629 DEBUG(3,("exit\n"));
2631 END_PROFILE(SMBexit
);
2636 /****************************************************************************
2637 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2638 ****************************************************************************/
2639 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2644 int32 eclass
= 0, err
= 0;
2645 files_struct
*fsp
= NULL
;
2646 START_PROFILE(SMBclose
);
2648 outsize
= set_message(outbuf
,0,0,True
);
2650 /* If it's an IPC, pass off to the pipe handler. */
2652 END_PROFILE(SMBclose
);
2653 return reply_pipe_close(conn
, inbuf
,outbuf
);
2656 fsp
= file_fsp(inbuf
,smb_vwv0
);
2659 * We can only use CHECK_FSP if we know it's not a directory.
2662 if(!fsp
|| (fsp
->conn
!= conn
)) {
2663 END_PROFILE(SMBclose
);
2664 return ERROR_DOS(ERRDOS
,ERRbadfid
);
2667 if(fsp
->is_directory
|| fsp
->stat_open
) {
2669 * Special case - close NT SMB directory or stat file
2672 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
2673 close_file(fsp
,True
);
2676 * Close ordinary file.
2681 * If there was a modify time outstanding,
2682 * try and set it here.
2684 if(fsp
->pending_modtime
)
2685 set_filetime(conn
, fsp
->fsp_name
, fsp
->pending_modtime
);
2688 * Now take care of any time sent in the close.
2690 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2692 /* try and set the date */
2693 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2695 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2697 conn
->num_files_open
));
2700 * close_file() returns the unix errno if an error
2701 * was detected on close - normally this is due to
2702 * a disk full error. If not then it was probably an I/O error.
2705 if((close_err
= close_file(fsp
,True
)) != 0) {
2707 END_PROFILE(SMBclose
);
2708 return (UNIXERROR(ERRHRD
,ERRgeneral
));
2712 /* We have a cached error */
2714 END_PROFILE(SMBclose
);
2715 return ERROR_DOS(eclass
,err
);
2718 END_PROFILE(SMBclose
);
2723 /****************************************************************************
2724 reply to a writeclose (Core+ protocol)
2725 ****************************************************************************/
2727 int reply_writeclose(connection_struct
*conn
,
2728 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2731 ssize_t nwritten
= -1;
2737 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2738 START_PROFILE(SMBwriteclose
);
2740 CHECK_FSP(fsp
,conn
);
2743 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2744 startpos
= IVAL(inbuf
,smb_vwv2
);
2745 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2746 data
= smb_buf(inbuf
) + 1;
2748 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2749 END_PROFILE(SMBwriteclose
);
2750 return ERROR_DOS(ERRDOS
,ERRlock
);
2753 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2755 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2757 close_err
= close_file(fsp
,True
);
2759 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2760 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
2761 conn
->num_files_open
));
2763 if (nwritten
<= 0) {
2764 END_PROFILE(SMBwriteclose
);
2765 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2768 if(close_err
!= 0) {
2770 END_PROFILE(SMBwriteclose
);
2771 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2774 outsize
= set_message(outbuf
,1,0,True
);
2776 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2777 END_PROFILE(SMBwriteclose
);
2782 /****************************************************************************
2784 ****************************************************************************/
2785 int reply_lock(connection_struct
*conn
,
2786 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
2788 int outsize
= set_message(outbuf
,0,0,True
);
2789 SMB_BIG_UINT count
,offset
;
2791 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2792 START_PROFILE(SMBlock
);
2794 CHECK_FSP(fsp
,conn
);
2796 release_level_2_oplocks_on_change(fsp
);
2798 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2799 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2801 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2802 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
2804 status
= do_lock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
, WRITE_LOCK
);
2805 if (NT_STATUS_V(status
)) {
2806 if (lp_blocking_locks(SNUM(conn
))) {
2808 * A blocking lock was requested. Package up
2809 * this smb into a queued request and push it
2810 * onto the blocking lock queue.
2812 if(push_blocking_lock_request(inbuf
, length
, -1, 0)) {
2813 END_PROFILE(SMBlock
);
2817 END_PROFILE(SMBlock
);
2818 return ERROR_NT(status
);
2821 END_PROFILE(SMBlock
);
2826 /****************************************************************************
2828 ****************************************************************************/
2829 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2832 int outsize
= set_message(outbuf
,0,0,True
);
2833 SMB_BIG_UINT count
,offset
;
2835 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2836 START_PROFILE(SMBunlock
);
2838 CHECK_FSP(fsp
,conn
);
2840 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2841 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2843 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
);
2844 if (NT_STATUS_V(status
)) {
2845 END_PROFILE(SMBunlock
);
2846 return ERROR_NT(status
);
2849 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2850 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
2852 END_PROFILE(SMBunlock
);
2857 /****************************************************************************
2859 ****************************************************************************/
2860 int reply_tdis(connection_struct
*conn
,
2861 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2863 int outsize
= set_message(outbuf
,0,0,True
);
2865 START_PROFILE(SMBtdis
);
2867 vuid
= SVAL(inbuf
,smb_uid
);
2870 DEBUG(4,("Invalid connection in tdis\n"));
2871 END_PROFILE(SMBtdis
);
2872 return ERROR_DOS(ERRSRV
,ERRinvnid
);
2877 close_cnum(conn
,vuid
);
2879 END_PROFILE(SMBtdis
);
2885 /****************************************************************************
2887 ****************************************************************************/
2888 int reply_echo(connection_struct
*conn
,
2889 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2891 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2893 unsigned int data_len
= smb_buflen(inbuf
);
2894 int outsize
= set_message(outbuf
,1,data_len
,True
);
2895 START_PROFILE(SMBecho
);
2897 data_len
= MIN(data_len
, (sizeof(inbuf
)-(smb_buf(inbuf
)-inbuf
)));
2899 /* copy any incoming data back out */
2901 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2903 if (smb_reverb
> 100) {
2904 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2908 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2909 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2911 smb_setlen(outbuf
,outsize
- 4);
2913 if (!send_smb(smbd_server_fd(),outbuf
))
2914 exit_server("reply_echo: send_smb failed.\n");
2917 DEBUG(3,("echo %d times\n", smb_reverb
));
2921 END_PROFILE(SMBecho
);
2926 /****************************************************************************
2927 reply to a printopen
2928 ****************************************************************************/
2929 int reply_printopen(connection_struct
*conn
,
2930 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2934 START_PROFILE(SMBsplopen
);
2936 if (!CAN_PRINT(conn
)) {
2937 END_PROFILE(SMBsplopen
);
2938 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2941 /* Open for exclusive use, write only. */
2942 fsp
= print_fsp_open(conn
);
2945 END_PROFILE(SMBsplopen
);
2946 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2949 outsize
= set_message(outbuf
,1,0,True
);
2950 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2952 DEBUG(3,("openprint fd=%d fnum=%d\n",
2953 fsp
->fd
, fsp
->fnum
));
2955 END_PROFILE(SMBsplopen
);
2960 /****************************************************************************
2961 reply to a printclose
2962 ****************************************************************************/
2963 int reply_printclose(connection_struct
*conn
,
2964 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2966 int outsize
= set_message(outbuf
,0,0,True
);
2967 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2969 START_PROFILE(SMBsplclose
);
2971 CHECK_FSP(fsp
,conn
);
2973 if (!CAN_PRINT(conn
)) {
2974 END_PROFILE(SMBsplclose
);
2975 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2978 DEBUG(3,("printclose fd=%d fnum=%d\n",
2979 fsp
->fd
,fsp
->fnum
));
2981 close_err
= close_file(fsp
,True
);
2983 if(close_err
!= 0) {
2985 END_PROFILE(SMBsplclose
);
2986 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2989 END_PROFILE(SMBsplclose
);
2994 /****************************************************************************
2995 reply to a printqueue
2996 ****************************************************************************/
2997 int reply_printqueue(connection_struct
*conn
,
2998 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3000 int outsize
= set_message(outbuf
,2,3,True
);
3001 int max_count
= SVAL(inbuf
,smb_vwv0
);
3002 int start_index
= SVAL(inbuf
,smb_vwv1
);
3003 START_PROFILE(SMBsplretq
);
3005 /* we used to allow the client to get the cnum wrong, but that
3006 is really quite gross and only worked when there was only
3007 one printer - I think we should now only accept it if they
3008 get it right (tridge) */
3009 if (!CAN_PRINT(conn
)) {
3010 END_PROFILE(SMBsplretq
);
3011 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3014 SSVAL(outbuf
,smb_vwv0
,0);
3015 SSVAL(outbuf
,smb_vwv1
,0);
3016 CVAL(smb_buf(outbuf
),0) = 1;
3017 SSVAL(smb_buf(outbuf
),1,0);
3019 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3020 start_index
, max_count
));
3023 print_queue_struct
*queue
= NULL
;
3024 char *p
= smb_buf(outbuf
) + 3;
3025 int count
= print_queue_status(SNUM(conn
), &queue
,NULL
);
3026 int num_to_get
= ABS(max_count
);
3027 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
3033 num_to_get
= MIN(num_to_get
,count
-first
);
3036 for (i
=first
;i
<first
+num_to_get
;i
++) {
3037 put_dos_date2(p
,0,queue
[i
].time
);
3038 CVAL(p
,4) = (queue
[i
].status
==LPQ_PRINTING
?2:3);
3039 SSVAL(p
,5, queue
[i
].job
);
3040 SIVAL(p
,7,queue
[i
].size
);
3042 srvstr_push(outbuf
, p
+12, queue
[i
].user
, 16, STR_ASCII
);
3047 outsize
= set_message(outbuf
,2,28*count
+3,False
);
3048 SSVAL(outbuf
,smb_vwv0
,count
);
3049 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
3050 CVAL(smb_buf(outbuf
),0) = 1;
3051 SSVAL(smb_buf(outbuf
),1,28*count
);
3056 DEBUG(3,("%d entries returned in queue\n",count
));
3059 END_PROFILE(SMBsplretq
);
3064 /****************************************************************************
3065 reply to a printwrite
3066 ****************************************************************************/
3067 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3070 int outsize
= set_message(outbuf
,0,0,True
);
3072 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
3073 START_PROFILE(SMBsplwr
);
3075 if (!CAN_PRINT(conn
)) {
3076 END_PROFILE(SMBsplwr
);
3077 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3080 CHECK_FSP(fsp
,conn
);
3083 numtowrite
= SVAL(smb_buf(inbuf
),1);
3084 data
= smb_buf(inbuf
) + 3;
3086 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
3087 END_PROFILE(SMBsplwr
);
3088 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3091 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
3093 END_PROFILE(SMBsplwr
);
3098 /****************************************************************************
3099 The guts of the mkdir command, split out so it may be called by the NT SMB
3101 ****************************************************************************/
3102 NTSTATUS
mkdir_internal(connection_struct
*conn
, pstring directory
)
3104 BOOL bad_path
= False
;
3105 SMB_STRUCT_STAT sbuf
;
3108 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3110 if (check_name(directory
, conn
))
3111 ret
= vfs_mkdir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3114 return map_nt_error_from_unix(errno
);
3117 return NT_STATUS_OK
;
3120 /****************************************************************************
3122 ****************************************************************************/
3124 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3129 START_PROFILE(SMBmkdir
);
3131 srvstr_pull(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), -1, STR_TERMINATE
);
3133 status
= mkdir_internal(conn
, directory
);
3134 if (!NT_STATUS_IS_OK(status
)) return ERROR_NT(status
);
3136 outsize
= set_message(outbuf
,0,0,True
);
3138 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
3140 END_PROFILE(SMBmkdir
);
3144 /****************************************************************************
3145 Static function used by reply_rmdir to delete an entire directory
3146 tree recursively. Return False on ok, True on fail.
3147 ****************************************************************************/
3149 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
3153 void *dirptr
= OpenDir(conn
, directory
, False
);
3158 while((dname
= ReadDirName(dirptr
))) {
3162 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3165 /* Construct the full name. */
3166 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3172 pstrcpy(fullname
, directory
);
3173 pstrcat(fullname
, "/");
3174 pstrcat(fullname
, dname
);
3176 if(conn
->vfs_ops
.lstat(conn
,fullname
, &st
) != 0) {
3181 if(st
.st_mode
& S_IFDIR
) {
3182 if(recursive_rmdir(conn
, fullname
)!=0) {
3186 if(vfs_rmdir(conn
,fullname
) != 0) {
3190 } else if(vfs_unlink(conn
,fullname
) != 0) {
3199 /****************************************************************************
3200 The internals of the rmdir code - called elsewhere.
3201 ****************************************************************************/
3203 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
3207 ok
= (vfs_rmdir(conn
,directory
) == 0);
3208 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
3210 * Check to see if the only thing in this directory are
3211 * vetoed files/directories. If so then delete them and
3212 * retry. If we fail to delete any of them (and we *don't*
3213 * do a recursive delete) then fail the rmdir.
3215 BOOL all_veto_files
= True
;
3217 void *dirptr
= OpenDir(conn
, directory
, False
);
3219 if(dirptr
!= NULL
) {
3220 int dirpos
= TellDir(dirptr
);
3221 while ((dname
= ReadDirName(dirptr
))) {
3222 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3224 if(!IS_VETO_PATH(conn
, dname
)) {
3225 all_veto_files
= False
;
3230 if(all_veto_files
) {
3231 SeekDir(dirptr
,dirpos
);
3232 while ((dname
= ReadDirName(dirptr
))) {
3236 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3239 /* Construct the full name. */
3240 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3245 pstrcpy(fullname
, directory
);
3246 pstrcat(fullname
, "/");
3247 pstrcat(fullname
, dname
);
3249 if(conn
->vfs_ops
.lstat(conn
,fullname
, &st
) != 0)
3251 if(st
.st_mode
& S_IFDIR
) {
3252 if(lp_recursive_veto_delete(SNUM(conn
))) {
3253 if(recursive_rmdir(conn
, fullname
) != 0)
3256 if(vfs_rmdir(conn
,fullname
) != 0)
3258 } else if(vfs_unlink(conn
,fullname
) != 0)
3262 /* Retry the rmdir */
3263 ok
= (vfs_rmdir(conn
,directory
) == 0);
3273 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory
,strerror(errno
)));
3278 /****************************************************************************
3280 ****************************************************************************/
3282 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3287 BOOL bad_path
= False
;
3288 SMB_STRUCT_STAT sbuf
;
3289 START_PROFILE(SMBrmdir
);
3291 srvstr_pull(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), -1, STR_TERMINATE
);
3293 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3295 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3297 if (check_name(directory
,conn
))
3299 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3300 ok
= rmdir_internals(conn
, directory
);
3305 if((errno
== ENOENT
) && bad_path
)
3307 unix_ERR_class
= ERRDOS
;
3308 unix_ERR_code
= ERRbadpath
;
3310 END_PROFILE(SMBrmdir
);
3311 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3314 outsize
= set_message(outbuf
,0,0,True
);
3316 DEBUG( 3, ( "rmdir %s\n", directory
) );
3318 END_PROFILE(SMBrmdir
);
3323 /*******************************************************************
3324 resolve wildcards in a filename rename
3325 ********************************************************************/
3326 static BOOL
resolve_wildcards(char *name1
,char *name2
)
3328 fstring root1
,root2
;
3332 name1
= strrchr_m(name1
,'/');
3333 name2
= strrchr_m(name2
,'/');
3335 if (!name1
|| !name2
) return(False
);
3337 fstrcpy(root1
,name1
);
3338 fstrcpy(root2
,name2
);
3339 p
= strrchr_m(root1
,'.');
3346 p
= strrchr_m(root2
,'.');
3378 pstrcpy(name2
,root2
);
3381 pstrcat(name2
,ext2
);
3387 /*******************************************************************
3388 check if a user is allowed to rename a file
3389 ********************************************************************/
3390 static BOOL
can_rename(char *fname
,connection_struct
*conn
)
3392 SMB_STRUCT_STAT sbuf
;
3394 if (!CAN_WRITE(conn
)) return(False
);
3396 if (conn
->vfs_ops
.lstat(conn
,fname
,&sbuf
) != 0) return(False
);
3397 if (!check_file_sharing(conn
,fname
,True
)) return(False
);
3401 /****************************************************************************
3402 The guts of the rename command, split out so it may be called by the NT SMB
3404 ****************************************************************************/
3405 NTSTATUS
rename_internals(connection_struct
*conn
,
3407 char *newname
, BOOL replace_if_exists
)
3411 pstring newname_last_component
;
3414 BOOL bad_path1
= False
;
3415 BOOL bad_path2
= False
;
3417 NTSTATUS error
= NT_STATUS_OK
;
3420 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3422 *directory
= *mask
= 0;
3424 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
3425 unix_convert(newname
,conn
,newname_last_component
,&bad_path2
,&sbuf2
);
3428 * Split the old name into directory and last component
3429 * strings. Note that unix_convert may have stripped off a
3430 * leading ./ from both name and newname if the rename is
3431 * at the root of the share. We need to make sure either both
3432 * name and newname contain a / character or neither of them do
3433 * as this is checked in resolve_wildcards().
3436 p
= strrchr_m(name
,'/');
3438 pstrcpy(directory
,".");
3442 pstrcpy(directory
,name
);
3444 *p
= '/'; /* Replace needed for exceptional test below. */
3448 * We should only check the mangled cache
3449 * here if unix_convert failed. This means
3450 * that the path in 'mask' doesn't exist
3451 * on the file system and so we need to look
3452 * for a possible mangle. This patch from
3453 * Tine Smukavec <valentin.smukavec@hermes.si>.
3456 if (!rc
&& is_mangled(mask
))
3457 check_mangled_cache( mask
);
3459 has_wild
= ms_has_wild(mask
);
3463 * No wildcards - just process the one file.
3465 BOOL is_short_name
= is_8_3(name
, True
);
3467 /* Add a terminating '/' to the directory name. */
3468 pstrcat(directory
,"/");
3469 pstrcat(directory
,mask
);
3471 /* Ensure newname contains a '/' also */
3472 if(strrchr_m(newname
,'/') == 0) {
3475 pstrcpy(tmpstr
, "./");
3476 pstrcat(tmpstr
, newname
);
3477 pstrcpy(newname
, tmpstr
);
3480 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",
3481 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3482 newname
, newname_last_component
, is_short_name
));
3485 * Check for special case with case preserving and not
3486 * case sensitive, if directory and newname are identical,
3487 * and the old last component differs from the original
3488 * last component only by case, then we should allow
3489 * the rename (user is trying to change the case of the
3492 if((case_sensitive
== False
) &&
3493 (((case_preserve
== True
) &&
3494 (is_short_name
== False
)) ||
3495 ((short_case_preserve
== True
) &&
3496 (is_short_name
== True
))) &&
3497 strcsequal(directory
, newname
)) {
3498 pstring newname_modified_last_component
;
3501 * Get the last component of the modified name.
3502 * Note that we guarantee that newname contains a '/'
3505 p
= strrchr_m(newname
,'/');
3506 pstrcpy(newname_modified_last_component
,p
+1);
3508 if(strcsequal(newname_modified_last_component
,
3509 newname_last_component
) == False
) {
3511 * Replace the modified last component with
3514 pstrcpy(p
+1, newname_last_component
);
3518 if(replace_if_exists
) {
3520 * NT SMB specific flag - rename can overwrite
3521 * file with the same name so don't check for
3525 if(resolve_wildcards(directory
,newname
) &&
3526 can_rename(directory
,conn
) &&
3527 conn
->vfs_ops
.rename(conn
,directory
,newname
) == 0)
3530 if (resolve_wildcards(directory
,newname
) &&
3531 can_rename(directory
,conn
) &&
3532 !vfs_file_exist(conn
,newname
,NULL
) &&
3533 conn
->vfs_ops
.rename(conn
,directory
,newname
) == 0)
3537 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count
!= 0) ? "succeeded" : "failed",
3538 directory
,newname
));
3540 if (!count
) exists
= vfs_file_exist(conn
,directory
,NULL
);
3541 if (!count
&& exists
&& vfs_file_exist(conn
,newname
,NULL
)) {
3543 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3547 * Wildcards - process each file that matches.
3549 void *dirptr
= NULL
;
3553 if (check_name(directory
,conn
))
3554 dirptr
= OpenDir(conn
, directory
, True
);
3557 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3559 if (strequal(mask
,"????????.???"))
3562 while ((dname
= ReadDirName(dirptr
))) {
3565 pstrcpy(fname
,dname
);
3567 if(!mask_match(fname
, mask
, case_sensitive
))
3570 error
= NT_STATUS_ACCESS_DENIED
;
3571 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3572 if (!can_rename(fname
,conn
)) {
3573 DEBUG(6,("rename %s refused\n", fname
));
3576 pstrcpy(destname
,newname
);
3578 if (!resolve_wildcards(fname
,destname
)) {
3579 DEBUG(6,("resolve_wildcards %s %s failed\n",
3584 if (!replace_if_exists
&&
3585 vfs_file_exist(conn
,destname
, NULL
)) {
3586 DEBUG(6,("file_exist %s\n", destname
));
3587 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3591 if (!conn
->vfs_ops
.rename(conn
,fname
,destname
))
3593 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3599 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
3600 error
= map_nt_error_from_unix(errno
);
3606 /****************************************************************************
3608 ****************************************************************************/
3610 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
3619 START_PROFILE(SMBmv
);
3621 p
= smb_buf(inbuf
) + 1;
3622 p
+= srvstr_pull(inbuf
, name
, p
, sizeof(name
), -1, STR_TERMINATE
);
3624 p
+= srvstr_pull(inbuf
, newname
, p
, sizeof(newname
), -1, STR_TERMINATE
);
3626 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3627 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3629 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3631 status
= rename_internals(conn
, name
, newname
, False
);
3632 if (!NT_STATUS_IS_OK(status
)) {
3633 return ERROR_NT(status
);
3637 * Win2k needs a changenotify request response before it will
3638 * update after a rename..
3640 process_pending_change_notify_queue((time_t)0);
3641 outsize
= set_message(outbuf
,0,0,True
);
3647 /*******************************************************************
3648 Copy a file as part of a reply_copy.
3649 ******************************************************************/
3651 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3652 int count
,BOOL target_is_directory
, int *err_ret
)
3655 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
3657 files_struct
*fsp1
,*fsp2
;
3662 pstrcpy(dest
,dest1
);
3663 if (target_is_directory
) {
3664 char *p
= strrchr_m(src
,'/');
3673 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
3676 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3677 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
3682 if (!target_is_directory
&& count
)
3683 ofun
= FILE_EXISTS_OPEN
;
3685 if (vfs_stat(conn
,dest
,&sbuf2
) == -1)
3686 ZERO_STRUCTP(&sbuf2
);
3688 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3689 ofun
,src_sbuf
.st_mode
,0,&Access
,&action
);
3692 close_file(fsp1
,False
);
3696 if ((ofun
&3) == 1) {
3697 if(conn
->vfs_ops
.lseek(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
3698 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
3700 * Stop the copy from occurring.
3703 src_sbuf
.st_size
= 0;
3707 if (src_sbuf
.st_size
)
3708 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
3710 close_file(fsp1
,False
);
3712 * As we are opening fsp1 read-only we only expect
3713 * an error on close on fsp2 if we are out of space.
3714 * Thus we don't look at the error return from the
3717 *err_ret
= close_file(fsp2
,False
);
3719 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
3722 /****************************************************************************
3723 reply to a file copy.
3724 ****************************************************************************/
3725 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3730 pstring mask
,newname
;
3733 int error
= ERRnoaccess
;
3737 int tid2
= SVAL(inbuf
,smb_vwv0
);
3738 int ofun
= SVAL(inbuf
,smb_vwv1
);
3739 int flags
= SVAL(inbuf
,smb_vwv2
);
3740 BOOL target_is_directory
=False
;
3741 BOOL bad_path1
= False
;
3742 BOOL bad_path2
= False
;
3744 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3745 START_PROFILE(SMBcopy
);
3747 *directory
= *mask
= 0;
3750 p
+= srvstr_pull(inbuf
, name
, p
, sizeof(name
), -1, STR_TERMINATE
);
3751 p
+= srvstr_pull(inbuf
, newname
, p
, sizeof(newname
), -1, STR_TERMINATE
);
3753 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
3755 if (tid2
!= conn
->cnum
) {
3756 /* can't currently handle inter share copies XXXX */
3757 DEBUG(3,("Rejecting inter-share copy\n"));
3758 END_PROFILE(SMBcopy
);
3759 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
3762 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3763 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3765 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
3766 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
3768 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
3770 if ((flags
&1) && target_is_directory
) {
3771 END_PROFILE(SMBcopy
);
3772 return ERROR_DOS(ERRDOS
,ERRbadfile
);
3775 if ((flags
&2) && !target_is_directory
) {
3776 END_PROFILE(SMBcopy
);
3777 return ERROR_DOS(ERRDOS
,ERRbadpath
);
3780 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
3781 /* wants a tree copy! XXXX */
3782 DEBUG(3,("Rejecting tree copy\n"));
3783 END_PROFILE(SMBcopy
);
3784 return ERROR_DOS(ERRSRV
,ERRerror
);
3787 p
= strrchr_m(name
,'/');
3789 pstrcpy(directory
,"./");
3793 pstrcpy(directory
,name
);
3798 * We should only check the mangled cache
3799 * here if unix_convert failed. This means
3800 * that the path in 'mask' doesn't exist
3801 * on the file system and so we need to look
3802 * for a possible mangle. This patch from
3803 * Tine Smukavec <valentin.smukavec@hermes.si>.
3806 if (!rc
&& is_mangled(mask
))
3807 check_mangled_cache( mask
);
3809 has_wild
= ms_has_wild(mask
);
3812 pstrcat(directory
,"/");
3813 pstrcat(directory
,mask
);
3814 if (resolve_wildcards(directory
,newname
) &&
3815 copy_file(directory
,newname
,conn
,ofun
,
3816 count
,target_is_directory
,&err
)) count
++;
3819 END_PROFILE(SMBcopy
);
3820 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3822 if (!count
) exists
= vfs_file_exist(conn
,directory
,NULL
);
3824 void *dirptr
= NULL
;
3828 if (check_name(directory
,conn
))
3829 dirptr
= OpenDir(conn
, directory
, True
);
3834 if (strequal(mask
,"????????.???"))
3837 while ((dname
= ReadDirName(dirptr
))) {
3839 pstrcpy(fname
,dname
);
3841 if(!mask_match(fname
, mask
, case_sensitive
))
3844 error
= ERRnoaccess
;
3845 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
3846 pstrcpy(destname
,newname
);
3847 if (resolve_wildcards(fname
,destname
) &&
3848 copy_file(fname
,destname
,conn
,ofun
,
3849 count
,target_is_directory
,&err
)) count
++;
3850 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
3858 /* Error on close... */
3860 END_PROFILE(SMBcopy
);
3861 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3865 END_PROFILE(SMBcopy
);
3866 return ERROR_DOS(ERRDOS
,error
);
3869 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
3871 unix_ERR_class
= ERRDOS
;
3872 unix_ERR_code
= ERRbadpath
;
3874 END_PROFILE(SMBcopy
);
3875 return(UNIXERROR(ERRDOS
,error
));
3879 outsize
= set_message(outbuf
,1,0,True
);
3880 SSVAL(outbuf
,smb_vwv0
,count
);
3882 END_PROFILE(SMBcopy
);
3886 /****************************************************************************
3888 ****************************************************************************/
3889 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3895 START_PROFILE(pathworks_setdir
);
3898 if (!CAN_SETDIR(snum
)) {
3899 END_PROFILE(pathworks_setdir
);
3900 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3903 srvstr_pull(inbuf
, newdir
, smb_buf(inbuf
) + 1, sizeof(newdir
), -1, STR_TERMINATE
);
3905 if (strlen(newdir
) == 0) {
3908 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
3910 string_set(&conn
->connectpath
,newdir
);
3915 END_PROFILE(pathworks_setdir
);
3916 return ERROR_DOS(ERRDOS
,ERRbadpath
);
3919 outsize
= set_message(outbuf
,0,0,True
);
3920 CVAL(outbuf
,smb_reh
) = CVAL(inbuf
,smb_reh
);
3922 DEBUG(3,("setdir %s\n", newdir
));
3924 END_PROFILE(pathworks_setdir
);
3928 /****************************************************************************
3929 Get a lock pid, dealing with large count requests.
3930 ****************************************************************************/
3932 uint16
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
3934 if(!large_file_format
)
3935 return SVAL(data
,SMB_LPID_OFFSET(data_offset
));
3937 return SVAL(data
,SMB_LARGE__LPID_OFFSET(data_offset
));
3940 /****************************************************************************
3941 Get a lock count, dealing with large count requests.
3942 ****************************************************************************/
3944 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
3946 SMB_BIG_UINT count
= 0;
3948 if(!large_file_format
) {
3949 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
3952 #if defined(HAVE_LONGLONG)
3953 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
3954 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
3955 #else /* HAVE_LONGLONG */
3958 * NT4.x seems to be broken in that it sends large file (64 bit)
3959 * lockingX calls even if the CAP_LARGE_FILES was *not*
3960 * negotiated. For boxes without large unsigned ints truncate the
3961 * lock count by dropping the top 32 bits.
3964 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
3965 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3966 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
3967 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
3968 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
3971 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
3972 #endif /* HAVE_LONGLONG */
3978 #if !defined(HAVE_LONGLONG)
3979 /****************************************************************************
3980 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3981 ****************************************************************************/
3982 static uint32
map_lock_offset(uint32 high
, uint32 low
)
3986 uint32 highcopy
= high
;
3989 * Try and find out how many significant bits there are in high.
3992 for(i
= 0; highcopy
; i
++)
3996 * We use 31 bits not 32 here as POSIX
3997 * lock offsets may not be negative.
4000 mask
= (~0) << (31 - i
);
4003 return 0; /* Fail. */
4009 #endif /* !defined(HAVE_LONGLONG) */
4011 /****************************************************************************
4012 Get a lock offset, dealing with large offset requests.
4013 ****************************************************************************/
4015 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
4017 SMB_BIG_UINT offset
= 0;
4021 if(!large_file_format
) {
4022 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
4025 #if defined(HAVE_LONGLONG)
4026 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
4027 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
4028 #else /* HAVE_LONGLONG */
4031 * NT4.x seems to be broken in that it sends large file (64 bit)
4032 * lockingX calls even if the CAP_LARGE_FILES was *not*
4033 * negotiated. For boxes without large unsigned ints mangle the
4034 * lock offset by mapping the top 32 bits onto the lower 32.
4037 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
4038 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4039 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
4042 if((new_low
= map_lock_offset(high
, low
)) == 0) {
4044 return (SMB_BIG_UINT
)-1;
4047 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4048 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
4049 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
4050 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
4053 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4054 #endif /* HAVE_LONGLONG */
4060 /****************************************************************************
4061 reply to a lockingX request
4062 ****************************************************************************/
4064 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4066 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
4067 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
4068 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
4069 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
4070 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
4071 SMB_BIG_UINT count
= 0, offset
= 0;
4073 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
4076 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
4080 START_PROFILE(SMBlockingX
);
4082 CHECK_FSP(fsp
,conn
);
4084 data
= smb_buf(inbuf
);
4086 /* Check if this is an oplock break on a file
4087 we have granted an oplock on.
4089 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
4090 /* Client can insist on breaking to none. */
4091 BOOL break_to_none
= (oplocklevel
== 0);
4093 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4094 (unsigned int)oplocklevel
, fsp
->fnum
));
4097 * Make sure we have granted an exclusive or batch oplock on this file.
4100 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
4101 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4102 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
4104 /* if this is a pure oplock break request then don't send a reply */
4105 if (num_locks
== 0 && num_ulocks
== 0) {
4106 END_PROFILE(SMBlockingX
);
4109 END_PROFILE(SMBlockingX
);
4110 return ERROR_DOS(ERRDOS
,ERRlock
);
4114 if (remove_oplock(fsp
, break_to_none
) == False
) {
4115 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4119 /* if this is a pure oplock break request then don't send a reply */
4120 if (num_locks
== 0 && num_ulocks
== 0) {
4121 /* Sanity check - ensure a pure oplock break is not a
4123 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
4124 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4125 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
4126 END_PROFILE(SMBlockingX
);
4132 * We do this check *after* we have checked this is not a oplock break
4133 * response message. JRA.
4136 release_level_2_oplocks_on_change(fsp
);
4138 /* Data now points at the beginning of the list
4139 of smb_unlkrng structs */
4140 for(i
= 0; i
< (int)num_ulocks
; i
++) {
4141 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4142 count
= get_lock_count( data
, i
, large_file_format
);
4143 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4146 * There is no error code marked "stupid client bug".... :-).
4149 END_PROFILE(SMBlockingX
);
4150 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4153 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4154 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
4156 status
= do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4157 if (NT_STATUS_V(status
)) {
4158 END_PROFILE(SMBlockingX
);
4159 return ERROR_NT(status
);
4163 /* Setup the timeout in seconds. */
4164 lock_timeout
= ((lock_timeout
== -1) ? -1 : lock_timeout
/1000);
4166 /* Now do any requested locks */
4167 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
4169 /* Data now points at the beginning of the list
4170 of smb_lkrng structs */
4172 for(i
= 0; i
< (int)num_locks
; i
++) {
4173 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4174 count
= get_lock_count( data
, i
, large_file_format
);
4175 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4178 * There is no error code marked "stupid client bug".... :-).
4181 END_PROFILE(SMBlockingX
);
4182 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4185 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
4186 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
4188 status
= do_lock(fsp
,conn
,lock_pid
, count
,offset
,
4189 ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
));
4190 if (NT_STATUS_V(status
)) {
4191 if ((lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
))) {
4193 * A blocking lock was requested. Package up
4194 * this smb into a queued request and push it
4195 * onto the blocking lock queue.
4197 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
)) {
4198 END_PROFILE(SMBlockingX
);
4206 /* If any of the above locks failed, then we must unlock
4207 all of the previous locks (X/Open spec). */
4208 if (i
!= num_locks
&& num_locks
!= 0) {
4210 * Ensure we don't do a remove on the lock that just failed,
4211 * as under POSIX rules, if we have a lock already there, we
4212 * will delete it (and we shouldn't) .....
4214 for(i
--; i
>= 0; i
--) {
4215 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4216 count
= get_lock_count( data
, i
, large_file_format
);
4217 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4220 * There is no error code marked "stupid client bug".... :-).
4223 END_PROFILE(SMBlockingX
);
4224 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4227 do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4229 END_PROFILE(SMBlockingX
);
4230 return ERROR_NT(status
);
4233 set_message(outbuf
,2,0,True
);
4235 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4236 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4238 END_PROFILE(SMBlockingX
);
4239 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4243 /****************************************************************************
4244 reply to a SMBreadbmpx (read block multiplex) request
4245 ****************************************************************************/
4246 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4257 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4258 START_PROFILE(SMBreadBmpx
);
4260 /* this function doesn't seem to work - disable by default */
4261 if (!lp_readbmpx()) {
4262 END_PROFILE(SMBreadBmpx
);
4263 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
4266 outsize
= set_message(outbuf
,8,0,True
);
4268 CHECK_FSP(fsp
,conn
);
4271 startpos
= IVAL(inbuf
,smb_vwv1
);
4272 maxcount
= SVAL(inbuf
,smb_vwv3
);
4274 data
= smb_buf(outbuf
);
4275 pad
= ((long)data
)%4;
4276 if (pad
) pad
= 4 - pad
;
4279 max_per_packet
= bufsize
-(outsize
+pad
);
4283 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
4284 END_PROFILE(SMBreadBmpx
);
4285 return ERROR_DOS(ERRDOS
,ERRlock
);
4290 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4292 nread
= read_file(fsp
,data
,startpos
,N
);
4294 if (nread
<= 0) nread
= 0;
4296 if (nread
< (ssize_t
)N
)
4297 tcount
= total_read
+ nread
;
4299 set_message(outbuf
,8,nread
,False
);
4300 SIVAL(outbuf
,smb_vwv0
,startpos
);
4301 SSVAL(outbuf
,smb_vwv2
,tcount
);
4302 SSVAL(outbuf
,smb_vwv6
,nread
);
4303 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4305 if (!send_smb(smbd_server_fd(),outbuf
))
4306 exit_server("reply_readbmpx: send_smb failed.\n");
4308 total_read
+= nread
;
4311 while (total_read
< (ssize_t
)tcount
);
4313 END_PROFILE(SMBreadBmpx
);
4318 /****************************************************************************
4319 reply to a SMBsetattrE
4320 ****************************************************************************/
4322 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4324 struct utimbuf unix_times
;
4326 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4327 START_PROFILE(SMBsetattrE
);
4329 outsize
= set_message(outbuf
,0,0,True
);
4331 CHECK_FSP(fsp
,conn
);
4333 /* Convert the DOS times into unix times. Ignore create
4334 time as UNIX can't set this.
4336 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4337 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4340 * Patch from Ray Frush <frush@engr.colostate.edu>
4341 * Sometimes times are sent as zero - ignore them.
4344 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0))
4346 /* Ignore request */
4349 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4350 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4352 END_PROFILE(SMBsetattrE
);
4355 else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0))
4357 /* set modify time = to access time if modify time was 0 */
4358 unix_times
.modtime
= unix_times
.actime
;
4361 /* Set the date on this file */
4362 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4363 END_PROFILE(SMBsetattrE
);
4364 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4367 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4368 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4370 END_PROFILE(SMBsetattrE
);
4375 /****************************************************************************
4376 reply to a SMBgetattrE
4377 ****************************************************************************/
4379 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4381 SMB_STRUCT_STAT sbuf
;
4384 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4385 START_PROFILE(SMBgetattrE
);
4387 outsize
= set_message(outbuf
,11,0,True
);
4389 CHECK_FSP(fsp
,conn
);
4391 /* Do an fstat on this file */
4392 if(vfs_fstat(fsp
,fsp
->fd
, &sbuf
)) {
4393 END_PROFILE(SMBgetattrE
);
4394 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4397 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4399 /* Convert the times into dos times. Set create
4400 date to be last modify date as UNIX doesn't save
4402 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4403 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4404 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4407 SIVAL(outbuf
,smb_vwv6
,0);
4408 SIVAL(outbuf
,smb_vwv8
,0);
4412 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4413 SIVAL(outbuf
,smb_vwv8
,SMB_ROUNDUP(sbuf
.st_size
,1024));
4415 SSVAL(outbuf
,smb_vwv10
, mode
);
4417 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
4419 END_PROFILE(SMBgetattrE
);