1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26 
27 #include "includes.h"
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
30 #include "printing.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
41 #include "auth.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "lib/util/tevent_ntstatus.h"
46 #include "libcli/smb/smb_signing.h"
47 #include "lib/util/sys_rw_data.h"
48 #include "librpc/gen_ndr/open_files.h"
49 #include "smb1_utils.h"
50 
51 /****************************************************************************
52  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
53  path or anything including wildcards.
54  We're assuming here that '/' is not the second byte in any multibyte char
55  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
56  set.
57 ****************************************************************************/
58 
59 /* Custom version for processing POSIX paths. */
60 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
61 
check_path_syntax_internal(char * path,bool posix_path,bool * p_last_component_contains_wcard)62 static NTSTATUS check_path_syntax_internal(char *path,
63 					   bool posix_path,
64 					   bool *p_last_component_contains_wcard)
65 {
66 	char *d = path;
67 	const char *s = path;
68 	NTSTATUS ret = NT_STATUS_OK;
69 	bool start_of_name_component = True;
70 	bool stream_started = false;
71 
72 	*p_last_component_contains_wcard = False;
73 
74 	while (*s) {
75 		if (stream_started) {
76 			switch (*s) {
77 			case '/':
78 			case '\\':
79 				return NT_STATUS_OBJECT_NAME_INVALID;
80 			case ':':
81 				if (s[1] == '\0') {
82 					return NT_STATUS_OBJECT_NAME_INVALID;
83 				}
84 				if (strchr_m(&s[1], ':')) {
85 					return NT_STATUS_OBJECT_NAME_INVALID;
86 				}
87 				break;
88 			}
89 		}
90 
91 		if ((*s == ':') && !posix_path && !stream_started) {
92 			if (*p_last_component_contains_wcard) {
93 				return NT_STATUS_OBJECT_NAME_INVALID;
94 			}
95 			/* Stream names allow more characters than file names.
96 			   We're overloading posix_path here to allow a wider
97 			   range of characters. If stream_started is true this
98 			   is still a Windows path even if posix_path is true.
99 			   JRA.
100 			*/
101 			stream_started = true;
102 			start_of_name_component = false;
103 			posix_path = true;
104 
105 			if (s[1] == '\0') {
106 				return NT_STATUS_OBJECT_NAME_INVALID;
107 			}
108 		}
109 
110 		if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
111 			/*
112 			 * Safe to assume is not the second part of a mb char
113 			 * as this is handled below.
114 			 */
115 			/* Eat multiple '/' or '\\' */
116 			while (IS_PATH_SEP(*s,posix_path)) {
117 				s++;
118 			}
119 			if ((d != path) && (*s != '\0')) {
120 				/* We only care about non-leading or trailing '/' or '\\' */
121 				*d++ = '/';
122 			}
123 
124 			start_of_name_component = True;
125 			/* New component. */
126 			*p_last_component_contains_wcard = False;
127 			continue;
128 		}
129 
130 		if (start_of_name_component) {
131 			if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
132 				/* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
133 
134 				/*
135 				 * No mb char starts with '.' so we're safe checking the directory separator here.
136 				 */
137 
138 				/* If  we just added a '/' - delete it */
139 				if ((d > path) && (*(d-1) == '/')) {
140 					*(d-1) = '\0';
141 					d--;
142 				}
143 
144 				/* Are we at the start ? Can't go back further if so. */
145 				if (d <= path) {
146 					ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
147 					break;
148 				}
149 				/* Go back one level... */
150 				/* We know this is safe as '/' cannot be part of a mb sequence. */
151 				/* NOTE - if this assumption is invalid we are not in good shape... */
152 				/* Decrement d first as d points to the *next* char to write into. */
153 				for (d--; d > path; d--) {
154 					if (*d == '/')
155 						break;
156 				}
157 				s += 2; /* Else go past the .. */
158 				/* We're still at the start of a name component, just the previous one. */
159 				continue;
160 
161 			} else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
162 				if (posix_path) {
163 					/* Eat the '.' */
164 					s++;
165 					continue;
166 				}
167 			}
168 
169 		}
170 
171 		if (!(*s & 0x80)) {
172 			if (!posix_path) {
173 				if (*s <= 0x1f || *s == '|') {
174 					return NT_STATUS_OBJECT_NAME_INVALID;
175 				}
176 				switch (*s) {
177 					case '*':
178 					case '?':
179 					case '<':
180 					case '>':
181 					case '"':
182 						*p_last_component_contains_wcard = True;
183 						break;
184 					default:
185 						break;
186 				}
187 			}
188 			*d++ = *s++;
189 		} else {
190 			size_t siz;
191 			/* Get the size of the next MB character. */
192 			next_codepoint(s,&siz);
193 			switch(siz) {
194 				case 5:
195 					*d++ = *s++;
196 					FALL_THROUGH;
197 				case 4:
198 					*d++ = *s++;
199 					FALL_THROUGH;
200 				case 3:
201 					*d++ = *s++;
202 					FALL_THROUGH;
203 				case 2:
204 					*d++ = *s++;
205 					FALL_THROUGH;
206 				case 1:
207 					*d++ = *s++;
208 					break;
209 				default:
210 					DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
211 					*d = '\0';
212 					return NT_STATUS_INVALID_PARAMETER;
213 			}
214 		}
215 		start_of_name_component = False;
216 	}
217 
218 	*d = '\0';
219 
220 	return ret;
221 }
222 
223 /****************************************************************************
224  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
225  No wildcards allowed.
226 ****************************************************************************/
227 
check_path_syntax(char * path)228 NTSTATUS check_path_syntax(char *path)
229 {
230 	bool ignore;
231 	return check_path_syntax_internal(path, False, &ignore);
232 }
233 
234 /****************************************************************************
235  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
236  Wildcards allowed - p_contains_wcard returns true if the last component contained
237  a wildcard.
238 ****************************************************************************/
239 
check_path_syntax_wcard(char * path,bool * p_contains_wcard)240 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
241 {
242 	return check_path_syntax_internal(path, False, p_contains_wcard);
243 }
244 
245 /****************************************************************************
246  Check the path for a POSIX client.
247  We're assuming here that '/' is not the second byte in any multibyte char
248  set (a safe assumption).
249 ****************************************************************************/
250 
check_path_syntax_posix(char * path)251 NTSTATUS check_path_syntax_posix(char *path)
252 {
253 	bool ignore;
254 	return check_path_syntax_internal(path, True, &ignore);
255 }
256 
257 /****************************************************************************
258  Pull a string and check the path allowing a wildcard - provide for error return.
259  Passes in posix flag.
260 ****************************************************************************/
261 
srvstr_get_path_wcard_internal(TALLOC_CTX * ctx,const char * base_ptr,uint16_t smb_flags2,char ** pp_dest,const char * src,size_t src_len,int flags,bool posix_pathnames,NTSTATUS * err,bool * contains_wcard)262 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
263 			const char *base_ptr,
264 			uint16_t smb_flags2,
265 			char **pp_dest,
266 			const char *src,
267 			size_t src_len,
268 			int flags,
269 			bool posix_pathnames,
270 			NTSTATUS *err,
271 			bool *contains_wcard)
272 {
273 	size_t ret;
274 
275 	*pp_dest = NULL;
276 
277 	ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
278 				 src_len, flags);
279 
280 	if (!*pp_dest) {
281 		*err = NT_STATUS_INVALID_PARAMETER;
282 		return ret;
283 	}
284 
285 	*contains_wcard = False;
286 
287 	if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
288 		/*
289 		 * For a DFS path the function parse_dfs_path()
290 		 * will do the path processing, just make a copy.
291 		 */
292 		*err = NT_STATUS_OK;
293 		return ret;
294 	}
295 
296 	if (posix_pathnames) {
297 		*err = check_path_syntax_posix(*pp_dest);
298 	} else {
299 		*err = check_path_syntax_wcard(*pp_dest, contains_wcard);
300 	}
301 
302 	return ret;
303 }
304 
305 /****************************************************************************
306  Pull a string and check the path allowing a wildcard - provide for error return.
307 ****************************************************************************/
308 
srvstr_get_path_wcard(TALLOC_CTX * ctx,const char * base_ptr,uint16_t smb_flags2,char ** pp_dest,const char * src,size_t src_len,int flags,NTSTATUS * err,bool * contains_wcard)309 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
310 			const char *base_ptr,
311 			uint16_t smb_flags2,
312 			char **pp_dest,
313 			const char *src,
314 			size_t src_len,
315 			int flags,
316 			NTSTATUS *err,
317 			bool *contains_wcard)
318 {
319 	return srvstr_get_path_wcard_internal(ctx,
320 			base_ptr,
321 			smb_flags2,
322 			pp_dest,
323 			src,
324 			src_len,
325 			flags,
326 			false,
327 			err,
328 			contains_wcard);
329 }
330 
331 /****************************************************************************
332  Pull a string and check the path allowing a wildcard - provide for error return.
333  posix_pathnames version.
334 ****************************************************************************/
335 
srvstr_get_path_wcard_posix(TALLOC_CTX * ctx,const char * base_ptr,uint16_t smb_flags2,char ** pp_dest,const char * src,size_t src_len,int flags,NTSTATUS * err,bool * contains_wcard)336 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
337 			const char *base_ptr,
338 			uint16_t smb_flags2,
339 			char **pp_dest,
340 			const char *src,
341 			size_t src_len,
342 			int flags,
343 			NTSTATUS *err,
344 			bool *contains_wcard)
345 {
346 	return srvstr_get_path_wcard_internal(ctx,
347 			base_ptr,
348 			smb_flags2,
349 			pp_dest,
350 			src,
351 			src_len,
352 			flags,
353 			true,
354 			err,
355 			contains_wcard);
356 }
357 
358 /****************************************************************************
359  Pull a string and check the path - provide for error return.
360 ****************************************************************************/
361 
srvstr_get_path(TALLOC_CTX * ctx,const char * base_ptr,uint16_t smb_flags2,char ** pp_dest,const char * src,size_t src_len,int flags,NTSTATUS * err)362 size_t srvstr_get_path(TALLOC_CTX *ctx,
363 			const char *base_ptr,
364 			uint16_t smb_flags2,
365 			char **pp_dest,
366 			const char *src,
367 			size_t src_len,
368 			int flags,
369 			NTSTATUS *err)
370 {
371 	bool ignore;
372 	return srvstr_get_path_wcard_internal(ctx,
373 			base_ptr,
374 			smb_flags2,
375 			pp_dest,
376 			src,
377 			src_len,
378 			flags,
379 			false,
380 			err,
381 			&ignore);
382 }
383 
384 /****************************************************************************
385  Pull a string and check the path - provide for error return.
386  posix_pathnames version.
387 ****************************************************************************/
388 
srvstr_get_path_posix(TALLOC_CTX * ctx,const char * base_ptr,uint16_t smb_flags2,char ** pp_dest,const char * src,size_t src_len,int flags,NTSTATUS * err)389 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
390 			const char *base_ptr,
391 			uint16_t smb_flags2,
392 			char **pp_dest,
393 			const char *src,
394 			size_t src_len,
395 			int flags,
396 			NTSTATUS *err)
397 {
398 	bool ignore;
399 	return srvstr_get_path_wcard_internal(ctx,
400 			base_ptr,
401 			smb_flags2,
402 			pp_dest,
403 			src,
404 			src_len,
405 			flags,
406 			true,
407 			err,
408 			&ignore);
409 }
410 
411 
srvstr_get_path_req_wcard(TALLOC_CTX * mem_ctx,struct smb_request * req,char ** pp_dest,const char * src,int flags,NTSTATUS * err,bool * contains_wcard)412 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
413 				 char **pp_dest, const char *src, int flags,
414 				 NTSTATUS *err, bool *contains_wcard)
415 {
416 	ssize_t bufrem = smbreq_bufrem(req, src);
417 
418 	if (bufrem < 0) {
419 		*err = NT_STATUS_INVALID_PARAMETER;
420 		return 0;
421 	}
422 
423 	if (req->posix_pathnames) {
424 		return srvstr_get_path_wcard_internal(mem_ctx,
425 				(const char *)req->inbuf,
426 				req->flags2,
427 				pp_dest,
428 				src,
429 				bufrem,
430 				flags,
431 				true,
432 				err,
433 				contains_wcard);
434 	} else {
435 		return srvstr_get_path_wcard_internal(mem_ctx,
436 				(const char *)req->inbuf,
437 				req->flags2,
438 				pp_dest,
439 				src,
440 				bufrem,
441 				flags,
442 				false,
443 				err,
444 				contains_wcard);
445 	}
446 }
447 
srvstr_get_path_req(TALLOC_CTX * mem_ctx,struct smb_request * req,char ** pp_dest,const char * src,int flags,NTSTATUS * err)448 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
449 			   char **pp_dest, const char *src, int flags,
450 			   NTSTATUS *err)
451 {
452 	bool ignore;
453 	return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
454 					 flags, err, &ignore);
455 }
456 
457 /**
458  * pull a string from the smb_buf part of a packet. In this case the
459  * string can either be null terminated or it can be terminated by the
460  * end of the smbbuf area
461  */
srvstr_pull_req_talloc(TALLOC_CTX * ctx,struct smb_request * req,char ** dest,const uint8_t * src,int flags)462 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
463 			      char **dest, const uint8_t *src, int flags)
464 {
465 	ssize_t bufrem = smbreq_bufrem(req, src);
466 
467 	if (bufrem < 0) {
468 		return 0;
469 	}
470 
471 	return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
472 				  bufrem, flags);
473 }
474 
475 /****************************************************************************
476  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
477 ****************************************************************************/
478 
check_fsp_open(connection_struct * conn,struct smb_request * req,files_struct * fsp)479 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
480 		    files_struct *fsp)
481 {
482 	if ((fsp == NULL) || (conn == NULL)) {
483 		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
484 		return False;
485 	}
486 	if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
487 		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
488 		return False;
489 	}
490 	return True;
491 }
492 
493 /****************************************************************************
494  Check if we have a correct fsp pointing to a file.
495 ****************************************************************************/
496 
check_fsp(connection_struct * conn,struct smb_request * req,files_struct * fsp)497 bool check_fsp(connection_struct *conn, struct smb_request *req,
498 	       files_struct *fsp)
499 {
500 	if (!check_fsp_open(conn, req, fsp)) {
501 		return False;
502 	}
503 	if (fsp->is_directory) {
504 		reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
505 		return False;
506 	}
507 	if (fsp->fh->fd == -1) {
508 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
509 		return False;
510 	}
511 	fsp->num_smb_operations++;
512 	return True;
513 }
514 
515 /****************************************************************************
516  Check if we have a correct fsp pointing to a quota fake file. Replacement for
517  the CHECK_NTQUOTA_HANDLE_OK macro.
518 ****************************************************************************/
519 
check_fsp_ntquota_handle(connection_struct * conn,struct smb_request * req,files_struct * fsp)520 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
521 			      files_struct *fsp)
522 {
523 	if (!check_fsp_open(conn, req, fsp)) {
524 		return false;
525 	}
526 
527 	if (fsp->is_directory) {
528 		return false;
529 	}
530 
531 	if (fsp->fake_file_handle == NULL) {
532 		return false;
533 	}
534 
535 	if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
536 		return false;
537 	}
538 
539 	if (fsp->fake_file_handle->private_data == NULL) {
540 		return false;
541 	}
542 
543 	return true;
544 }
545 
netbios_session_retarget(struct smbXsrv_connection * xconn,const char * name,int name_type)546 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
547 				     const char *name, int name_type)
548 {
549 	char *trim_name;
550 	char *trim_name_type;
551 	const char *retarget_parm;
552 	char *retarget;
553 	char *p;
554 	int retarget_type = 0x20;
555 	int retarget_port = NBT_SMB_PORT;
556 	struct sockaddr_storage retarget_addr;
557 	struct sockaddr_in *in_addr;
558 	bool ret = false;
559 	uint8_t outbuf[10];
560 
561 	if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
562 		return false;
563 	}
564 
565 	trim_name = talloc_strdup(talloc_tos(), name);
566 	if (trim_name == NULL) {
567 		goto fail;
568 	}
569 	trim_char(trim_name, ' ', ' ');
570 
571 	trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
572 					 name_type);
573 	if (trim_name_type == NULL) {
574 		goto fail;
575 	}
576 
577 	retarget_parm = lp_parm_const_string(-1, "netbios retarget",
578 					     trim_name_type, NULL);
579 	if (retarget_parm == NULL) {
580 		retarget_parm = lp_parm_const_string(-1, "netbios retarget",
581 						     trim_name, NULL);
582 	}
583 	if (retarget_parm == NULL) {
584 		goto fail;
585 	}
586 
587 	retarget = talloc_strdup(trim_name, retarget_parm);
588 	if (retarget == NULL) {
589 		goto fail;
590 	}
591 
592 	DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
593 
594 	p = strchr(retarget, ':');
595 	if (p != NULL) {
596 		*p++ = '\0';
597 		retarget_port = atoi(p);
598 	}
599 
600 	p = strchr_m(retarget, '#');
601 	if (p != NULL) {
602 		*p++ = '\0';
603 		if (sscanf(p, "%x", &retarget_type) != 1) {
604 			goto fail;
605 		}
606 	}
607 
608 	ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
609 	if (!ret) {
610 		DEBUG(10, ("could not resolve %s\n", retarget));
611 		goto fail;
612 	}
613 
614 	if (retarget_addr.ss_family != AF_INET) {
615 		DEBUG(10, ("Retarget target not an IPv4 addr\n"));
616 		goto fail;
617 	}
618 
619 	in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
620 
621 	_smb_setlen(outbuf, 6);
622 	SCVAL(outbuf, 0, 0x84);
623 	*(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
624 	*(uint16_t *)(outbuf+8) = htons(retarget_port);
625 
626 	if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
627 			  NULL)) {
628 		exit_server_cleanly("netbios_session_retarget: srv_send_smb "
629 				    "failed.");
630 	}
631 
632 	ret = true;
633  fail:
634 	TALLOC_FREE(trim_name);
635 	return ret;
636 }
637 
reply_called_name_not_present(char * outbuf)638 static void reply_called_name_not_present(char *outbuf)
639 {
640 	smb_setlen(outbuf, 1);
641 	SCVAL(outbuf, 0, 0x83);
642 	SCVAL(outbuf, 4, 0x82);
643 }
644 
645 /****************************************************************************
646  Reply to a (netbios-level) special message.
647 ****************************************************************************/
648 
reply_special(struct smbXsrv_connection * xconn,char * inbuf,size_t inbuf_size)649 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
650 {
651 	struct smbd_server_connection *sconn = xconn->client->sconn;
652 	int msg_type = CVAL(inbuf,0);
653 	int msg_flags = CVAL(inbuf,1);
654 	/*
655 	 * We only really use 4 bytes of the outbuf, but for the smb_setlen
656 	 * calculation & friends (srv_send_smb uses that) we need the full smb
657 	 * header.
658 	 */
659 	char outbuf[smb_size];
660 
661 	memset(outbuf, '\0', sizeof(outbuf));
662 
663 	smb_setlen(outbuf,0);
664 
665 	switch (msg_type) {
666 	case NBSSrequest: /* session request */
667 	{
668 		/* inbuf_size is guarenteed to be at least 4. */
669 		fstring name1,name2;
670 		int name_type1, name_type2;
671 		int name_len1, name_len2;
672 
673 		*name1 = *name2 = 0;
674 
675 		if (xconn->transport.nbt.got_session) {
676 			exit_server_cleanly("multiple session request not permitted");
677 		}
678 
679 		SCVAL(outbuf,0,NBSSpositive);
680 		SCVAL(outbuf,3,0);
681 
682 		/* inbuf_size is guaranteed to be at least 4. */
683 		name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
684 		if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
685 			DEBUG(0,("Invalid name length in session request\n"));
686 			reply_called_name_not_present(outbuf);
687 			break;
688 		}
689 		name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
690 		if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
691 			DEBUG(0,("Invalid name length in session request\n"));
692 			reply_called_name_not_present(outbuf);
693 			break;
694 		}
695 
696 		name_type1 = name_extract((unsigned char *)inbuf,
697 				inbuf_size,(unsigned int)4,name1);
698 		name_type2 = name_extract((unsigned char *)inbuf,
699 				inbuf_size,(unsigned int)(4 + name_len1),name2);
700 
701 		if (name_type1 == -1 || name_type2 == -1) {
702 			DEBUG(0,("Invalid name type in session request\n"));
703 			reply_called_name_not_present(outbuf);
704 			break;
705 		}
706 
707 		DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
708 			 name1, name_type1, name2, name_type2));
709 
710 		if (netbios_session_retarget(xconn, name1, name_type1)) {
711 			exit_server_cleanly("retargeted client");
712 		}
713 
714 		/*
715 		 * Windows NT/2k uses "*SMBSERVER" and XP uses
716 		 * "*SMBSERV" arrggg!!!
717 		 */
718 		if (strequal(name1, "*SMBSERVER     ")
719 		    || strequal(name1, "*SMBSERV       "))  {
720 			char *raddr;
721 
722 			raddr = tsocket_address_inet_addr_string(sconn->remote_address,
723 								 talloc_tos());
724 			if (raddr == NULL) {
725 				exit_server_cleanly("could not allocate raddr");
726 			}
727 
728 			fstrcpy(name1, raddr);
729 		}
730 
731 		set_local_machine_name(name1, True);
732 		set_remote_machine_name(name2, True);
733 
734 		if (is_ipaddress(sconn->remote_hostname)) {
735 			char *p = discard_const_p(char, sconn->remote_hostname);
736 
737 			talloc_free(p);
738 
739 			sconn->remote_hostname = talloc_strdup(sconn,
740 						get_remote_machine_name());
741 			if (sconn->remote_hostname == NULL) {
742 				exit_server_cleanly("could not copy remote name");
743 			}
744 			xconn->remote_hostname = sconn->remote_hostname;
745 		}
746 
747 		DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
748 			 get_local_machine_name(), get_remote_machine_name(),
749 			 name_type2));
750 
751 		if (name_type2 == 'R') {
752 			/* We are being asked for a pathworks session ---
753 			   no thanks! */
754 			reply_called_name_not_present(outbuf);
755 			break;
756 		}
757 
758 		reload_services(sconn, conn_snum_used, true);
759 		reopen_logs();
760 
761 		xconn->transport.nbt.got_session = true;
762 		break;
763 	}
764 
765 	case 0x89: /* session keepalive request
766 		      (some old clients produce this?) */
767 		SCVAL(outbuf,0,NBSSkeepalive);
768 		SCVAL(outbuf,3,0);
769 		break;
770 
771 	case NBSSpositive: /* positive session response */
772 	case NBSSnegative: /* negative session response */
773 	case NBSSretarget: /* retarget session response */
774 		DEBUG(0,("Unexpected session response\n"));
775 		break;
776 
777 	case NBSSkeepalive: /* session keepalive */
778 	default:
779 		return;
780 	}
781 
782 	DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
783 		    msg_type, msg_flags));
784 
785 	if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
786 		exit_server_cleanly("reply_special: srv_send_smb failed.");
787 	}
788 
789 	if (CVAL(outbuf, 0) != 0x82) {
790 		exit_server_cleanly("invalid netbios session");
791 	}
792 	return;
793 }
794 
795 /****************************************************************************
796  Reply to a tcon.
797  conn POINTER CAN BE NULL HERE !
798 ****************************************************************************/
799 
reply_tcon(struct smb_request * req)800 void reply_tcon(struct smb_request *req)
801 {
802 	connection_struct *conn = req->conn;
803 	const char *service;
804 	char *service_buf = NULL;
805 	char *password = NULL;
806 	char *dev = NULL;
807 	int pwlen=0;
808 	NTSTATUS nt_status;
809 	const uint8_t *p;
810 	const char *p2;
811 	TALLOC_CTX *ctx = talloc_tos();
812 	struct smbXsrv_connection *xconn = req->xconn;
813 	NTTIME now = timeval_to_nttime(&req->request_time);
814 
815 	START_PROFILE(SMBtcon);
816 
817 	if (req->buflen < 4) {
818 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
819 		END_PROFILE(SMBtcon);
820 		return;
821 	}
822 
823 	p = req->buf + 1;
824 	p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
825 	p += 1;
826 	pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
827 	p += pwlen+1;
828 	p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
829 	p += 1;
830 
831 	if (service_buf == NULL || password == NULL || dev == NULL) {
832 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
833 		END_PROFILE(SMBtcon);
834 		return;
835 	}
836 	p2 = strrchr_m(service_buf,'\\');
837 	if (p2) {
838 		service = p2+1;
839 	} else {
840 		service = service_buf;
841 	}
842 
843 	conn = make_connection(req, now, service, dev,
844 			       req->vuid,&nt_status);
845 	req->conn = conn;
846 
847 	if (!conn) {
848 		reply_nterror(req, nt_status);
849 		END_PROFILE(SMBtcon);
850 		return;
851 	}
852 
853 	reply_outbuf(req, 2, 0);
854 	SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
855 	SSVAL(req->outbuf,smb_vwv1,conn->cnum);
856 	SSVAL(req->outbuf,smb_tid,conn->cnum);
857 
858 	DEBUG(3,("tcon service=%s cnum=%d\n",
859 		 service, conn->cnum));
860 
861 	END_PROFILE(SMBtcon);
862 	return;
863 }
864 
865 /****************************************************************************
866  Reply to a tcon and X.
867  conn POINTER CAN BE NULL HERE !
868 ****************************************************************************/
869 
reply_tcon_and_X(struct smb_request * req)870 void reply_tcon_and_X(struct smb_request *req)
871 {
872 	const struct loadparm_substitution *lp_sub =
873 		loadparm_s3_global_substitution();
874 	connection_struct *conn = req->conn;
875 	const char *service = NULL;
876 	TALLOC_CTX *ctx = talloc_tos();
877 	/* what the client thinks the device is */
878 	char *client_devicetype = NULL;
879 	/* what the server tells the client the share represents */
880 	const char *server_devicetype;
881 	NTSTATUS nt_status;
882 	int passlen;
883 	char *path = NULL;
884 	const uint8_t *p;
885 	const char *q;
886 	uint16_t tcon_flags;
887 	struct smbXsrv_session *session = NULL;
888 	NTTIME now = timeval_to_nttime(&req->request_time);
889 	bool session_key_updated = false;
890 	uint16_t optional_support = 0;
891 	struct smbXsrv_connection *xconn = req->xconn;
892 
893 	START_PROFILE(SMBtconX);
894 
895 	if (req->wct < 4) {
896 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
897 		END_PROFILE(SMBtconX);
898 		return;
899 	}
900 
901 	passlen = SVAL(req->vwv+3, 0);
902 	tcon_flags = SVAL(req->vwv+2, 0);
903 
904 	/* we might have to close an old one */
905 	if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
906 		struct smbXsrv_tcon *tcon;
907 		NTSTATUS status;
908 
909 		tcon = conn->tcon;
910 		req->conn = NULL;
911 		conn = NULL;
912 
913 		/*
914 		 * TODO: cancel all outstanding requests on the tcon
915 		 */
916 		status = smbXsrv_tcon_disconnect(tcon, req->vuid);
917 		if (!NT_STATUS_IS_OK(status)) {
918 			DEBUG(0, ("reply_tcon_and_X: "
919 				  "smbXsrv_tcon_disconnect() failed: %s\n",
920 				  nt_errstr(status)));
921 			/*
922 			 * If we hit this case, there is something completely
923 			 * wrong, so we better disconnect the transport connection.
924 			 */
925 			END_PROFILE(SMBtconX);
926 			exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
927 			return;
928 		}
929 
930 		TALLOC_FREE(tcon);
931 		/*
932 		 * This tree id is gone. Make sure we can't re-use it
933 		 * by accident.
934 		 */
935 		req->tid = 0;
936 	}
937 
938 	if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
939 		reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
940 		END_PROFILE(SMBtconX);
941 		return;
942 	}
943 
944 	if (xconn->smb1.negprot.encrypted_passwords) {
945 		p = req->buf + passlen;
946 	} else {
947 		p = req->buf + passlen + 1;
948 	}
949 
950 	p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
951 
952 	if (path == NULL) {
953 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
954 		END_PROFILE(SMBtconX);
955 		return;
956 	}
957 
958 	/*
959 	 * the service name can be either: \\server\share
960 	 * or share directly like on the DELL PowerVault 705
961 	 */
962 	if (*path=='\\') {
963 		q = strchr_m(path+2,'\\');
964 		if (!q) {
965 			reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
966 			END_PROFILE(SMBtconX);
967 			return;
968 		}
969 		service = q+1;
970 	} else {
971 		service = path;
972 	}
973 
974 	p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
975 				&client_devicetype, p,
976 				MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
977 
978 	if (client_devicetype == NULL) {
979 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
980 		END_PROFILE(SMBtconX);
981 		return;
982 	}
983 
984 	DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
985 
986 	nt_status = smb1srv_session_lookup(xconn,
987 					   req->vuid, now, &session);
988 	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
989 		reply_force_doserror(req, ERRSRV, ERRbaduid);
990 		END_PROFILE(SMBtconX);
991 		return;
992 	}
993 	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
994 		reply_nterror(req, nt_status);
995 		END_PROFILE(SMBtconX);
996 		return;
997 	}
998 	if (!NT_STATUS_IS_OK(nt_status)) {
999 		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1000 		END_PROFILE(SMBtconX);
1001 		return;
1002 	}
1003 
1004 	if (session->global->auth_session_info == NULL) {
1005 		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1006 		END_PROFILE(SMBtconX);
1007 		return;
1008 	}
1009 
1010 	/*
1011 	 * If there is no application key defined yet
1012 	 * we create one.
1013 	 *
1014 	 * This means we setup the application key on the
1015 	 * first tcon that happens via the given session.
1016 	 *
1017 	 * Once the application key is defined, it does not
1018 	 * change any more.
1019 	 */
1020 	if (session->global->application_key.length == 0 &&
1021 	    smb2_signing_key_valid(session->global->signing_key))
1022 	{
1023 		struct smbXsrv_session *x = session;
1024 		struct auth_session_info *session_info =
1025 			session->global->auth_session_info;
1026 		uint8_t session_key[16];
1027 
1028 		ZERO_STRUCT(session_key);
1029 		memcpy(session_key, x->global->signing_key->blob.data,
1030 		       MIN(x->global->signing_key->blob.length, sizeof(session_key)));
1031 
1032 		/*
1033 		 * The application key is truncated/padded to 16 bytes
1034 		 */
1035 		x->global->application_key = data_blob_talloc(x->global,
1036 							     session_key,
1037 							     sizeof(session_key));
1038 		ZERO_STRUCT(session_key);
1039 		if (x->global->application_key.data == NULL) {
1040 			reply_nterror(req, NT_STATUS_NO_MEMORY);
1041 			END_PROFILE(SMBtconX);
1042 			return;
1043 		}
1044 
1045 		if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1046 			NTSTATUS status;
1047 
1048 			status = smb_key_derivation(x->global->application_key.data,
1049 						    x->global->application_key.length,
1050 						    x->global->application_key.data);
1051 			if (!NT_STATUS_IS_OK(status)) {
1052 				DBG_ERR("smb_key_derivation failed: %s\n",
1053 					nt_errstr(status));
1054 				END_PROFILE(SMBtconX);
1055 				return;
1056 			}
1057 			optional_support |= SMB_EXTENDED_SIGNATURES;
1058 		}
1059 
1060 		/*
1061 		 * Place the application key into the session_info
1062 		 */
1063 		data_blob_clear_free(&session_info->session_key);
1064 		session_info->session_key = data_blob_dup_talloc(session_info,
1065 						x->global->application_key);
1066 		if (session_info->session_key.data == NULL) {
1067 			data_blob_clear_free(&x->global->application_key);
1068 			reply_nterror(req, NT_STATUS_NO_MEMORY);
1069 			END_PROFILE(SMBtconX);
1070 			return;
1071 		}
1072 		session_key_updated = true;
1073 	}
1074 
1075 	conn = make_connection(req, now, service, client_devicetype,
1076 			       req->vuid, &nt_status);
1077 	req->conn =conn;
1078 
1079 	if (!conn) {
1080 		if (session_key_updated) {
1081 			struct smbXsrv_session *x = session;
1082 			struct auth_session_info *session_info =
1083 				session->global->auth_session_info;
1084 			data_blob_clear_free(&x->global->application_key);
1085 			data_blob_clear_free(&session_info->session_key);
1086 		}
1087 		reply_nterror(req, nt_status);
1088 		END_PROFILE(SMBtconX);
1089 		return;
1090 	}
1091 
1092 	if ( IS_IPC(conn) )
1093 		server_devicetype = "IPC";
1094 	else if ( IS_PRINT(conn) )
1095 		server_devicetype = "LPT1:";
1096 	else
1097 		server_devicetype = "A:";
1098 
1099 	if (get_Protocol() < PROTOCOL_NT1) {
1100 		reply_outbuf(req, 2, 0);
1101 		if (message_push_string(&req->outbuf, server_devicetype,
1102 					STR_TERMINATE|STR_ASCII) == -1) {
1103 			reply_nterror(req, NT_STATUS_NO_MEMORY);
1104 			END_PROFILE(SMBtconX);
1105 			return;
1106 		}
1107 	} else {
1108 		/* NT sets the fstype of IPC$ to the null string */
1109 		const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1110 
1111 		if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1112 			/* Return permissions. */
1113 			uint32_t perm1 = 0;
1114 			uint32_t perm2 = 0;
1115 
1116 			reply_outbuf(req, 7, 0);
1117 
1118 			if (IS_IPC(conn)) {
1119 				perm1 = FILE_ALL_ACCESS;
1120 				perm2 = FILE_ALL_ACCESS;
1121 			} else {
1122 				perm1 = conn->share_access;
1123 			}
1124 
1125 			SIVAL(req->outbuf, smb_vwv3, perm1);
1126 			SIVAL(req->outbuf, smb_vwv5, perm2);
1127 		} else {
1128 			reply_outbuf(req, 3, 0);
1129 		}
1130 
1131 		if ((message_push_string(&req->outbuf, server_devicetype,
1132 					 STR_TERMINATE|STR_ASCII) == -1)
1133 		    || (message_push_string(&req->outbuf, fstype,
1134 					    STR_TERMINATE) == -1)) {
1135 			reply_nterror(req, NT_STATUS_NO_MEMORY);
1136 			END_PROFILE(SMBtconX);
1137 			return;
1138 		}
1139 
1140 		/* what does setting this bit do? It is set by NT4 and
1141 		   may affect the ability to autorun mounted cdroms */
1142 		optional_support |= SMB_SUPPORT_SEARCH_BITS;
1143 		optional_support |=
1144 			(lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1145 
1146 		if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1147 			DEBUG(2,("Serving %s as a Dfs root\n",
1148 				 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1149 			optional_support |= SMB_SHARE_IN_DFS;
1150 		}
1151 
1152 		SSVAL(req->outbuf, smb_vwv2, optional_support);
1153 	}
1154 
1155 	SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1156 	SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
1157 
1158 	DEBUG(3,("tconX service=%s \n",
1159 		 service));
1160 
1161 	/* set the incoming and outgoing tid to the just created one */
1162 	SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1163 	SSVAL(req->outbuf,smb_tid,conn->cnum);
1164 
1165 	END_PROFILE(SMBtconX);
1166 
1167 	req->tid = conn->cnum;
1168 }
1169 
1170 /****************************************************************************
1171  Reply to an unknown type.
1172 ****************************************************************************/
1173 
reply_unknown_new(struct smb_request * req,uint8_t type)1174 void reply_unknown_new(struct smb_request *req, uint8_t type)
1175 {
1176 	DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1177 		  smb_fn_name(type), type, type));
1178 	reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1179 	return;
1180 }
1181 
1182 /****************************************************************************
1183  Reply to an ioctl.
1184  conn POINTER CAN BE NULL HERE !
1185 ****************************************************************************/
1186 
reply_ioctl(struct smb_request * req)1187 void reply_ioctl(struct smb_request *req)
1188 {
1189 	const struct loadparm_substitution *lp_sub =
1190 		loadparm_s3_global_substitution();
1191 	connection_struct *conn = req->conn;
1192 	uint16_t device;
1193 	uint16_t function;
1194 	uint32_t ioctl_code;
1195 	int replysize;
1196 	char *p;
1197 
1198 	START_PROFILE(SMBioctl);
1199 
1200 	if (req->wct < 3) {
1201 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1202 		END_PROFILE(SMBioctl);
1203 		return;
1204 	}
1205 
1206 	device     = SVAL(req->vwv+1, 0);
1207 	function   = SVAL(req->vwv+2, 0);
1208 	ioctl_code = (device << 16) + function;
1209 
1210 	DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1211 
1212 	switch (ioctl_code) {
1213 	    case IOCTL_QUERY_JOB_INFO:
1214 		    replysize = 32;
1215 		    break;
1216 	    default:
1217 		    reply_force_doserror(req, ERRSRV, ERRnosupport);
1218 		    END_PROFILE(SMBioctl);
1219 		    return;
1220 	}
1221 
1222 	reply_outbuf(req, 8, replysize+1);
1223 	SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1224 	SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1225 	SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
1226 	p = smb_buf(req->outbuf);
1227 	memset(p, '\0', replysize+1); /* valgrind-safe. */
1228 	p += 1;          /* Allow for alignment */
1229 
1230 	switch (ioctl_code) {
1231 		case IOCTL_QUERY_JOB_INFO:
1232 		{
1233 			NTSTATUS status;
1234 			size_t len = 0;
1235 			files_struct *fsp = file_fsp(
1236 				req, SVAL(req->vwv+0, 0));
1237 			if (!fsp) {
1238 				reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1239 				END_PROFILE(SMBioctl);
1240 				return;
1241 			}
1242 			/* Job number */
1243 			SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1244 
1245 			status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1246 				    lp_netbios_name(), 15,
1247 				    STR_TERMINATE|STR_ASCII, &len);
1248 			if (!NT_STATUS_IS_OK(status)) {
1249 				reply_nterror(req, status);
1250 				END_PROFILE(SMBioctl);
1251 				return;
1252 			}
1253 			if (conn) {
1254 				status = srvstr_push((char *)req->outbuf, req->flags2,
1255 					    p+18,
1256 					    lp_servicename(talloc_tos(),
1257 							   lp_sub,
1258 							   SNUM(conn)),
1259 					    13, STR_TERMINATE|STR_ASCII, &len);
1260 				if (!NT_STATUS_IS_OK(status)) {
1261 					reply_nterror(req, status);
1262 					END_PROFILE(SMBioctl);
1263 					return;
1264 				}
1265 			} else {
1266 				memset(p+18, 0, 13);
1267 			}
1268 			break;
1269 		}
1270 	}
1271 
1272 	END_PROFILE(SMBioctl);
1273 	return;
1274 }
1275 
1276 /****************************************************************************
1277  Strange checkpath NTSTATUS mapping.
1278 ****************************************************************************/
1279 
map_checkpath_error(uint16_t flags2,NTSTATUS status)1280 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1281 {
1282 	/* Strange DOS error code semantics only for checkpath... */
1283 	if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1284 		if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1285 			/* We need to map to ERRbadpath */
1286 			return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1287 		}
1288 	}
1289 	return status;
1290 }
1291 
1292 /****************************************************************************
1293  Reply to a checkpath.
1294 ****************************************************************************/
1295 
reply_checkpath(struct smb_request * req)1296 void reply_checkpath(struct smb_request *req)
1297 {
1298 	connection_struct *conn = req->conn;
1299 	struct smb_filename *smb_fname = NULL;
1300 	char *name = NULL;
1301 	NTSTATUS status;
1302 	uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1303 	TALLOC_CTX *ctx = talloc_tos();
1304 
1305 	START_PROFILE(SMBcheckpath);
1306 
1307 	srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1308 			    STR_TERMINATE, &status);
1309 
1310 	if (!NT_STATUS_IS_OK(status)) {
1311 		status = map_checkpath_error(req->flags2, status);
1312 		reply_nterror(req, status);
1313 		END_PROFILE(SMBcheckpath);
1314 		return;
1315 	}
1316 
1317 	DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1318 
1319 	status = filename_convert(ctx,
1320 				conn,
1321 				name,
1322 				ucf_flags,
1323 				NULL,
1324 				NULL,
1325 				&smb_fname);
1326 
1327 	if (!NT_STATUS_IS_OK(status)) {
1328 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1329 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1330 					ERRSRV, ERRbadpath);
1331 			END_PROFILE(SMBcheckpath);
1332 			return;
1333 		}
1334 		goto path_err;
1335 	}
1336 
1337 	if (!VALID_STAT(smb_fname->st) &&
1338 	    (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1339 		DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1340 			smb_fname_str_dbg(smb_fname), strerror(errno)));
1341 		status = map_nt_error_from_unix(errno);
1342 		goto path_err;
1343 	}
1344 
1345 	if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1346 		reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1347 				ERRDOS, ERRbadpath);
1348 		goto out;
1349 	}
1350 
1351 	reply_outbuf(req, 0, 0);
1352 
1353  path_err:
1354 	/* We special case this - as when a Windows machine
1355 		is parsing a path is steps through the components
1356 		one at a time - if a component fails it expects
1357 		ERRbadpath, not ERRbadfile.
1358 	*/
1359 	status = map_checkpath_error(req->flags2, status);
1360 	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1361 		/*
1362 		 * Windows returns different error codes if
1363 		 * the parent directory is valid but not the
1364 		 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1365 		 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1366 		 * if the path is invalid.
1367 		 */
1368 		reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1369 				ERRDOS, ERRbadpath);
1370 		goto out;
1371 	}
1372 
1373 	reply_nterror(req, status);
1374 
1375  out:
1376 	TALLOC_FREE(smb_fname);
1377 	END_PROFILE(SMBcheckpath);
1378 	return;
1379 }
1380 
1381 /****************************************************************************
1382  Reply to a getatr.
1383 ****************************************************************************/
1384 
reply_getatr(struct smb_request * req)1385 void reply_getatr(struct smb_request *req)
1386 {
1387 	connection_struct *conn = req->conn;
1388 	struct smb_filename *smb_fname = NULL;
1389 	char *fname = NULL;
1390 	int mode=0;
1391 	off_t size=0;
1392 	time_t mtime=0;
1393 	const char *p;
1394 	NTSTATUS status;
1395 	TALLOC_CTX *ctx = talloc_tos();
1396 	bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1397 
1398 	START_PROFILE(SMBgetatr);
1399 
1400 	p = (const char *)req->buf + 1;
1401 	p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1402 	if (!NT_STATUS_IS_OK(status)) {
1403 		reply_nterror(req, status);
1404 		goto out;
1405 	}
1406 
1407 	/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1408 		under WfWg - weird! */
1409 	if (*fname == '\0') {
1410 		mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1411 		if (!CAN_WRITE(conn)) {
1412 			mode |= FILE_ATTRIBUTE_READONLY;
1413 		}
1414 		size = 0;
1415 		mtime = 0;
1416 	} else {
1417 		uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1418 		status = filename_convert(ctx,
1419 				conn,
1420 				fname,
1421 				ucf_flags,
1422 				NULL,
1423 				NULL,
1424 				&smb_fname);
1425 		if (!NT_STATUS_IS_OK(status)) {
1426 			if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1427 				reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1428 						ERRSRV, ERRbadpath);
1429 				goto out;
1430 			}
1431 			reply_nterror(req, status);
1432 			goto out;
1433 		}
1434 		if (!VALID_STAT(smb_fname->st) &&
1435 		    (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1436 			DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1437 				 smb_fname_str_dbg(smb_fname),
1438 				 strerror(errno)));
1439 			reply_nterror(req,  map_nt_error_from_unix(errno));
1440 			goto out;
1441 		}
1442 
1443 		mode = dos_mode(conn, smb_fname);
1444 		size = smb_fname->st.st_ex_size;
1445 
1446 		if (ask_sharemode) {
1447 			struct timespec write_time_ts;
1448 			struct file_id fileid;
1449 
1450 			ZERO_STRUCT(write_time_ts);
1451 			fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1452 			get_file_infos(fileid, 0, NULL, &write_time_ts);
1453 			if (!is_omit_timespec(&write_time_ts)) {
1454 				update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1455 			}
1456 		}
1457 
1458 		mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1459 		if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1460 			size = 0;
1461 		}
1462 	}
1463 
1464 	reply_outbuf(req, 10, 0);
1465 
1466 	SSVAL(req->outbuf,smb_vwv0,mode);
1467 	if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1468 		srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1469 	} else {
1470 		srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1471 	}
1472 	SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1473 
1474 	if (get_Protocol() >= PROTOCOL_NT1) {
1475 		SSVAL(req->outbuf, smb_flg2,
1476 		      SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1477 	}
1478 
1479 	DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1480 		 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1481 
1482  out:
1483 	TALLOC_FREE(smb_fname);
1484 	TALLOC_FREE(fname);
1485 	END_PROFILE(SMBgetatr);
1486 	return;
1487 }
1488 
1489 /****************************************************************************
1490  Reply to a setatr.
1491 ****************************************************************************/
1492 
reply_setatr(struct smb_request * req)1493 void reply_setatr(struct smb_request *req)
1494 {
1495 	struct smb_file_time ft;
1496 	connection_struct *conn = req->conn;
1497 	struct smb_filename *smb_fname = NULL;
1498 	char *fname = NULL;
1499 	int mode;
1500 	time_t mtime;
1501 	const char *p;
1502 	NTSTATUS status;
1503 	uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1504 	TALLOC_CTX *ctx = talloc_tos();
1505 
1506 	START_PROFILE(SMBsetatr);
1507 	init_smb_file_time(&ft);
1508 
1509 	if (req->wct < 2) {
1510 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1511 		goto out;
1512 	}
1513 
1514 	p = (const char *)req->buf + 1;
1515 	p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1516 	if (!NT_STATUS_IS_OK(status)) {
1517 		reply_nterror(req, status);
1518 		goto out;
1519 	}
1520 
1521 	status = filename_convert(ctx,
1522 				conn,
1523 				fname,
1524 				ucf_flags,
1525 				NULL,
1526 				NULL,
1527 				&smb_fname);
1528 	if (!NT_STATUS_IS_OK(status)) {
1529 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1530 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1531 					ERRSRV, ERRbadpath);
1532 			goto out;
1533 		}
1534 		reply_nterror(req, status);
1535 		goto out;
1536 	}
1537 
1538 	if (ISDOT(smb_fname->base_name)) {
1539 		/*
1540 		 * Not sure here is the right place to catch this
1541 		 * condition. Might be moved to somewhere else later -- vl
1542 		 */
1543 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1544 		goto out;
1545 	}
1546 
1547 	mode = SVAL(req->vwv+0, 0);
1548 	mtime = srv_make_unix_date3(req->vwv+1);
1549 
1550 	if (mode != FILE_ATTRIBUTE_NORMAL) {
1551 		if (VALID_STAT_OF_DIR(smb_fname->st))
1552 			mode |= FILE_ATTRIBUTE_DIRECTORY;
1553 		else
1554 			mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1555 
1556 		status = smbd_check_access_rights(
1557 			conn, smb_fname, false, FILE_WRITE_ATTRIBUTES);
1558 		if (!NT_STATUS_IS_OK(status)) {
1559 			reply_nterror(req, status);
1560 			goto out;
1561 		}
1562 
1563 		if (file_set_dosmode(conn, smb_fname, mode, NULL,
1564 				     false) != 0) {
1565 			reply_nterror(req, map_nt_error_from_unix(errno));
1566 			goto out;
1567 		}
1568 	}
1569 
1570 	ft.mtime = time_t_to_full_timespec(mtime);
1571 
1572 	status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1573 	if (!NT_STATUS_IS_OK(status)) {
1574 		reply_nterror(req, status);
1575 		goto out;
1576 	}
1577 
1578 	reply_outbuf(req, 0, 0);
1579 
1580 	DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1581 		 mode));
1582  out:
1583 	TALLOC_FREE(smb_fname);
1584 	END_PROFILE(SMBsetatr);
1585 	return;
1586 }
1587 
1588 /****************************************************************************
1589  Reply to a dskattr.
1590 ****************************************************************************/
1591 
reply_dskattr(struct smb_request * req)1592 void reply_dskattr(struct smb_request *req)
1593 {
1594 	connection_struct *conn = req->conn;
1595 	uint64_t ret;
1596 	uint64_t dfree,dsize,bsize;
1597 	struct smb_filename smb_fname;
1598 	START_PROFILE(SMBdskattr);
1599 
1600 	ZERO_STRUCT(smb_fname);
1601 	smb_fname.base_name = discard_const_p(char, ".");
1602 
1603 	if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1604 		reply_nterror(req, map_nt_error_from_unix(errno));
1605 		DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1606 		END_PROFILE(SMBdskattr);
1607 		return;
1608 	}
1609 
1610 	ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1611 	if (ret == (uint64_t)-1) {
1612 		reply_nterror(req, map_nt_error_from_unix(errno));
1613 		END_PROFILE(SMBdskattr);
1614 		return;
1615 	}
1616 
1617 	/*
1618 	 * Force max to fit in 16 bit fields.
1619 	 */
1620 	while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1621 		dfree /= 2;
1622 		dsize /= 2;
1623 		bsize *= 2;
1624 		if (bsize > (WORDMAX*512)) {
1625 			bsize = (WORDMAX*512);
1626 			if (dsize > WORDMAX)
1627 				dsize = WORDMAX;
1628 			if (dfree >  WORDMAX)
1629 				dfree = WORDMAX;
1630 			break;
1631 		}
1632 	}
1633 
1634 	reply_outbuf(req, 5, 0);
1635 
1636 	if (get_Protocol() <= PROTOCOL_LANMAN2) {
1637 		double total_space, free_space;
1638 		/* we need to scale this to a number that DOS6 can handle. We
1639 		   use floating point so we can handle large drives on systems
1640 		   that don't have 64 bit integers
1641 
1642 		   we end up displaying a maximum of 2G to DOS systems
1643 		*/
1644 		total_space = dsize * (double)bsize;
1645 		free_space = dfree * (double)bsize;
1646 
1647 		dsize = (uint64_t)((total_space+63*512) / (64*512));
1648 		dfree = (uint64_t)((free_space+63*512) / (64*512));
1649 
1650 		if (dsize > 0xFFFF) dsize = 0xFFFF;
1651 		if (dfree > 0xFFFF) dfree = 0xFFFF;
1652 
1653 		SSVAL(req->outbuf,smb_vwv0,dsize);
1654 		SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1655 		SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1656 		SSVAL(req->outbuf,smb_vwv3,dfree);
1657 	} else {
1658 		SSVAL(req->outbuf,smb_vwv0,dsize);
1659 		SSVAL(req->outbuf,smb_vwv1,bsize/512);
1660 		SSVAL(req->outbuf,smb_vwv2,512);
1661 		SSVAL(req->outbuf,smb_vwv3,dfree);
1662 	}
1663 
1664 	DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1665 
1666 	END_PROFILE(SMBdskattr);
1667 	return;
1668 }
1669 
1670 /*
1671  * Utility function to split the filename from the directory.
1672  */
split_fname_dir_mask(TALLOC_CTX * ctx,const char * fname_in,char ** fname_dir_out,char ** fname_mask_out)1673 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1674 				     char **fname_dir_out,
1675 				     char **fname_mask_out)
1676 {
1677 	const char *p = NULL;
1678 	char *fname_dir = NULL;
1679 	char *fname_mask = NULL;
1680 
1681 	p = strrchr_m(fname_in, '/');
1682 	if (!p) {
1683 		fname_dir = talloc_strdup(ctx, ".");
1684 		fname_mask = talloc_strdup(ctx, fname_in);
1685 	} else {
1686 		fname_dir = talloc_strndup(ctx, fname_in,
1687 		    PTR_DIFF(p, fname_in));
1688 		fname_mask = talloc_strdup(ctx, p+1);
1689 	}
1690 
1691 	if (!fname_dir || !fname_mask) {
1692 		TALLOC_FREE(fname_dir);
1693 		TALLOC_FREE(fname_mask);
1694 		return NT_STATUS_NO_MEMORY;
1695 	}
1696 
1697 	*fname_dir_out = fname_dir;
1698 	*fname_mask_out = fname_mask;
1699 	return NT_STATUS_OK;
1700 }
1701 
1702 /****************************************************************************
1703  Make a dir struct.
1704 ****************************************************************************/
1705 
make_dir_struct(TALLOC_CTX * ctx,char * buf,const char * mask,const char * fname,off_t size,uint32_t mode,time_t date,bool uc)1706 static bool make_dir_struct(TALLOC_CTX *ctx,
1707 			    char *buf,
1708 			    const char *mask,
1709 			    const char *fname,
1710 			    off_t size,
1711 			    uint32_t mode,
1712 			    time_t date,
1713 			    bool uc)
1714 {
1715 	char *p;
1716 	char *mask2 = talloc_strdup(ctx, mask);
1717 
1718 	if (!mask2) {
1719 		return False;
1720 	}
1721 
1722 	if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1723 		size = 0;
1724 	}
1725 
1726 	memset(buf+1,' ',11);
1727 	if ((p = strchr_m(mask2,'.')) != NULL) {
1728 		*p = 0;
1729 		push_ascii(buf+1,mask2,8, 0);
1730 		push_ascii(buf+9,p+1,3, 0);
1731 		*p = '.';
1732 	} else {
1733 		push_ascii(buf+1,mask2,11, 0);
1734 	}
1735 
1736 	memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1737 	SCVAL(buf,21,mode);
1738 	srv_put_dos_date(buf,22,date);
1739 	SSVAL(buf,26,size & 0xFFFF);
1740 	SSVAL(buf,28,(size >> 16)&0xFFFF);
1741 	/* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1742 	   Strange, but verified on W2K3. Needed for OS/2. JRA. */
1743 	push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1744 	DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1745 	return True;
1746 }
1747 
1748 /****************************************************************************
1749  Reply to a search.
1750  Can be called from SMBsearch, SMBffirst or SMBfunique.
1751 ****************************************************************************/
1752 
reply_search(struct smb_request * req)1753 void reply_search(struct smb_request *req)
1754 {
1755 	connection_struct *conn = req->conn;
1756 	char *path = NULL;
1757 	char *mask = NULL;
1758 	char *directory = NULL;
1759 	struct smb_filename *smb_fname = NULL;
1760 	char *fname = NULL;
1761 	off_t size;
1762 	uint32_t mode;
1763 	struct timespec date;
1764 	uint32_t dirtype;
1765 	unsigned int numentries = 0;
1766 	unsigned int maxentries = 0;
1767 	bool finished = False;
1768 	const char *p;
1769 	int status_len;
1770 	char status[21];
1771 	int dptr_num= -1;
1772 	bool check_descend = False;
1773 	bool expect_close = False;
1774 	NTSTATUS nt_status;
1775 	bool mask_contains_wcard = False;
1776 	bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1777 	TALLOC_CTX *ctx = talloc_tos();
1778 	bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1779 	struct smbXsrv_connection *xconn = req->xconn;
1780 	struct smbd_server_connection *sconn = req->sconn;
1781 	files_struct *fsp = NULL;
1782 	const struct loadparm_substitution *lp_sub =
1783 		loadparm_s3_global_substitution();
1784 
1785 	START_PROFILE(SMBsearch);
1786 
1787 	if (req->wct < 2) {
1788 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1789 		goto out;
1790 	}
1791 
1792 	if (req->posix_pathnames) {
1793 		reply_unknown_new(req, req->cmd);
1794 		goto out;
1795 	}
1796 
1797 	/* If we were called as SMBffirst then we must expect close. */
1798 	if(req->cmd == SMBffirst) {
1799 		expect_close = True;
1800 	}
1801 
1802 	reply_outbuf(req, 1, 3);
1803 	maxentries = SVAL(req->vwv+0, 0);
1804 	dirtype = SVAL(req->vwv+1, 0);
1805 	p = (const char *)req->buf + 1;
1806 	p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1807 				       &nt_status, &mask_contains_wcard);
1808 	if (!NT_STATUS_IS_OK(nt_status)) {
1809 		reply_nterror(req, nt_status);
1810 		goto out;
1811 	}
1812 
1813 	if (smbreq_bufrem(req, p) < 3) {
1814 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1815 		goto out;
1816 	}
1817 
1818 	p++;
1819 	status_len = SVAL(p, 0);
1820 	p += 2;
1821 
1822 	/* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1823 
1824 	if (status_len == 0) {
1825 		int ret;
1826 		struct smb_filename *smb_dname = NULL;
1827 		uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1828 			ucf_flags_from_smb_request(req);
1829 		nt_status = filename_convert(ctx, conn,
1830 					     path,
1831 					     ucf_flags,
1832 					     NULL,
1833 					     &mask_contains_wcard,
1834 					     &smb_fname);
1835 		if (!NT_STATUS_IS_OK(nt_status)) {
1836 			if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1837 				reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1838 						ERRSRV, ERRbadpath);
1839 				goto out;
1840 			}
1841 			reply_nterror(req, nt_status);
1842 			goto out;
1843 		}
1844 
1845 		directory = smb_fname->base_name;
1846 
1847 		p = strrchr_m(directory,'/');
1848 		if ((p != NULL) && (*directory != '/')) {
1849 			mask = talloc_strdup(ctx, p + 1);
1850 			directory = talloc_strndup(ctx, directory,
1851 						   PTR_DIFF(p, directory));
1852 		} else {
1853 			mask = talloc_strdup(ctx, directory);
1854 			directory = talloc_strdup(ctx,".");
1855 		}
1856 
1857 		if (!directory) {
1858 			reply_nterror(req, NT_STATUS_NO_MEMORY);
1859 			goto out;
1860 		}
1861 
1862 		memset((char *)status,'\0',21);
1863 		SCVAL(status,0,(dirtype & 0x1F));
1864 
1865 		smb_dname = synthetic_smb_fname(talloc_tos(),
1866 					directory,
1867 					NULL,
1868 					NULL,
1869 					smb_fname->flags);
1870 		if (smb_dname == NULL) {
1871 			reply_nterror(req, NT_STATUS_NO_MEMORY);
1872 			goto out;
1873 		}
1874 
1875 		/*
1876 		 * As we've cut off the last component from
1877 		 * smb_fname we need to re-stat smb_dname
1878 		 * so FILE_OPEN disposition knows the directory
1879 		 * exists.
1880 		 */
1881 		if (req->posix_pathnames) {
1882 			ret = SMB_VFS_LSTAT(conn, smb_dname);
1883 		} else {
1884 			ret = SMB_VFS_STAT(conn, smb_dname);
1885 		}
1886 		if (ret == -1) {
1887 			nt_status = map_nt_error_from_unix(errno);
1888 			reply_nterror(req, nt_status);
1889 			goto out;
1890 		}
1891 
1892 		/*
1893 		 * Open an fsp on this directory for the dptr.
1894 		 */
1895 		nt_status = SMB_VFS_CREATE_FILE(
1896 				conn, /* conn */
1897 				req, /* req */
1898 				0, /* root_dir_fid */
1899 				smb_dname, /* dname */
1900 				FILE_LIST_DIRECTORY, /* access_mask */
1901 				FILE_SHARE_READ|
1902 				FILE_SHARE_WRITE, /* share_access */
1903 				FILE_OPEN, /* create_disposition*/
1904 				FILE_DIRECTORY_FILE, /* create_options */
1905 				FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1906 				NO_OPLOCK, /* oplock_request */
1907 				NULL, /* lease */
1908 				0, /* allocation_size */
1909 				0, /* private_flags */
1910 				NULL, /* sd */
1911 				NULL, /* ea_list */
1912 				&fsp, /* result */
1913 				NULL, /* pinfo */
1914 				NULL, /* in_context */
1915 				NULL);/* out_context */
1916 
1917 		if (!NT_STATUS_IS_OK(nt_status)) {
1918 			DBG_ERR("failed to open directory %s\n",
1919 				smb_fname_str_dbg(smb_dname));
1920 			reply_nterror(req, nt_status);
1921 			goto out;
1922 		}
1923 
1924 		nt_status = dptr_create(conn,
1925 					NULL, /* req */
1926 					fsp, /* fsp */
1927 					True,
1928 					expect_close,
1929 					req->smbpid,
1930 					mask,
1931 					mask_contains_wcard,
1932 					dirtype,
1933 					&fsp->dptr);
1934 
1935 		TALLOC_FREE(smb_dname);
1936 
1937 		if (!NT_STATUS_IS_OK(nt_status)) {
1938 			/*
1939 			 * Use NULL here for the first parameter (req)
1940 			 * as this is not a client visible handle so
1941 			 * can'tbe part of an SMB1 chain.
1942 			 */
1943 			close_file(NULL, fsp, NORMAL_CLOSE);
1944 			fsp = NULL;
1945 			reply_nterror(req, nt_status);
1946 			goto out;
1947 		}
1948 
1949 		dptr_num = dptr_dnum(fsp->dptr);
1950 
1951 	} else {
1952 		int status_dirtype;
1953 		const char *dirpath;
1954 
1955 		if (smbreq_bufrem(req, p) < 21) {
1956 			reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1957 			goto out;
1958 		}
1959 
1960 		memcpy(status,p,21);
1961 		status_dirtype = CVAL(status,0) & 0x1F;
1962 		if (status_dirtype != (dirtype & 0x1F)) {
1963 			dirtype = status_dirtype;
1964 		}
1965 
1966 		fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1967 		if (fsp == NULL) {
1968 			goto SearchEmpty;
1969 		}
1970 		dirpath = dptr_path(sconn, dptr_num);
1971 		directory = talloc_strdup(ctx, dirpath);
1972 		if (!directory) {
1973 			reply_nterror(req, NT_STATUS_NO_MEMORY);
1974 			goto out;
1975 		}
1976 
1977 		mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1978 		if (!mask) {
1979 			goto SearchEmpty;
1980 		}
1981 		/*
1982 		 * For a 'continue' search we have no string. So
1983 		 * check from the initial saved string.
1984 		 */
1985 		if (!req->posix_pathnames) {
1986 			mask_contains_wcard = ms_has_wild(mask);
1987 		}
1988 		dirtype = dptr_attr(sconn, dptr_num);
1989 	}
1990 
1991 	DEBUG(4,("dptr_num is %d\n",dptr_num));
1992 
1993 	if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1994 		char buf[DIR_STRUCT_SIZE];
1995 		memcpy(buf,status,21);
1996 		if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1997 				0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1998 			reply_nterror(req, NT_STATUS_NO_MEMORY);
1999 			goto out;
2000 		}
2001 		dptr_fill(sconn, buf+12,dptr_num);
2002 		if (dptr_zero(buf+12) && (status_len==0)) {
2003 			numentries = 1;
2004 		} else {
2005 			numentries = 0;
2006 		}
2007 		if (message_push_blob(&req->outbuf,
2008 				      data_blob_const(buf, sizeof(buf)))
2009 		    == -1) {
2010 			reply_nterror(req, NT_STATUS_NO_MEMORY);
2011 			goto out;
2012 		}
2013 	} else {
2014 		unsigned int i;
2015 		size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
2016 		size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
2017 
2018 		maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
2019 
2020 		DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2021 			 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
2022 		if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
2023 			check_descend = True;
2024 		}
2025 
2026 		for (i=numentries;(i<maxentries) && !finished;i++) {
2027 			finished = !get_dir_entry(ctx,
2028 						  fsp->dptr,
2029 						  mask,
2030 						  dirtype,
2031 						  &fname,
2032 						  &size,
2033 						  &mode,
2034 						  &date,
2035 						  check_descend,
2036 						  ask_sharemode);
2037 			if (!finished) {
2038 				char buf[DIR_STRUCT_SIZE];
2039 				memcpy(buf,status,21);
2040 				if (!make_dir_struct(ctx,
2041 						buf,
2042 						mask,
2043 						fname,
2044 						size,
2045 						mode,
2046 						convert_timespec_to_time_t(date),
2047 						!allow_long_path_components)) {
2048 					reply_nterror(req, NT_STATUS_NO_MEMORY);
2049 					goto out;
2050 				}
2051 				if (!dptr_fill(sconn, buf+12,dptr_num)) {
2052 					break;
2053 				}
2054 				if (message_push_blob(&req->outbuf,
2055 						      data_blob_const(buf, sizeof(buf)))
2056 				    == -1) {
2057 					reply_nterror(req, NT_STATUS_NO_MEMORY);
2058 					goto out;
2059 				}
2060 				numentries++;
2061 			}
2062 		}
2063 	}
2064 
2065   SearchEmpty:
2066 
2067 	/* If we were called as SMBffirst with smb_search_id == NULL
2068 		and no entries were found then return error and close fsp->dptr
2069 		(X/Open spec) */
2070 
2071 	if (numentries == 0) {
2072 		dptr_num = -1;
2073 		if (fsp != NULL) {
2074 			close_file(NULL, fsp, NORMAL_CLOSE);
2075 			fsp = NULL;
2076 		}
2077 	} else if(expect_close && status_len == 0) {
2078 		/* Close the dptr - we know it's gone */
2079 		dptr_num = -1;
2080 		if (fsp != NULL) {
2081 			close_file(NULL, fsp, NORMAL_CLOSE);
2082 			fsp = NULL;
2083 		}
2084 	}
2085 
2086 	/* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2087 	if(dptr_num >= 0 && req->cmd == SMBfunique) {
2088 		dptr_num = -1;
2089 		/* fsp may have been closed above. */
2090 		if (fsp != NULL) {
2091 			close_file(NULL, fsp, NORMAL_CLOSE);
2092 			fsp = NULL;
2093 		}
2094 	}
2095 
2096 	if ((numentries == 0) && !mask_contains_wcard) {
2097 		reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2098 		goto out;
2099 	}
2100 
2101 	SSVAL(req->outbuf,smb_vwv0,numentries);
2102 	SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2103 	SCVAL(smb_buf(req->outbuf),0,5);
2104 	SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2105 
2106 	/* The replies here are never long name. */
2107 	SSVAL(req->outbuf, smb_flg2,
2108 	      SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2109 	if (!allow_long_path_components) {
2110 		SSVAL(req->outbuf, smb_flg2,
2111 		      SVAL(req->outbuf, smb_flg2)
2112 		      & (~FLAGS2_LONG_PATH_COMPONENTS));
2113 	}
2114 
2115 	/* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2116 	SSVAL(req->outbuf, smb_flg2,
2117 	      (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2118 
2119 	DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2120 		smb_fn_name(req->cmd),
2121 		mask,
2122 		directory,
2123 		dirtype,
2124 		numentries,
2125 		maxentries ));
2126  out:
2127 	TALLOC_FREE(directory);
2128 	TALLOC_FREE(mask);
2129 	TALLOC_FREE(smb_fname);
2130 	END_PROFILE(SMBsearch);
2131 	return;
2132 }
2133 
2134 /****************************************************************************
2135  Reply to a fclose (stop directory search).
2136 ****************************************************************************/
2137 
reply_fclose(struct smb_request * req)2138 void reply_fclose(struct smb_request *req)
2139 {
2140 	int status_len;
2141 	char status[21];
2142 	int dptr_num= -2;
2143 	const char *p;
2144 	char *path = NULL;
2145 	NTSTATUS err;
2146 	bool path_contains_wcard = False;
2147 	TALLOC_CTX *ctx = talloc_tos();
2148 	struct smbd_server_connection *sconn = req->sconn;
2149 	files_struct *fsp = NULL;
2150 
2151 	START_PROFILE(SMBfclose);
2152 
2153 	if (req->posix_pathnames) {
2154 		reply_unknown_new(req, req->cmd);
2155 		END_PROFILE(SMBfclose);
2156 		return;
2157 	}
2158 
2159 	p = (const char *)req->buf + 1;
2160 	p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2161 				       &err, &path_contains_wcard);
2162 	if (!NT_STATUS_IS_OK(err)) {
2163 		reply_nterror(req, err);
2164 		END_PROFILE(SMBfclose);
2165 		return;
2166 	}
2167 
2168 	if (smbreq_bufrem(req, p) < 3) {
2169 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2170 		END_PROFILE(SMBfclose);
2171 		return;
2172 	}
2173 
2174 	p++;
2175 	status_len = SVAL(p,0);
2176 	p += 2;
2177 
2178 	if (status_len == 0) {
2179 		reply_force_doserror(req, ERRSRV, ERRsrverror);
2180 		END_PROFILE(SMBfclose);
2181 		return;
2182 	}
2183 
2184 	if (smbreq_bufrem(req, p) < 21) {
2185 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2186 		END_PROFILE(SMBfclose);
2187 		return;
2188 	}
2189 
2190 	memcpy(status,p,21);
2191 
2192 	fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2193 	if(fsp != NULL) {
2194 		/*  Close the file - we know it's gone */
2195 		close_file(NULL, fsp, NORMAL_CLOSE);
2196 		fsp = NULL;
2197 		dptr_num = -1;
2198 	}
2199 
2200 	reply_outbuf(req, 1, 0);
2201 	SSVAL(req->outbuf,smb_vwv0,0);
2202 
2203 	DEBUG(3,("search close\n"));
2204 
2205 	END_PROFILE(SMBfclose);
2206 	return;
2207 }
2208 
2209 /****************************************************************************
2210  Reply to an open.
2211 ****************************************************************************/
2212 
reply_open(struct smb_request * req)2213 void reply_open(struct smb_request *req)
2214 {
2215 	connection_struct *conn = req->conn;
2216 	struct smb_filename *smb_fname = NULL;
2217 	char *fname = NULL;
2218 	uint32_t fattr=0;
2219 	off_t size = 0;
2220 	time_t mtime=0;
2221 	int info;
2222 	files_struct *fsp;
2223 	int oplock_request;
2224 	int deny_mode;
2225 	uint32_t dos_attr;
2226 	uint32_t access_mask;
2227 	uint32_t share_mode;
2228 	uint32_t create_disposition;
2229 	uint32_t create_options = 0;
2230 	uint32_t private_flags = 0;
2231 	NTSTATUS status;
2232 	uint32_t ucf_flags;
2233 	TALLOC_CTX *ctx = talloc_tos();
2234 
2235 	START_PROFILE(SMBopen);
2236 
2237 	if (req->wct < 2) {
2238 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2239 		goto out;
2240 	}
2241 
2242 	oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2243 	deny_mode = SVAL(req->vwv+0, 0);
2244 	dos_attr = SVAL(req->vwv+1, 0);
2245 
2246 	srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2247 			    STR_TERMINATE, &status);
2248 	if (!NT_STATUS_IS_OK(status)) {
2249 		reply_nterror(req, status);
2250 		goto out;
2251 	}
2252 
2253 	if (!map_open_params_to_ntcreate(fname, deny_mode,
2254 					 OPENX_FILE_EXISTS_OPEN, &access_mask,
2255 					 &share_mode, &create_disposition,
2256 					 &create_options, &private_flags)) {
2257 		reply_force_doserror(req, ERRDOS, ERRbadaccess);
2258 		goto out;
2259 	}
2260 
2261 	ucf_flags = filename_create_ucf_flags(req, create_disposition);
2262 
2263 	status = filename_convert(ctx,
2264 				conn,
2265 				fname,
2266 				ucf_flags,
2267 				NULL,
2268 				NULL,
2269 				&smb_fname);
2270 	if (!NT_STATUS_IS_OK(status)) {
2271 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2272 			reply_botherror(req,
2273 					NT_STATUS_PATH_NOT_COVERED,
2274 					ERRSRV, ERRbadpath);
2275 			goto out;
2276 		}
2277 		reply_nterror(req, status);
2278 		goto out;
2279 	}
2280 
2281 	status = SMB_VFS_CREATE_FILE(
2282 		conn,					/* conn */
2283 		req,					/* req */
2284 		0,					/* root_dir_fid */
2285 		smb_fname,				/* fname */
2286 		access_mask,				/* access_mask */
2287 		share_mode,				/* share_access */
2288 		create_disposition,			/* create_disposition*/
2289 		create_options,				/* create_options */
2290 		dos_attr,				/* file_attributes */
2291 		oplock_request,				/* oplock_request */
2292 		NULL,					/* lease */
2293 		0,					/* allocation_size */
2294 		private_flags,
2295 		NULL,					/* sd */
2296 		NULL,					/* ea_list */
2297 		&fsp,					/* result */
2298 		&info,					/* pinfo */
2299 		NULL, NULL);				/* create context */
2300 
2301 	if (!NT_STATUS_IS_OK(status)) {
2302 		if (open_was_deferred(req->xconn, req->mid)) {
2303 			/* We have re-scheduled this call. */
2304 			goto out;
2305 		}
2306 
2307 		if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2308 			reply_openerror(req, status);
2309 			goto out;
2310 		}
2311 
2312 		fsp = fcb_or_dos_open(
2313 			req,
2314 			smb_fname,
2315 			access_mask,
2316 			create_options,
2317 			private_flags);
2318 		if (fsp == NULL) {
2319 			bool ok = defer_smb1_sharing_violation(req);
2320 			if (ok) {
2321 				goto out;
2322 			}
2323 			reply_openerror(req, status);
2324 			goto out;
2325 		}
2326 	}
2327 
2328 	/* Ensure we're pointing at the correct stat struct. */
2329 	TALLOC_FREE(smb_fname);
2330 	smb_fname = fsp->fsp_name;
2331 
2332 	size = smb_fname->st.st_ex_size;
2333 	fattr = dos_mode(conn, smb_fname);
2334 
2335 	mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2336 
2337 	if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2338 		DEBUG(3,("attempt to open a directory %s\n",
2339 			 fsp_str_dbg(fsp)));
2340 		close_file(req, fsp, ERROR_CLOSE);
2341 		reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2342 			ERRDOS, ERRnoaccess);
2343 		goto out;
2344 	}
2345 
2346 	reply_outbuf(req, 7, 0);
2347 	SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2348 	SSVAL(req->outbuf,smb_vwv1,fattr);
2349 	if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2350 		srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2351 	} else {
2352 		srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2353 	}
2354 	SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2355 	SSVAL(req->outbuf,smb_vwv6,deny_mode);
2356 
2357 	if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2358 		SCVAL(req->outbuf,smb_flg,
2359 		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2360 	}
2361 
2362 	if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2363 		SCVAL(req->outbuf,smb_flg,
2364 		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2365 	}
2366  out:
2367 	END_PROFILE(SMBopen);
2368 	return;
2369 }
2370 
2371 /****************************************************************************
2372  Reply to an open and X.
2373 ****************************************************************************/
2374 
reply_open_and_X(struct smb_request * req)2375 void reply_open_and_X(struct smb_request *req)
2376 {
2377 	connection_struct *conn = req->conn;
2378 	struct smb_filename *smb_fname = NULL;
2379 	char *fname = NULL;
2380 	uint16_t open_flags;
2381 	int deny_mode;
2382 	uint32_t smb_attr;
2383 	/* Breakout the oplock request bits so we can set the
2384 		reply bits separately. */
2385 	int ex_oplock_request;
2386 	int core_oplock_request;
2387 	int oplock_request;
2388 #if 0
2389 	int smb_sattr = SVAL(req->vwv+4, 0);
2390 	uint32_t smb_time = make_unix_date3(req->vwv+6);
2391 #endif
2392 	int smb_ofun;
2393 	uint32_t fattr=0;
2394 	int mtime=0;
2395 	int smb_action = 0;
2396 	files_struct *fsp;
2397 	NTSTATUS status;
2398 	uint64_t allocation_size;
2399 	ssize_t retval = -1;
2400 	uint32_t access_mask;
2401 	uint32_t share_mode;
2402 	uint32_t create_disposition;
2403 	uint32_t create_options = 0;
2404 	uint32_t private_flags = 0;
2405 	uint32_t ucf_flags;
2406 	TALLOC_CTX *ctx = talloc_tos();
2407 
2408 	START_PROFILE(SMBopenX);
2409 
2410 	if (req->wct < 15) {
2411 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2412 		goto out;
2413 	}
2414 
2415 	open_flags = SVAL(req->vwv+2, 0);
2416 	deny_mode = SVAL(req->vwv+3, 0);
2417 	smb_attr = SVAL(req->vwv+5, 0);
2418 	ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2419 	core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2420 	oplock_request = ex_oplock_request | core_oplock_request;
2421 	smb_ofun = SVAL(req->vwv+8, 0);
2422 	allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2423 
2424 	/* If it's an IPC, pass off the pipe handler. */
2425 	if (IS_IPC(conn)) {
2426 		if (lp_nt_pipe_support()) {
2427 			reply_open_pipe_and_X(conn, req);
2428 		} else {
2429 			reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2430 		}
2431 		goto out;
2432 	}
2433 
2434 	/* XXXX we need to handle passed times, sattr and flags */
2435 	srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2436 			STR_TERMINATE, &status);
2437 	if (!NT_STATUS_IS_OK(status)) {
2438 		reply_nterror(req, status);
2439 		goto out;
2440 	}
2441 
2442 	if (!map_open_params_to_ntcreate(fname, deny_mode,
2443 					 smb_ofun,
2444 					 &access_mask, &share_mode,
2445 					 &create_disposition,
2446 					 &create_options,
2447 					 &private_flags)) {
2448 		reply_force_doserror(req, ERRDOS, ERRbadaccess);
2449 		goto out;
2450 	}
2451 
2452 	ucf_flags = filename_create_ucf_flags(req, create_disposition);
2453 
2454 	status = filename_convert(ctx,
2455 				conn,
2456 				fname,
2457 				ucf_flags,
2458 				NULL,
2459 				NULL,
2460 				&smb_fname);
2461 	if (!NT_STATUS_IS_OK(status)) {
2462 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2463 			reply_botherror(req,
2464 					NT_STATUS_PATH_NOT_COVERED,
2465 					ERRSRV, ERRbadpath);
2466 			goto out;
2467 		}
2468 		reply_nterror(req, status);
2469 		goto out;
2470 	}
2471 
2472 	status = SMB_VFS_CREATE_FILE(
2473 		conn,					/* conn */
2474 		req,					/* req */
2475 		0,					/* root_dir_fid */
2476 		smb_fname,				/* fname */
2477 		access_mask,				/* access_mask */
2478 		share_mode,				/* share_access */
2479 		create_disposition,			/* create_disposition*/
2480 		create_options,				/* create_options */
2481 		smb_attr,				/* file_attributes */
2482 		oplock_request,				/* oplock_request */
2483 		NULL,					/* lease */
2484 		0,					/* allocation_size */
2485 		private_flags,
2486 		NULL,					/* sd */
2487 		NULL,					/* ea_list */
2488 		&fsp,					/* result */
2489 		&smb_action,				/* pinfo */
2490 		NULL, NULL);				/* create context */
2491 
2492 	if (!NT_STATUS_IS_OK(status)) {
2493 		if (open_was_deferred(req->xconn, req->mid)) {
2494 			/* We have re-scheduled this call. */
2495 			goto out;
2496 		}
2497 
2498 		if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2499 			reply_openerror(req, status);
2500 			goto out;
2501 		}
2502 
2503 		fsp = fcb_or_dos_open(
2504 			req,
2505 			smb_fname,
2506 			access_mask,
2507 			create_options,
2508 			private_flags);
2509 		if (fsp == NULL) {
2510 			bool ok = defer_smb1_sharing_violation(req);
2511 			if (ok) {
2512 				goto out;
2513 			}
2514 			reply_openerror(req, status);
2515 			goto out;
2516 		}
2517 
2518 
2519 		smb_action = FILE_WAS_OPENED;
2520 	}
2521 
2522 	/* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2523 	   if the file is truncated or created. */
2524 	if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2525 		fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2526 		if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2527 			close_file(req, fsp, ERROR_CLOSE);
2528 			reply_nterror(req, NT_STATUS_DISK_FULL);
2529 			goto out;
2530 		}
2531 		retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2532 		if (retval < 0) {
2533 			close_file(req, fsp, ERROR_CLOSE);
2534 			reply_nterror(req, NT_STATUS_DISK_FULL);
2535 			goto out;
2536 		}
2537 		status = vfs_stat_fsp(fsp);
2538 		if (!NT_STATUS_IS_OK(status)) {
2539 			close_file(req, fsp, ERROR_CLOSE);
2540 			reply_nterror(req, status);
2541 			goto out;
2542 		}
2543 	}
2544 
2545 	fattr = dos_mode(conn, fsp->fsp_name);
2546 	if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2547 		close_file(req, fsp, ERROR_CLOSE);
2548 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2549 		goto out;
2550 	}
2551 	mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2552 
2553 	/* If the caller set the extended oplock request bit
2554 		and we granted one (by whatever means) - set the
2555 		correct bit for extended oplock reply.
2556 	*/
2557 
2558 	if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2559 		smb_action |= EXTENDED_OPLOCK_GRANTED;
2560 	}
2561 
2562 	if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2563 		smb_action |= EXTENDED_OPLOCK_GRANTED;
2564 	}
2565 
2566 	/* If the caller set the core oplock request bit
2567 		and we granted one (by whatever means) - set the
2568 		correct bit for core oplock reply.
2569 	*/
2570 
2571 	if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2572 		reply_outbuf(req, 19, 0);
2573 	} else {
2574 		reply_outbuf(req, 15, 0);
2575 	}
2576 
2577 	SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2578 	SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
2579 
2580 	if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2581 		SCVAL(req->outbuf, smb_flg,
2582 		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2583 	}
2584 
2585 	if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2586 		SCVAL(req->outbuf, smb_flg,
2587 		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2588 	}
2589 
2590 	SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2591 	SSVAL(req->outbuf,smb_vwv3,fattr);
2592 	if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2593 		srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2594 	} else {
2595 		srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2596 	}
2597 	SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2598 	SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2599 	SSVAL(req->outbuf,smb_vwv11,smb_action);
2600 
2601 	if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2602 		SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2603 	}
2604 
2605  out:
2606 	TALLOC_FREE(smb_fname);
2607 	END_PROFILE(SMBopenX);
2608 	return;
2609 }
2610 
2611 /****************************************************************************
2612  Reply to a SMBulogoffX.
2613 ****************************************************************************/
2614 
2615 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2616 				struct smbXsrv_session *session);
2617 static void reply_ulogoffX_done(struct tevent_req *req);
2618 
reply_ulogoffX(struct smb_request * smb1req)2619 void reply_ulogoffX(struct smb_request *smb1req)
2620 {
2621 	struct timeval now = timeval_current();
2622 	struct smbXsrv_session *session = NULL;
2623 	struct tevent_req *req;
2624 	NTSTATUS status;
2625 
2626 	/*
2627 	 * Don't setup the profile charge here, take
2628 	 * it in reply_ulogoffX_done(). Not strictly correct
2629 	 * but better than the other SMB1 async
2630 	 * code that double-charges at the moment.
2631 	 */
2632 
2633 	status = smb1srv_session_lookup(smb1req->xconn,
2634 					smb1req->vuid,
2635 					timeval_to_nttime(&now),
2636 					&session);
2637 	if (!NT_STATUS_IS_OK(status)) {
2638 		/* Not going async, profile here. */
2639 		START_PROFILE(SMBulogoffX);
2640 		DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2641 			 (unsigned long long)smb1req->vuid);
2642 
2643 		smb1req->vuid = UID_FIELD_INVALID;
2644 		reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2645 		END_PROFILE(SMBulogoffX);
2646 		return;
2647 	}
2648 
2649 	req = reply_ulogoffX_send(smb1req, session);
2650 	if (req == NULL) {
2651 		/* Not going async, profile here. */
2652 		START_PROFILE(SMBulogoffX);
2653 		reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2654 		END_PROFILE(SMBulogoffX);
2655 		return;
2656 	}
2657 
2658 	/* We're async. This will complete later. */
2659 	tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2660 	return;
2661 }
2662 
2663 struct reply_ulogoffX_state {
2664 	struct tevent_queue *wait_queue;
2665 	struct smbXsrv_session *session;
2666 };
2667 
2668 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2669 
2670 /****************************************************************************
2671  Async SMB1 ulogoffX.
2672  Note, on failure here we deallocate and return NULL to allow the caller to
2673  SMB1 return an error of ERRnomem immediately.
2674 ****************************************************************************/
2675 
reply_ulogoffX_send(struct smb_request * smb1req,struct smbXsrv_session * session)2676 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2677 					struct smbXsrv_session *session)
2678 {
2679 	struct tevent_req *req;
2680 	struct reply_ulogoffX_state *state;
2681 	struct tevent_req *subreq;
2682 	files_struct *fsp;
2683 	struct smbd_server_connection *sconn = session->client->sconn;
2684 	uint64_t vuid = session->global->session_wire_id;
2685 
2686 	req = tevent_req_create(smb1req, &state,
2687 			struct reply_ulogoffX_state);
2688 	if (req == NULL) {
2689 		return NULL;
2690 	}
2691 	state->wait_queue = tevent_queue_create(state,
2692 				"reply_ulogoffX_wait_queue");
2693 	if (tevent_req_nomem(state->wait_queue, req)) {
2694 		TALLOC_FREE(req);
2695 		return NULL;
2696 	}
2697 	state->session = session;
2698 
2699 	/*
2700 	 * Make sure that no new request will be able to use this session.
2701 	 * This ensures that once all outstanding fsp->aio_requests
2702 	 * on this session are done, we are safe to close it.
2703 	 */
2704 	session->status = NT_STATUS_USER_SESSION_DELETED;
2705 
2706 	for (fsp = sconn->files; fsp; fsp = fsp->next) {
2707 		if (fsp->vuid != vuid) {
2708 			continue;
2709 		}
2710 		/*
2711 		 * Flag the file as close in progress.
2712 		 * This will prevent any more IO being
2713 		 * done on it.
2714 		 */
2715 		fsp->closing = true;
2716 
2717 		if (fsp->num_aio_requests > 0) {
2718 			/*
2719 			 * Now wait until all aio requests on this fsp are
2720 			 * finished.
2721 			 *
2722 			 * We don't set a callback, as we just want to block the
2723 			 * wait queue and the talloc_free() of fsp->aio_request
2724 			 * will remove the item from the wait queue.
2725 			 */
2726 			subreq = tevent_queue_wait_send(fsp->aio_requests,
2727 						sconn->ev_ctx,
2728 						state->wait_queue);
2729 			if (tevent_req_nomem(subreq, req)) {
2730 				TALLOC_FREE(req);
2731 				return NULL;
2732 			}
2733 		}
2734 	}
2735 
2736 	/*
2737 	 * Now we add our own waiter to the end of the queue,
2738 	 * this way we get notified when all pending requests are finished
2739 	 * and reply to the outstanding SMB1 request.
2740 	 */
2741 	subreq = tevent_queue_wait_send(state,
2742 				sconn->ev_ctx,
2743 				state->wait_queue);
2744 	if (tevent_req_nomem(subreq, req)) {
2745 		TALLOC_FREE(req);
2746 		return NULL;
2747 	}
2748 
2749 	/*
2750 	 * We're really going async - move the SMB1 request from
2751 	 * a talloc stackframe above us to the sconn talloc-context.
2752 	 * We need this to stick around until the wait_done
2753 	 * callback is invoked.
2754 	 */
2755 	smb1req = talloc_move(sconn, &smb1req);
2756 
2757 	tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2758 
2759 	return req;
2760 }
2761 
reply_ulogoffX_wait_done(struct tevent_req * subreq)2762 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2763 {
2764 	struct tevent_req *req = tevent_req_callback_data(
2765 		subreq, struct tevent_req);
2766 
2767 	tevent_queue_wait_recv(subreq);
2768 	TALLOC_FREE(subreq);
2769 	tevent_req_done(req);
2770 }
2771 
reply_ulogoffX_recv(struct tevent_req * req)2772 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2773 {
2774 	return tevent_req_simple_recv_ntstatus(req);
2775 }
2776 
reply_ulogoffX_done(struct tevent_req * req)2777 static void reply_ulogoffX_done(struct tevent_req *req)
2778 {
2779 	struct smb_request *smb1req = tevent_req_callback_data(
2780 		req, struct smb_request);
2781 	struct reply_ulogoffX_state *state = tevent_req_data(req,
2782 						struct reply_ulogoffX_state);
2783 	struct smbXsrv_session *session = state->session;
2784 	NTSTATUS status;
2785 
2786 	/*
2787 	 * Take the profile charge here. Not strictly
2788 	 * correct but better than the other SMB1 async
2789 	 * code that double-charges at the moment.
2790 	 */
2791 	START_PROFILE(SMBulogoffX);
2792 
2793 	status = reply_ulogoffX_recv(req);
2794 	TALLOC_FREE(req);
2795 	if (!NT_STATUS_IS_OK(status)) {
2796 		TALLOC_FREE(smb1req);
2797 		END_PROFILE(SMBulogoffX);
2798 		exit_server(__location__ ": reply_ulogoffX_recv failed");
2799 		return;
2800 	}
2801 
2802 	status = smbXsrv_session_logoff(session);
2803 	if (!NT_STATUS_IS_OK(status)) {
2804 		TALLOC_FREE(smb1req);
2805 		END_PROFILE(SMBulogoffX);
2806 		exit_server(__location__ ": smbXsrv_session_logoff failed");
2807 		return;
2808 	}
2809 
2810 	TALLOC_FREE(session);
2811 
2812 	reply_outbuf(smb1req, 2, 0);
2813 	SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2814 	SSVAL(smb1req->outbuf, smb_vwv1, 0);    /* no andx offset */
2815 
2816 	DBG_NOTICE("ulogoffX vuid=%llu\n",
2817 		  (unsigned long long)smb1req->vuid);
2818 
2819 	smb1req->vuid = UID_FIELD_INVALID;
2820 	/*
2821 	 * The following call is needed to push the
2822 	 * reply data back out the socket after async
2823 	 * return. Plus it frees smb1req.
2824 	 */
2825 	smb_request_done(smb1req);
2826 	END_PROFILE(SMBulogoffX);
2827 }
2828 
2829 /****************************************************************************
2830  Reply to a mknew or a create.
2831 ****************************************************************************/
2832 
reply_mknew(struct smb_request * req)2833 void reply_mknew(struct smb_request *req)
2834 {
2835 	connection_struct *conn = req->conn;
2836 	struct smb_filename *smb_fname = NULL;
2837 	char *fname = NULL;
2838 	uint32_t fattr = 0;
2839 	struct smb_file_time ft;
2840 	files_struct *fsp;
2841 	int oplock_request = 0;
2842 	NTSTATUS status;
2843 	uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2844 	uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2845 	uint32_t create_disposition;
2846 	uint32_t create_options = 0;
2847 	uint32_t ucf_flags;
2848 	TALLOC_CTX *ctx = talloc_tos();
2849 
2850 	START_PROFILE(SMBcreate);
2851 	init_smb_file_time(&ft);
2852 
2853         if (req->wct < 3) {
2854 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2855 		goto out;
2856 	}
2857 
2858 	fattr = SVAL(req->vwv+0, 0);
2859 	oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2860 
2861 	if (req->cmd == SMBmknew) {
2862 		/* We should fail if file exists. */
2863 		create_disposition = FILE_CREATE;
2864 	} else {
2865 		/* Create if file doesn't exist, truncate if it does. */
2866 		create_disposition = FILE_OVERWRITE_IF;
2867 	}
2868 
2869 	/* mtime. */
2870 	ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2871 
2872 	srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2873 			    STR_TERMINATE, &status);
2874 	if (!NT_STATUS_IS_OK(status)) {
2875 		reply_nterror(req, status);
2876 		goto out;
2877 	}
2878 
2879 	ucf_flags = filename_create_ucf_flags(req, create_disposition);
2880 	status = filename_convert(ctx,
2881 				conn,
2882 				fname,
2883 				ucf_flags,
2884 				NULL,
2885 				NULL,
2886 				&smb_fname);
2887 	if (!NT_STATUS_IS_OK(status)) {
2888 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2889 			reply_botherror(req,
2890 					NT_STATUS_PATH_NOT_COVERED,
2891 					ERRSRV, ERRbadpath);
2892 			goto out;
2893 		}
2894 		reply_nterror(req, status);
2895 		goto out;
2896 	}
2897 
2898 	if (fattr & FILE_ATTRIBUTE_VOLUME) {
2899 		DEBUG(0,("Attempt to create file (%s) with volid set - "
2900 			 "please report this\n",
2901 			 smb_fname_str_dbg(smb_fname)));
2902 	}
2903 
2904 	status = SMB_VFS_CREATE_FILE(
2905 		conn,					/* conn */
2906 		req,					/* req */
2907 		0,					/* root_dir_fid */
2908 		smb_fname,				/* fname */
2909 		access_mask,				/* access_mask */
2910 		share_mode,				/* share_access */
2911 		create_disposition,			/* create_disposition*/
2912 		create_options,				/* create_options */
2913 		fattr,					/* file_attributes */
2914 		oplock_request,				/* oplock_request */
2915 		NULL,					/* lease */
2916 		0,					/* allocation_size */
2917 		0,					/* private_flags */
2918 		NULL,					/* sd */
2919 		NULL,					/* ea_list */
2920 		&fsp,					/* result */
2921 		NULL,					/* pinfo */
2922 		NULL, NULL);				/* create context */
2923 
2924 	if (!NT_STATUS_IS_OK(status)) {
2925 		if (open_was_deferred(req->xconn, req->mid)) {
2926 			/* We have re-scheduled this call. */
2927 			goto out;
2928 		}
2929 		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2930 			bool ok = defer_smb1_sharing_violation(req);
2931 			if (ok) {
2932 				goto out;
2933 			}
2934 		}
2935 		reply_openerror(req, status);
2936 		goto out;
2937 	}
2938 
2939 	ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2940 	status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2941 	if (!NT_STATUS_IS_OK(status)) {
2942 		END_PROFILE(SMBcreate);
2943 		goto out;
2944 	}
2945 
2946 	reply_outbuf(req, 1, 0);
2947 	SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2948 
2949 	if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2950 		SCVAL(req->outbuf,smb_flg,
2951 				CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2952 	}
2953 
2954 	if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2955 		SCVAL(req->outbuf,smb_flg,
2956 				CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2957 	}
2958 
2959 	DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2960 	DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2961 		  smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2962 		  (unsigned int)fattr));
2963 
2964  out:
2965 	TALLOC_FREE(smb_fname);
2966 	END_PROFILE(SMBcreate);
2967 	return;
2968 }
2969 
2970 /****************************************************************************
2971  Reply to a create temporary file.
2972 ****************************************************************************/
2973 
reply_ctemp(struct smb_request * req)2974 void reply_ctemp(struct smb_request *req)
2975 {
2976 	connection_struct *conn = req->conn;
2977 	struct smb_filename *smb_fname = NULL;
2978 	char *wire_name = NULL;
2979 	char *fname = NULL;
2980 	uint32_t fattr;
2981 	files_struct *fsp;
2982 	int oplock_request;
2983 	char *s;
2984 	NTSTATUS status;
2985 	int i;
2986 	uint32_t ucf_flags;
2987 	TALLOC_CTX *ctx = talloc_tos();
2988 
2989 	START_PROFILE(SMBctemp);
2990 
2991 	if (req->wct < 3) {
2992 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2993 		goto out;
2994 	}
2995 
2996 	fattr = SVAL(req->vwv+0, 0);
2997 	oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2998 
2999 	srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
3000 			    STR_TERMINATE, &status);
3001 	if (!NT_STATUS_IS_OK(status)) {
3002 		reply_nterror(req, status);
3003 		goto out;
3004 	}
3005 
3006 	for (i = 0; i < 10; i++) {
3007 		if (*wire_name) {
3008 			fname = talloc_asprintf(ctx,
3009 					"%s/TMP%s",
3010 					wire_name,
3011 					generate_random_str_list(ctx, 5, "0123456789"));
3012 		} else {
3013 			fname = talloc_asprintf(ctx,
3014 					"TMP%s",
3015 					generate_random_str_list(ctx, 5, "0123456789"));
3016 		}
3017 
3018 		if (!fname) {
3019 			reply_nterror(req, NT_STATUS_NO_MEMORY);
3020 			goto out;
3021 		}
3022 
3023 		ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
3024 		status = filename_convert(ctx, conn,
3025 				fname,
3026 				ucf_flags,
3027 				NULL,
3028 				NULL,
3029 				&smb_fname);
3030 		if (!NT_STATUS_IS_OK(status)) {
3031 			if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3032 				reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3033 					ERRSRV, ERRbadpath);
3034 				goto out;
3035 			}
3036 			reply_nterror(req, status);
3037 			goto out;
3038 		}
3039 
3040 		/* Create the file. */
3041 		status = SMB_VFS_CREATE_FILE(
3042 			conn,					/* conn */
3043 			req,					/* req */
3044 			0,					/* root_dir_fid */
3045 			smb_fname,				/* fname */
3046 			FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
3047 			FILE_SHARE_READ | FILE_SHARE_WRITE,	/* share_access */
3048 			FILE_CREATE,				/* create_disposition*/
3049 			0,					/* create_options */
3050 			fattr,					/* file_attributes */
3051 			oplock_request,				/* oplock_request */
3052 			NULL,					/* lease */
3053 			0,					/* allocation_size */
3054 			0,					/* private_flags */
3055 			NULL,					/* sd */
3056 			NULL,					/* ea_list */
3057 			&fsp,					/* result */
3058 			NULL,					/* pinfo */
3059 			NULL, NULL);				/* create context */
3060 
3061 		if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3062 			TALLOC_FREE(fname);
3063 			TALLOC_FREE(smb_fname);
3064 			continue;
3065 		}
3066 
3067 		if (!NT_STATUS_IS_OK(status)) {
3068 			if (open_was_deferred(req->xconn, req->mid)) {
3069 				/* We have re-scheduled this call. */
3070 				goto out;
3071 			}
3072 			if (NT_STATUS_EQUAL(
3073 				    status, NT_STATUS_SHARING_VIOLATION)) {
3074 				bool ok = defer_smb1_sharing_violation(req);
3075 				if (ok) {
3076 					goto out;
3077 				}
3078 			}
3079 			reply_openerror(req, status);
3080 			goto out;
3081 		}
3082 
3083 		break;
3084 	}
3085 
3086 	if (i == 10) {
3087 		/* Collision after 10 times... */
3088 		reply_nterror(req, status);
3089 		goto out;
3090 	}
3091 
3092 	reply_outbuf(req, 1, 0);
3093 	SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3094 
3095 	/* the returned filename is relative to the directory */
3096 	s = strrchr_m(fsp->fsp_name->base_name, '/');
3097 	if (!s) {
3098 		s = fsp->fsp_name->base_name;
3099 	} else {
3100 		s++;
3101 	}
3102 
3103 #if 0
3104 	/* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3105 	   thing in the byte section. JRA */
3106 	SSVALS(p, 0, -1); /* what is this? not in spec */
3107 #endif
3108 	if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3109 	    == -1) {
3110 		reply_nterror(req, NT_STATUS_NO_MEMORY);
3111 		goto out;
3112 	}
3113 
3114 	if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3115 		SCVAL(req->outbuf, smb_flg,
3116 		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3117 	}
3118 
3119 	if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3120 		SCVAL(req->outbuf, smb_flg,
3121 		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3122 	}
3123 
3124 	DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3125 	DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3126 		    fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
3127  out:
3128 	TALLOC_FREE(smb_fname);
3129 	TALLOC_FREE(wire_name);
3130 	END_PROFILE(SMBctemp);
3131 	return;
3132 }
3133 
3134 /*******************************************************************
3135  Check if a user is allowed to rename a file.
3136 ********************************************************************/
3137 
can_rename(connection_struct * conn,files_struct * fsp,uint16_t dirtype)3138 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3139 			uint16_t dirtype)
3140 {
3141 	if (!CAN_WRITE(conn)) {
3142 		return NT_STATUS_MEDIA_WRITE_PROTECTED;
3143 	}
3144 
3145 	if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3146 			(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3147 		/* Only bother to read the DOS attribute if we might deny the
3148 		   rename on the grounds of attribute mismatch. */
3149 		uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3150 		if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3151 			return NT_STATUS_NO_SUCH_FILE;
3152 		}
3153 	}
3154 
3155 	if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3156 		if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3157 			return NT_STATUS_OK;
3158 		}
3159 
3160 		/* If no pathnames are open below this
3161 		   directory, allow the rename. */
3162 
3163 		if (lp_strict_rename(SNUM(conn))) {
3164 			/*
3165 			 * Strict rename, check open file db.
3166 			 */
3167 			if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3168 				return NT_STATUS_ACCESS_DENIED;
3169 			}
3170 		} else if (file_find_subpath(fsp)) {
3171 			/*
3172 			 * No strict rename, just look in local process.
3173 			 */
3174 			return NT_STATUS_ACCESS_DENIED;
3175 		}
3176 		return NT_STATUS_OK;
3177 	}
3178 
3179 	if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3180 		return NT_STATUS_OK;
3181 	}
3182 
3183 	return NT_STATUS_ACCESS_DENIED;
3184 }
3185 
3186 /*******************************************************************
3187  * unlink a file with all relevant access checks
3188  *******************************************************************/
3189 
do_unlink(connection_struct * conn,struct smb_request * req,struct smb_filename * smb_fname,uint32_t dirtype)3190 static NTSTATUS do_unlink(connection_struct *conn,
3191 			struct smb_request *req,
3192 			struct smb_filename *smb_fname,
3193 			uint32_t dirtype)
3194 {
3195 	uint32_t fattr;
3196 	files_struct *fsp;
3197 	uint32_t dirtype_orig = dirtype;
3198 	NTSTATUS status;
3199 	int ret;
3200 	bool posix_paths = (req != NULL && req->posix_pathnames);
3201 
3202 	DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3203 		  smb_fname_str_dbg(smb_fname),
3204 		  dirtype));
3205 
3206 	if (!CAN_WRITE(conn)) {
3207 		return NT_STATUS_MEDIA_WRITE_PROTECTED;
3208 	}
3209 
3210 	if (posix_paths) {
3211 		ret = SMB_VFS_LSTAT(conn, smb_fname);
3212 	} else {
3213 		ret = SMB_VFS_STAT(conn, smb_fname);
3214 	}
3215 	if (ret != 0) {
3216 		return map_nt_error_from_unix(errno);
3217 	}
3218 
3219 	fattr = dos_mode(conn, smb_fname);
3220 
3221 	if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3222 		dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3223 	}
3224 
3225 	dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3226 	if (!dirtype) {
3227 		return NT_STATUS_NO_SUCH_FILE;
3228 	}
3229 
3230 	if (!dir_check_ftype(fattr, dirtype)) {
3231 		if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3232 			return NT_STATUS_FILE_IS_A_DIRECTORY;
3233 		}
3234 		return NT_STATUS_NO_SUCH_FILE;
3235 	}
3236 
3237 	if (dirtype_orig & 0x8000) {
3238 		/* These will never be set for POSIX. */
3239 		return NT_STATUS_NO_SUCH_FILE;
3240 	}
3241 
3242 #if 0
3243 	if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3244                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3245         }
3246 
3247         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3248                 return NT_STATUS_NO_SUCH_FILE;
3249         }
3250 
3251 	if (dirtype & 0xFF00) {
3252 		/* These will never be set for POSIX. */
3253 		return NT_STATUS_NO_SUCH_FILE;
3254 	}
3255 
3256 	dirtype &= 0xFF;
3257 	if (!dirtype) {
3258 		return NT_STATUS_NO_SUCH_FILE;
3259 	}
3260 
3261 	/* Can't delete a directory. */
3262 	if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3263 		return NT_STATUS_FILE_IS_A_DIRECTORY;
3264 	}
3265 #endif
3266 
3267 #if 0 /* JRATEST */
3268 	else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3269 		return NT_STATUS_OBJECT_NAME_INVALID;
3270 #endif /* JRATEST */
3271 
3272 	/* On open checks the open itself will check the share mode, so
3273 	   don't do it here as we'll get it wrong. */
3274 
3275 	status = SMB_VFS_CREATE_FILE
3276 		(conn,			/* conn */
3277 		 req,			/* req */
3278 		 0,			/* root_dir_fid */
3279 		 smb_fname,		/* fname */
3280 		 DELETE_ACCESS,		/* access_mask */
3281 		 FILE_SHARE_NONE,	/* share_access */
3282 		 FILE_OPEN,		/* create_disposition*/
3283 		 FILE_NON_DIRECTORY_FILE, /* create_options */
3284 		 			/* file_attributes */
3285 		 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
3286 				FILE_ATTRIBUTE_NORMAL,
3287 		 0,			/* oplock_request */
3288 		 NULL,			/* lease */
3289 		 0,			/* allocation_size */
3290 		 0,			/* private_flags */
3291 		 NULL,			/* sd */
3292 		 NULL,			/* ea_list */
3293 		 &fsp,			/* result */
3294 		 NULL,			/* pinfo */
3295 		 NULL, NULL);		/* create context */
3296 
3297 	if (!NT_STATUS_IS_OK(status)) {
3298 		DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3299 			   nt_errstr(status)));
3300 		return status;
3301 	}
3302 
3303 	status = can_set_delete_on_close(fsp, fattr);
3304 	if (!NT_STATUS_IS_OK(status)) {
3305 		DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3306 			"(%s)\n",
3307 			smb_fname_str_dbg(smb_fname),
3308 			nt_errstr(status)));
3309 		close_file(req, fsp, NORMAL_CLOSE);
3310 		return status;
3311 	}
3312 
3313 	/* The set is across all open files on this dev/inode pair. */
3314 	if (!set_delete_on_close(fsp, True,
3315 				conn->session_info->security_token,
3316 				conn->session_info->unix_token)) {
3317 		close_file(req, fsp, NORMAL_CLOSE);
3318 		return NT_STATUS_ACCESS_DENIED;
3319 	}
3320 
3321 	return close_file(req, fsp, NORMAL_CLOSE);
3322 }
3323 
3324 /****************************************************************************
3325  The guts of the unlink command, split out so it may be called by the NT SMB
3326  code.
3327 ****************************************************************************/
3328 
unlink_internals(connection_struct * conn,struct smb_request * req,uint32_t dirtype,struct smb_filename * smb_fname,bool has_wild)3329 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3330 			  uint32_t dirtype, struct smb_filename *smb_fname,
3331 			  bool has_wild)
3332 {
3333 	char *fname_dir = NULL;
3334 	char *fname_mask = NULL;
3335 	int count=0;
3336 	NTSTATUS status = NT_STATUS_OK;
3337 	struct smb_filename *smb_fname_dir = NULL;
3338 	TALLOC_CTX *ctx = talloc_tos();
3339 
3340 	/* Split up the directory from the filename/mask. */
3341 	status = split_fname_dir_mask(ctx, smb_fname->base_name,
3342 				      &fname_dir, &fname_mask);
3343 	if (!NT_STATUS_IS_OK(status)) {
3344 		goto out;
3345 	}
3346 
3347 	/*
3348 	 * We should only check the mangled cache
3349 	 * here if unix_convert failed. This means
3350 	 * that the path in 'mask' doesn't exist
3351 	 * on the file system and so we need to look
3352 	 * for a possible mangle. This patch from
3353 	 * Tine Smukavec <valentin.smukavec@hermes.si>.
3354 	 */
3355 
3356 	if (!VALID_STAT(smb_fname->st) &&
3357 	    mangle_is_mangled(fname_mask, conn->params)) {
3358 		char *new_mask = NULL;
3359 		mangle_lookup_name_from_8_3(ctx, fname_mask,
3360 					    &new_mask, conn->params);
3361 		if (new_mask) {
3362 			TALLOC_FREE(fname_mask);
3363 			fname_mask = new_mask;
3364 		}
3365 	}
3366 
3367 	if (!has_wild) {
3368 
3369 		/*
3370 		 * Only one file needs to be unlinked. Append the mask back
3371 		 * onto the directory.
3372 		 */
3373 		TALLOC_FREE(smb_fname->base_name);
3374 		if (ISDOT(fname_dir)) {
3375 			/* Ensure we use canonical names on open. */
3376 			smb_fname->base_name = talloc_asprintf(smb_fname,
3377 							"%s",
3378 							fname_mask);
3379 		} else {
3380 			smb_fname->base_name = talloc_asprintf(smb_fname,
3381 							"%s/%s",
3382 							fname_dir,
3383 							fname_mask);
3384 		}
3385 		if (!smb_fname->base_name) {
3386 			status = NT_STATUS_NO_MEMORY;
3387 			goto out;
3388 		}
3389 		if (dirtype == 0) {
3390 			dirtype = FILE_ATTRIBUTE_NORMAL;
3391 		}
3392 
3393 		status = check_name(conn, smb_fname);
3394 		if (!NT_STATUS_IS_OK(status)) {
3395 			goto out;
3396 		}
3397 
3398 		status = do_unlink(conn, req, smb_fname, dirtype);
3399 		if (!NT_STATUS_IS_OK(status)) {
3400 			goto out;
3401 		}
3402 
3403 		count++;
3404 	} else {
3405 		struct smb_Dir *dir_hnd = NULL;
3406 		long offset = 0;
3407 		const char *dname = NULL;
3408 		char *talloced = NULL;
3409 
3410 		if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3411 			status = NT_STATUS_OBJECT_NAME_INVALID;
3412 			goto out;
3413 		}
3414 		if (dirtype == 0) {
3415 			dirtype = FILE_ATTRIBUTE_NORMAL;
3416 		}
3417 
3418 		if (strequal(fname_mask,"????????.???")) {
3419 			TALLOC_FREE(fname_mask);
3420 			fname_mask = talloc_strdup(ctx, "*");
3421 			if (!fname_mask) {
3422 				status = NT_STATUS_NO_MEMORY;
3423 				goto out;
3424 			}
3425 		}
3426 
3427 		smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3428 					fname_dir,
3429 					NULL,
3430 					NULL,
3431 					smb_fname->flags);
3432 		if (smb_fname_dir == NULL) {
3433 			status = NT_STATUS_NO_MEMORY;
3434 			goto out;
3435 		}
3436 
3437 		status = check_name(conn, smb_fname_dir);
3438 		if (!NT_STATUS_IS_OK(status)) {
3439 			goto out;
3440 		}
3441 
3442 		dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3443 				  dirtype);
3444 		if (dir_hnd == NULL) {
3445 			status = map_nt_error_from_unix(errno);
3446 			goto out;
3447 		}
3448 
3449 		/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3450 		   the pattern matches against the long name, otherwise the short name
3451 		   We don't implement this yet XXXX
3452 		*/
3453 
3454 		status = NT_STATUS_NO_SUCH_FILE;
3455 
3456 		while ((dname = ReadDirName(dir_hnd, &offset,
3457 					    &smb_fname->st, &talloced))) {
3458 			TALLOC_CTX *frame = talloc_stackframe();
3459 
3460 			if (!is_visible_file(conn, fname_dir, dname,
3461 					     &smb_fname->st, true)) {
3462 				TALLOC_FREE(frame);
3463 				TALLOC_FREE(talloced);
3464 				continue;
3465 			}
3466 
3467 			/* Quick check for "." and ".." */
3468 			if (ISDOT(dname) || ISDOTDOT(dname)) {
3469 				TALLOC_FREE(frame);
3470 				TALLOC_FREE(talloced);
3471 				continue;
3472 			}
3473 
3474 			if(!mask_match(dname, fname_mask,
3475 				       conn->case_sensitive)) {
3476 				TALLOC_FREE(frame);
3477 				TALLOC_FREE(talloced);
3478 				continue;
3479 			}
3480 
3481 			TALLOC_FREE(smb_fname->base_name);
3482 			if (ISDOT(fname_dir)) {
3483 				/* Ensure we use canonical names on open. */
3484 				smb_fname->base_name =
3485 					talloc_asprintf(smb_fname, "%s",
3486 						dname);
3487 			} else {
3488 				smb_fname->base_name =
3489 					talloc_asprintf(smb_fname, "%s/%s",
3490 						fname_dir, dname);
3491 			}
3492 
3493 			if (!smb_fname->base_name) {
3494 				TALLOC_FREE(dir_hnd);
3495 				status = NT_STATUS_NO_MEMORY;
3496 				TALLOC_FREE(frame);
3497 				TALLOC_FREE(talloced);
3498 				goto out;
3499 			}
3500 
3501 			status = check_name(conn, smb_fname);
3502 			if (!NT_STATUS_IS_OK(status)) {
3503 				TALLOC_FREE(dir_hnd);
3504 				TALLOC_FREE(frame);
3505 				TALLOC_FREE(talloced);
3506 				goto out;
3507 			}
3508 
3509 			status = do_unlink(conn, req, smb_fname, dirtype);
3510 			if (!NT_STATUS_IS_OK(status)) {
3511 				TALLOC_FREE(dir_hnd);
3512 				TALLOC_FREE(frame);
3513 				TALLOC_FREE(talloced);
3514 				goto out;
3515 			}
3516 
3517 			count++;
3518 			DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3519 				 smb_fname->base_name));
3520 
3521 			TALLOC_FREE(frame);
3522 			TALLOC_FREE(talloced);
3523 		}
3524 		TALLOC_FREE(dir_hnd);
3525 	}
3526 
3527 	if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3528 		status = map_nt_error_from_unix(errno);
3529 	}
3530 
3531  out:
3532 	TALLOC_FREE(smb_fname_dir);
3533 	TALLOC_FREE(fname_dir);
3534 	TALLOC_FREE(fname_mask);
3535 	return status;
3536 }
3537 
3538 /****************************************************************************
3539  Reply to a unlink
3540 ****************************************************************************/
3541 
reply_unlink(struct smb_request * req)3542 void reply_unlink(struct smb_request *req)
3543 {
3544 	connection_struct *conn = req->conn;
3545 	char *name = NULL;
3546 	struct smb_filename *smb_fname = NULL;
3547 	uint32_t dirtype;
3548 	NTSTATUS status;
3549 	bool path_contains_wcard = False;
3550 	uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3551 			ucf_flags_from_smb_request(req);
3552 	TALLOC_CTX *ctx = talloc_tos();
3553 
3554 	START_PROFILE(SMBunlink);
3555 
3556 	if (req->wct < 1) {
3557 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3558 		goto out;
3559 	}
3560 
3561 	dirtype = SVAL(req->vwv+0, 0);
3562 
3563 	srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3564 				  STR_TERMINATE, &status,
3565 				  &path_contains_wcard);
3566 	if (!NT_STATUS_IS_OK(status)) {
3567 		reply_nterror(req, status);
3568 		goto out;
3569 	}
3570 
3571 	status = filename_convert(ctx, conn,
3572 				  name,
3573 				  ucf_flags,
3574 				  NULL,
3575 				  &path_contains_wcard,
3576 				  &smb_fname);
3577 	if (!NT_STATUS_IS_OK(status)) {
3578 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3579 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3580 					ERRSRV, ERRbadpath);
3581 			goto out;
3582 		}
3583 		reply_nterror(req, status);
3584 		goto out;
3585 	}
3586 
3587 	DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3588 
3589 	status = unlink_internals(conn, req, dirtype, smb_fname,
3590 				  path_contains_wcard);
3591 	if (!NT_STATUS_IS_OK(status)) {
3592 		if (open_was_deferred(req->xconn, req->mid)) {
3593 			/* We have re-scheduled this call. */
3594 			goto out;
3595 		}
3596 		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3597 			bool ok = defer_smb1_sharing_violation(req);
3598 			if (ok) {
3599 				goto out;
3600 			}
3601 		}
3602 		reply_nterror(req, status);
3603 		goto out;
3604 	}
3605 
3606 	reply_outbuf(req, 0, 0);
3607  out:
3608 	TALLOC_FREE(smb_fname);
3609 	END_PROFILE(SMBunlink);
3610 	return;
3611 }
3612 
3613 /****************************************************************************
3614  Fail for readbraw.
3615 ****************************************************************************/
3616 
fail_readraw(void)3617 static void fail_readraw(void)
3618 {
3619 	const char *errstr = talloc_asprintf(talloc_tos(),
3620 			"FAIL ! reply_readbraw: socket write fail (%s)",
3621 			strerror(errno));
3622 	if (!errstr) {
3623 		errstr = "";
3624 	}
3625 	exit_server_cleanly(errstr);
3626 }
3627 
3628 /****************************************************************************
3629  Fake (read/write) sendfile. Returns -1 on read or write fail.
3630 ****************************************************************************/
3631 
fake_sendfile(struct smbXsrv_connection * xconn,files_struct * fsp,off_t startpos,size_t nread)3632 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3633 		      off_t startpos, size_t nread)
3634 {
3635 	size_t bufsize;
3636 	size_t tosend = nread;
3637 	char *buf;
3638 
3639 	if (nread == 0) {
3640 		return 0;
3641 	}
3642 
3643 	bufsize = MIN(nread, 65536);
3644 
3645 	if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3646 		return -1;
3647 	}
3648 
3649 	while (tosend > 0) {
3650 		ssize_t ret;
3651 		size_t cur_read;
3652 
3653 		cur_read = MIN(tosend, bufsize);
3654 		ret = read_file(fsp,buf,startpos,cur_read);
3655 		if (ret == -1) {
3656 			SAFE_FREE(buf);
3657 			return -1;
3658 		}
3659 
3660 		/* If we had a short read, fill with zeros. */
3661 		if (ret < cur_read) {
3662 			memset(buf + ret, '\0', cur_read - ret);
3663 		}
3664 
3665 		ret = write_data(xconn->transport.sock, buf, cur_read);
3666 		if (ret != cur_read) {
3667 			int saved_errno = errno;
3668 			/*
3669 			 * Try and give an error message saying what
3670 			 * client failed.
3671 			 */
3672 			DEBUG(0, ("write_data failed for client %s. "
3673 				  "Error %s\n",
3674 				  smbXsrv_connection_dbg(xconn),
3675 				  strerror(saved_errno)));
3676 			SAFE_FREE(buf);
3677 			errno = saved_errno;
3678 			return -1;
3679 		}
3680 		tosend -= cur_read;
3681 		startpos += cur_read;
3682 	}
3683 
3684 	SAFE_FREE(buf);
3685 	return (ssize_t)nread;
3686 }
3687 
3688 /****************************************************************************
3689  Deal with the case of sendfile reading less bytes from the file than
3690  requested. Fill with zeros (all we can do). Returns 0 on success
3691 ****************************************************************************/
3692 
sendfile_short_send(struct smbXsrv_connection * xconn,files_struct * fsp,ssize_t nread,size_t headersize,size_t smb_maxcnt)3693 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3694 			    files_struct *fsp,
3695 			    ssize_t nread,
3696 			    size_t headersize,
3697 			    size_t smb_maxcnt)
3698 {
3699 #define SHORT_SEND_BUFSIZE 1024
3700 	if (nread < headersize) {
3701 		DEBUG(0,("sendfile_short_send: sendfile failed to send "
3702 			"header for file %s (%s). Terminating\n",
3703 			fsp_str_dbg(fsp), strerror(errno)));
3704 		return -1;
3705 	}
3706 
3707 	nread -= headersize;
3708 
3709 	if (nread < smb_maxcnt) {
3710 		char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3711 		if (!buf) {
3712 			DEBUG(0,("sendfile_short_send: malloc failed "
3713 				"for file %s (%s). Terminating\n",
3714 				fsp_str_dbg(fsp), strerror(errno)));
3715 			return -1;
3716 		}
3717 
3718 		DEBUG(0,("sendfile_short_send: filling truncated file %s "
3719 			"with zeros !\n", fsp_str_dbg(fsp)));
3720 
3721 		while (nread < smb_maxcnt) {
3722 			/*
3723 			 * We asked for the real file size and told sendfile
3724 			 * to not go beyond the end of the file. But it can
3725 			 * happen that in between our fstat call and the
3726 			 * sendfile call the file was truncated. This is very
3727 			 * bad because we have already announced the larger
3728 			 * number of bytes to the client.
3729 			 *
3730 			 * The best we can do now is to send 0-bytes, just as
3731 			 * a read from a hole in a sparse file would do.
3732 			 *
3733 			 * This should happen rarely enough that I don't care
3734 			 * about efficiency here :-)
3735 			 */
3736 			size_t to_write;
3737 			ssize_t ret;
3738 
3739 			to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3740 			ret = write_data(xconn->transport.sock, buf, to_write);
3741 			if (ret != to_write) {
3742 				int saved_errno = errno;
3743 				/*
3744 				 * Try and give an error message saying what
3745 				 * client failed.
3746 				 */
3747 				DEBUG(0, ("write_data failed for client %s. "
3748 					  "Error %s\n",
3749 					  smbXsrv_connection_dbg(xconn),
3750 					  strerror(saved_errno)));
3751 				errno = saved_errno;
3752 				return -1;
3753 			}
3754 			nread += to_write;
3755 		}
3756 		SAFE_FREE(buf);
3757 	}
3758 
3759 	return 0;
3760 }
3761 
3762 /****************************************************************************
3763  Return a readbraw error (4 bytes of zero).
3764 ****************************************************************************/
3765 
reply_readbraw_error(struct smbXsrv_connection * xconn)3766 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3767 {
3768 	char header[4];
3769 
3770 	SIVAL(header,0,0);
3771 
3772 	smbd_lock_socket(xconn);
3773 	if (write_data(xconn->transport.sock,header,4) != 4) {
3774 		int saved_errno = errno;
3775 		/*
3776 		 * Try and give an error message saying what
3777 		 * client failed.
3778 		 */
3779 		DEBUG(0, ("write_data failed for client %s. "
3780 			  "Error %s\n",
3781 			  smbXsrv_connection_dbg(xconn),
3782 			  strerror(saved_errno)));
3783 		errno = saved_errno;
3784 
3785 		fail_readraw();
3786 	}
3787 	smbd_unlock_socket(xconn);
3788 }
3789 
3790 /*******************************************************************
3791  Ensure we don't use sendfile if server smb signing is active.
3792 ********************************************************************/
3793 
lp_use_sendfile(int snum,struct smb_signing_state * signing_state)3794 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3795 {
3796 	bool sign_active = false;
3797 
3798 	/* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3799 	if (get_Protocol() < PROTOCOL_NT1) {
3800 		return false;
3801 	}
3802 	if (signing_state) {
3803 		sign_active = smb_signing_is_active(signing_state);
3804 	}
3805 	return (lp__use_sendfile(snum) &&
3806 			(get_remote_arch() != RA_WIN95) &&
3807 			!sign_active);
3808 }
3809 /****************************************************************************
3810  Use sendfile in readbraw.
3811 ****************************************************************************/
3812 
send_file_readbraw(connection_struct * conn,struct smb_request * req,files_struct * fsp,off_t startpos,size_t nread,ssize_t mincount)3813 static void send_file_readbraw(connection_struct *conn,
3814 			       struct smb_request *req,
3815 			       files_struct *fsp,
3816 			       off_t startpos,
3817 			       size_t nread,
3818 			       ssize_t mincount)
3819 {
3820 	struct smbXsrv_connection *xconn = req->xconn;
3821 	char *outbuf = NULL;
3822 	ssize_t ret=0;
3823 
3824 	/*
3825 	 * We can only use sendfile on a non-chained packet
3826 	 * but we can use on a non-oplocked file. tridge proved this
3827 	 * on a train in Germany :-). JRA.
3828 	 * reply_readbraw has already checked the length.
3829 	 */
3830 
3831 	if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3832 	    lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3833 		ssize_t sendfile_read = -1;
3834 		char header[4];
3835 		DATA_BLOB header_blob;
3836 
3837 		_smb_setlen(header,nread);
3838 		header_blob = data_blob_const(header, 4);
3839 
3840 		sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3841 						 &header_blob, startpos,
3842 						 nread);
3843 		if (sendfile_read == -1) {
3844 			/* Returning ENOSYS means no data at all was sent.
3845 			 * Do this as a normal read. */
3846 			if (errno == ENOSYS) {
3847 				goto normal_readbraw;
3848 			}
3849 
3850 			/*
3851 			 * Special hack for broken Linux with no working sendfile. If we
3852 			 * return EINTR we sent the header but not the rest of the data.
3853 			 * Fake this up by doing read/write calls.
3854 			 */
3855 			if (errno == EINTR) {
3856 				/* Ensure we don't do this again. */
3857 				set_use_sendfile(SNUM(conn), False);
3858 				DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3859 
3860 				if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3861 					DEBUG(0,("send_file_readbraw: "
3862 						 "fake_sendfile failed for "
3863 						 "file %s (%s).\n",
3864 						 fsp_str_dbg(fsp),
3865 						 strerror(errno)));
3866 					exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3867 				}
3868 				return;
3869 			}
3870 
3871 			DEBUG(0,("send_file_readbraw: sendfile failed for "
3872 				 "file %s (%s). Terminating\n",
3873 				 fsp_str_dbg(fsp), strerror(errno)));
3874 			exit_server_cleanly("send_file_readbraw sendfile failed");
3875 		} else if (sendfile_read == 0) {
3876 			/*
3877 			 * Some sendfile implementations return 0 to indicate
3878 			 * that there was a short read, but nothing was
3879 			 * actually written to the socket.  In this case,
3880 			 * fallback to the normal read path so the header gets
3881 			 * the correct byte count.
3882 			 */
3883 			DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3884 				  "bytes falling back to the normal read: "
3885 				  "%s\n", fsp_str_dbg(fsp)));
3886 			goto normal_readbraw;
3887 		}
3888 
3889 		/* Deal with possible short send. */
3890 		if (sendfile_read != 4+nread) {
3891 			ret = sendfile_short_send(xconn, fsp,
3892 						  sendfile_read, 4, nread);
3893 			if (ret == -1) {
3894 				fail_readraw();
3895 			}
3896 		}
3897 		return;
3898 	}
3899 
3900 normal_readbraw:
3901 
3902 	outbuf = talloc_array(NULL, char, nread+4);
3903 	if (!outbuf) {
3904 		DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3905 			(unsigned)(nread+4)));
3906 		reply_readbraw_error(xconn);
3907 		return;
3908 	}
3909 
3910 	if (nread > 0) {
3911 		ret = read_file(fsp,outbuf+4,startpos,nread);
3912 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3913 		if (ret < mincount)
3914 			ret = 0;
3915 #else
3916 		if (ret < nread)
3917 			ret = 0;
3918 #endif
3919 	}
3920 
3921 	_smb_setlen(outbuf,ret);
3922 	if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3923 		int saved_errno = errno;
3924 		/*
3925 		 * Try and give an error message saying what
3926 		 * client failed.
3927 		 */
3928 		DEBUG(0, ("write_data failed for client %s. Error %s\n",
3929 			  smbXsrv_connection_dbg(xconn),
3930 			  strerror(saved_errno)));
3931 		errno = saved_errno;
3932 
3933 		fail_readraw();
3934 	}
3935 
3936 	TALLOC_FREE(outbuf);
3937 }
3938 
3939 /****************************************************************************
3940  Reply to a readbraw (core+ protocol).
3941 ****************************************************************************/
3942 
reply_readbraw(struct smb_request * req)3943 void reply_readbraw(struct smb_request *req)
3944 {
3945 	connection_struct *conn = req->conn;
3946 	struct smbXsrv_connection *xconn = req->xconn;
3947 	ssize_t maxcount,mincount;
3948 	size_t nread = 0;
3949 	off_t startpos;
3950 	files_struct *fsp;
3951 	struct lock_struct lock;
3952 	off_t size = 0;
3953 	NTSTATUS status;
3954 
3955 	START_PROFILE(SMBreadbraw);
3956 
3957 	if (srv_is_signing_active(xconn) || req->encrypted) {
3958 		exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3959 			"raw reads/writes are disallowed.");
3960 	}
3961 
3962 	if (req->wct < 8) {
3963 		reply_readbraw_error(xconn);
3964 		END_PROFILE(SMBreadbraw);
3965 		return;
3966 	}
3967 
3968 	if (xconn->smb1.echo_handler.trusted_fde) {
3969 		DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3970 			 "'async smb echo handler = yes'\n"));
3971 		reply_readbraw_error(xconn);
3972 		END_PROFILE(SMBreadbraw);
3973 		return;
3974 	}
3975 
3976 	/*
3977 	 * Special check if an oplock break has been issued
3978 	 * and the readraw request croses on the wire, we must
3979 	 * return a zero length response here.
3980 	 */
3981 
3982 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3983 
3984 	/*
3985 	 * We have to do a check_fsp by hand here, as
3986 	 * we must always return 4 zero bytes on error,
3987 	 * not a NTSTATUS.
3988 	 */
3989 
3990 	if (!fsp || !conn || conn != fsp->conn ||
3991 			req->vuid != fsp->vuid ||
3992 			fsp->is_directory || fsp->fh->fd == -1) {
3993 		/*
3994 		 * fsp could be NULL here so use the value from the packet. JRA.
3995 		 */
3996 		DEBUG(3,("reply_readbraw: fnum %d not valid "
3997 			"- cache prime?\n",
3998 			(int)SVAL(req->vwv+0, 0)));
3999 		reply_readbraw_error(xconn);
4000 		END_PROFILE(SMBreadbraw);
4001 		return;
4002 	}
4003 
4004 	/* Do a "by hand" version of CHECK_READ. */
4005 	if (!(fsp->can_read ||
4006 			((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
4007 				(fsp->access_mask & FILE_EXECUTE)))) {
4008 		DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
4009 				(int)SVAL(req->vwv+0, 0)));
4010 		reply_readbraw_error(xconn);
4011 		END_PROFILE(SMBreadbraw);
4012 		return;
4013 	}
4014 
4015 	startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
4016 	if(req->wct == 10) {
4017 		/*
4018 		 * This is a large offset (64 bit) read.
4019 		 */
4020 
4021 		startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
4022 
4023 		if(startpos < 0) {
4024 			DEBUG(0,("reply_readbraw: negative 64 bit "
4025 				"readraw offset (%.0f) !\n",
4026 				(double)startpos ));
4027 			reply_readbraw_error(xconn);
4028 			END_PROFILE(SMBreadbraw);
4029 			return;
4030 		}
4031 	}
4032 
4033 	maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4034 	mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4035 
4036 	/* ensure we don't overrun the packet size */
4037 	maxcount = MIN(65535,maxcount);
4038 
4039 	init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4040 	    (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4041 	    &lock);
4042 
4043 	if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4044 		reply_readbraw_error(xconn);
4045 		END_PROFILE(SMBreadbraw);
4046 		return;
4047 	}
4048 
4049 	status = vfs_stat_fsp(fsp);
4050 	if (NT_STATUS_IS_OK(status)) {
4051 		size = fsp->fsp_name->st.st_ex_size;
4052 	}
4053 
4054 	if (startpos >= size) {
4055 		nread = 0;
4056 	} else {
4057 		nread = MIN(maxcount,(size - startpos));
4058 	}
4059 
4060 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4061 	if (nread < mincount)
4062 		nread = 0;
4063 #endif
4064 
4065 	DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4066 		"min=%lu nread=%lu\n",
4067 		fsp_fnum_dbg(fsp), (double)startpos,
4068 		(unsigned long)maxcount,
4069 		(unsigned long)mincount,
4070 		(unsigned long)nread ) );
4071 
4072 	send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4073 
4074 	DEBUG(5,("reply_readbraw finished\n"));
4075 
4076 	END_PROFILE(SMBreadbraw);
4077 	return;
4078 }
4079 
4080 #undef DBGC_CLASS
4081 #define DBGC_CLASS DBGC_LOCKING
4082 
4083 /****************************************************************************
4084  Reply to a lockread (core+ protocol).
4085 ****************************************************************************/
4086 
4087 static void reply_lockread_locked(struct tevent_req *subreq);
4088 
reply_lockread(struct smb_request * req)4089 void reply_lockread(struct smb_request *req)
4090 {
4091 	struct tevent_req *subreq = NULL;
4092 	connection_struct *conn = req->conn;
4093 	files_struct *fsp;
4094 	struct smbd_lock_element *lck = NULL;
4095 
4096 	START_PROFILE(SMBlockread);
4097 
4098 	if (req->wct < 5) {
4099 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4100 		END_PROFILE(SMBlockread);
4101 		return;
4102 	}
4103 
4104 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4105 
4106 	if (!check_fsp(conn, req, fsp)) {
4107 		END_PROFILE(SMBlockread);
4108 		return;
4109 	}
4110 
4111 	if (!CHECK_READ(fsp,req)) {
4112 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4113 		END_PROFILE(SMBlockread);
4114 		return;
4115 	}
4116 
4117 	lck = talloc(req, struct smbd_lock_element);
4118 	if (lck == NULL) {
4119 		reply_nterror(req, NT_STATUS_NO_MEMORY);
4120 		END_PROFILE(SMBlockread);
4121 		return;
4122 	}
4123 
4124 	/*
4125 	 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4126 	 * protocol request that predates the read/write lock concept.
4127 	 * Thus instead of asking for a read lock here we need to ask
4128 	 * for a write lock. JRA.
4129 	 * Note that the requested lock size is unaffected by max_send.
4130 	 */
4131 
4132 	*lck = (struct smbd_lock_element) {
4133 		.req_guid = smbd_request_guid(req, 0),
4134 		.smblctx = req->smbpid,
4135 		.brltype = WRITE_LOCK,
4136 		.count = SVAL(req->vwv+1, 0),
4137 		.offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4138 	};
4139 
4140 	subreq = smbd_smb1_do_locks_send(
4141 		fsp,
4142 		req->sconn->ev_ctx,
4143 		&req,
4144 		fsp,
4145 		0,
4146 		false,		/* large_offset */
4147 		WINDOWS_LOCK,
4148 		1,
4149 		lck);
4150 	if (subreq == NULL) {
4151 		reply_nterror(req, NT_STATUS_NO_MEMORY);
4152 		END_PROFILE(SMBlockread);
4153 		return;
4154 	}
4155 	tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4156 	END_PROFILE(SMBlockread);
4157 }
4158 
reply_lockread_locked(struct tevent_req * subreq)4159 static void reply_lockread_locked(struct tevent_req *subreq)
4160 {
4161 	struct smb_request *req = NULL;
4162 	ssize_t nread = -1;
4163 	char *data = NULL;
4164 	NTSTATUS status;
4165 	bool ok;
4166 	off_t startpos;
4167 	size_t numtoread, maxtoread;
4168 	struct files_struct *fsp = NULL;
4169 	char *p = NULL;
4170 
4171 	START_PROFILE(SMBlockread);
4172 
4173 	ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4174 	SMB_ASSERT(ok);
4175 
4176 	status = smbd_smb1_do_locks_recv(subreq);
4177 	TALLOC_FREE(subreq);
4178 
4179 	if (!NT_STATUS_IS_OK(status)) {
4180 		reply_nterror(req, status);
4181 		goto send;
4182 	}
4183 
4184 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4185 	if (fsp == NULL) {
4186 		reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4187 		goto send;
4188 	}
4189 
4190 	numtoread = SVAL(req->vwv+1, 0);
4191 	startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4192 
4193 	/*
4194 	 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4195 	 */
4196 	maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4197 
4198 	if (numtoread > maxtoread) {
4199 		DBG_WARNING("requested read size (%zu) is greater than "
4200 			    "maximum allowed (%zu/%d). "
4201 			    "Returning short read of maximum allowed for "
4202 			    "compatibility with Windows 2000.\n",
4203 			    numtoread,
4204 			    maxtoread,
4205 			    req->xconn->smb1.sessions.max_send);
4206 		numtoread = maxtoread;
4207 	}
4208 
4209 	reply_outbuf(req, 5, numtoread + 3);
4210 
4211 	data = smb_buf(req->outbuf) + 3;
4212 
4213 	nread = read_file(fsp,data,startpos,numtoread);
4214 
4215 	if (nread < 0) {
4216 		reply_nterror(req, map_nt_error_from_unix(errno));
4217 		goto send;
4218 	}
4219 
4220 	srv_set_message((char *)req->outbuf, 5, nread+3, False);
4221 
4222 	SSVAL(req->outbuf,smb_vwv0,nread);
4223 	SSVAL(req->outbuf,smb_vwv5,nread+3);
4224 	p = smb_buf(req->outbuf);
4225 	SCVAL(p,0,0); /* pad byte. */
4226 	SSVAL(p,1,nread);
4227 
4228 	DEBUG(3,("lockread %s num=%d nread=%d\n",
4229 		 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4230 
4231 send:
4232 	ok = srv_send_smb(req->xconn,
4233 			  (char *)req->outbuf,
4234 			  true,
4235 			  req->seqnum+1,
4236 			  IS_CONN_ENCRYPTED(req->conn),
4237 			  NULL);
4238 	if (!ok) {
4239 		exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4240 	}
4241 	TALLOC_FREE(req);
4242 	END_PROFILE(SMBlockread);
4243 	return;
4244 }
4245 
4246 #undef DBGC_CLASS
4247 #define DBGC_CLASS DBGC_ALL
4248 
4249 /****************************************************************************
4250  Reply to a read.
4251 ****************************************************************************/
4252 
reply_read(struct smb_request * req)4253 void reply_read(struct smb_request *req)
4254 {
4255 	connection_struct *conn = req->conn;
4256 	size_t numtoread;
4257 	size_t maxtoread;
4258 	ssize_t nread = 0;
4259 	char *data;
4260 	off_t startpos;
4261 	files_struct *fsp;
4262 	struct lock_struct lock;
4263 	struct smbXsrv_connection *xconn = req->xconn;
4264 
4265 	START_PROFILE(SMBread);
4266 
4267 	if (req->wct < 3) {
4268 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4269 		END_PROFILE(SMBread);
4270 		return;
4271 	}
4272 
4273 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4274 
4275 	if (!check_fsp(conn, req, fsp)) {
4276 		END_PROFILE(SMBread);
4277 		return;
4278 	}
4279 
4280 	if (!CHECK_READ(fsp,req)) {
4281 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4282 		END_PROFILE(SMBread);
4283 		return;
4284 	}
4285 
4286 	numtoread = SVAL(req->vwv+1, 0);
4287 	startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4288 
4289 	/*
4290 	 * The requested read size cannot be greater than max_send. JRA.
4291 	 */
4292 	maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4293 
4294 	if (numtoread > maxtoread) {
4295 		DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4296 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4297 			(unsigned int)numtoread, (unsigned int)maxtoread,
4298 			(unsigned int)xconn->smb1.sessions.max_send));
4299 		numtoread = maxtoread;
4300 	}
4301 
4302 	reply_outbuf(req, 5, numtoread+3);
4303 
4304 	data = smb_buf(req->outbuf) + 3;
4305 
4306 	init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4307 	    (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4308 	    &lock);
4309 
4310 	if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4311 		reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4312 		END_PROFILE(SMBread);
4313 		return;
4314 	}
4315 
4316 	if (numtoread > 0)
4317 		nread = read_file(fsp,data,startpos,numtoread);
4318 
4319 	if (nread < 0) {
4320 		reply_nterror(req, map_nt_error_from_unix(errno));
4321 		goto out;
4322 	}
4323 
4324 	srv_set_message((char *)req->outbuf, 5, nread+3, False);
4325 
4326 	SSVAL(req->outbuf,smb_vwv0,nread);
4327 	SSVAL(req->outbuf,smb_vwv5,nread+3);
4328 	SCVAL(smb_buf(req->outbuf),0,1);
4329 	SSVAL(smb_buf(req->outbuf),1,nread);
4330 
4331 	DEBUG(3, ("read %s num=%d nread=%d\n",
4332 		  fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4333 
4334 out:
4335 	END_PROFILE(SMBread);
4336 	return;
4337 }
4338 
4339 /****************************************************************************
4340  Setup readX header.
4341 ****************************************************************************/
4342 
setup_readX_header(char * outbuf,size_t smb_maxcnt)4343 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4344 {
4345 	size_t outsize;
4346 
4347 	outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4348 				  False);
4349 
4350 	memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4351 
4352 	SCVAL(outbuf,smb_vwv0,0xFF);
4353 	SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4354 	SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4355 	SSVAL(outbuf,smb_vwv6,
4356 	      (smb_wct - 4)	/* offset from smb header to wct */
4357 	      + 1 		/* the wct field */
4358 	      + 12 * sizeof(uint16_t) /* vwv */
4359 	      + 2		/* the buflen field */
4360 	      + 1);		/* padding byte */
4361 	SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4362 	SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4363 	/* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4364 	_smb_setlen_large(outbuf,
4365 			  smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4366 	return outsize;
4367 }
4368 
4369 /****************************************************************************
4370  Reply to a read and X - possibly using sendfile.
4371 ****************************************************************************/
4372 
send_file_readX(connection_struct * conn,struct smb_request * req,files_struct * fsp,off_t startpos,size_t smb_maxcnt)4373 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4374 			    files_struct *fsp, off_t startpos,
4375 			    size_t smb_maxcnt)
4376 {
4377 	struct smbXsrv_connection *xconn = req->xconn;
4378 	ssize_t nread = -1;
4379 	struct lock_struct lock;
4380 	int saved_errno = 0;
4381 	NTSTATUS status;
4382 
4383 	init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4384 	    (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4385 	    &lock);
4386 
4387 	if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4388 		reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4389 		return;
4390 	}
4391 
4392 	/*
4393 	 * We can only use sendfile on a non-chained packet
4394 	 * but we can use on a non-oplocked file. tridge proved this
4395 	 * on a train in Germany :-). JRA.
4396 	 */
4397 
4398 	if (!req_is_in_chain(req) &&
4399 	    !req->encrypted &&
4400 	    (fsp->base_fsp == NULL) &&
4401 	    lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4402 		uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4403 		DATA_BLOB header;
4404 
4405 		status = vfs_stat_fsp(fsp);
4406 		if (!NT_STATUS_IS_OK(status)) {
4407 			reply_nterror(req, status);
4408 			goto out;
4409 		}
4410 
4411 		if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4412 		    (startpos > fsp->fsp_name->st.st_ex_size) ||
4413 		    (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4414 			/*
4415 			 * We already know that we would do a short read, so don't
4416 			 * try the sendfile() path.
4417 			 */
4418 			goto nosendfile_read;
4419 		}
4420 
4421 		/*
4422 		 * Set up the packet header before send. We
4423 		 * assume here the sendfile will work (get the
4424 		 * correct amount of data).
4425 		 */
4426 
4427 		header = data_blob_const(headerbuf, sizeof(headerbuf));
4428 
4429 		construct_reply_common_req(req, (char *)headerbuf);
4430 		setup_readX_header((char *)headerbuf, smb_maxcnt);
4431 
4432 		nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4433 					 startpos, smb_maxcnt);
4434 		if (nread == -1) {
4435 			saved_errno = errno;
4436 
4437 			/* Returning ENOSYS means no data at all was sent.
4438 			   Do this as a normal read. */
4439 			if (errno == ENOSYS) {
4440 				goto normal_read;
4441 			}
4442 
4443 			/*
4444 			 * Special hack for broken Linux with no working sendfile. If we
4445 			 * return EINTR we sent the header but not the rest of the data.
4446 			 * Fake this up by doing read/write calls.
4447 			 */
4448 
4449 			if (errno == EINTR) {
4450 				/* Ensure we don't do this again. */
4451 				set_use_sendfile(SNUM(conn), False);
4452 				DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4453 				nread = fake_sendfile(xconn, fsp, startpos,
4454 						      smb_maxcnt);
4455 				if (nread == -1) {
4456 					saved_errno = errno;
4457 					DEBUG(0,("send_file_readX: "
4458 						 "fake_sendfile failed for "
4459 						 "file %s (%s) for client %s. "
4460 						 "Terminating\n",
4461 						 fsp_str_dbg(fsp),
4462 						 smbXsrv_connection_dbg(xconn),
4463 						 strerror(saved_errno)));
4464 					errno = saved_errno;
4465 					exit_server_cleanly("send_file_readX: fake_sendfile failed");
4466 				}
4467 				DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4468 					  fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4469 				/* No outbuf here means successful sendfile. */
4470 				goto out;
4471 			}
4472 
4473 			DEBUG(0,("send_file_readX: sendfile failed for file "
4474 				 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4475 				 strerror(errno)));
4476 			exit_server_cleanly("send_file_readX sendfile failed");
4477 		} else if (nread == 0) {
4478 			/*
4479 			 * Some sendfile implementations return 0 to indicate
4480 			 * that there was a short read, but nothing was
4481 			 * actually written to the socket.  In this case,
4482 			 * fallback to the normal read path so the header gets
4483 			 * the correct byte count.
4484 			 */
4485 			DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4486 				  "falling back to the normal read: %s\n",
4487 				  fsp_str_dbg(fsp)));
4488 			goto normal_read;
4489 		}
4490 
4491 		DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4492 			  fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4493 
4494 		/* Deal with possible short send. */
4495 		if (nread != smb_maxcnt + sizeof(headerbuf)) {
4496 			ssize_t ret;
4497 
4498 			ret = sendfile_short_send(xconn, fsp, nread,
4499 						  sizeof(headerbuf), smb_maxcnt);
4500 			if (ret == -1) {
4501 				const char *r;
4502 				r = "send_file_readX: sendfile_short_send failed";
4503 				DEBUG(0,("%s for file %s (%s).\n",
4504 					 r, fsp_str_dbg(fsp), strerror(errno)));
4505 				exit_server_cleanly(r);
4506 			}
4507 		}
4508 		/* No outbuf here means successful sendfile. */
4509 		SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4510 		SMB_PERFCOUNT_END(&req->pcd);
4511 		goto out;
4512 	}
4513 
4514 normal_read:
4515 
4516 	if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4517 		uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4518 		ssize_t ret;
4519 
4520 		if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4521 		    (startpos > fsp->fsp_name->st.st_ex_size) ||
4522 		    (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4523 			/*
4524 			 * We already know that we would do a short
4525 			 * read, so don't try the sendfile() path.
4526 			 */
4527 			goto nosendfile_read;
4528 		}
4529 
4530 		construct_reply_common_req(req, (char *)headerbuf);
4531 		setup_readX_header((char *)headerbuf, smb_maxcnt);
4532 
4533 		/* Send out the header. */
4534 		ret = write_data(xconn->transport.sock, (char *)headerbuf,
4535 				 sizeof(headerbuf));
4536 		if (ret != sizeof(headerbuf)) {
4537 			saved_errno = errno;
4538 			/*
4539 			 * Try and give an error message saying what
4540 			 * client failed.
4541 			 */
4542 			DEBUG(0,("send_file_readX: write_data failed for file "
4543 				 "%s (%s) for client %s. Terminating\n",
4544 				 fsp_str_dbg(fsp),
4545 				 smbXsrv_connection_dbg(xconn),
4546 				 strerror(saved_errno)));
4547 			errno = saved_errno;
4548 			exit_server_cleanly("send_file_readX sendfile failed");
4549 		}
4550 		nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4551 		if (nread == -1) {
4552 			saved_errno = errno;
4553 			DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4554 				 "%s (%s) for client %s. Terminating\n",
4555 				 fsp_str_dbg(fsp),
4556 				 smbXsrv_connection_dbg(xconn),
4557 				 strerror(saved_errno)));
4558 			errno = saved_errno;
4559 			exit_server_cleanly("send_file_readX: fake_sendfile failed");
4560 		}
4561 		goto out;
4562 	}
4563 
4564 nosendfile_read:
4565 
4566 	reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4567 	SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4568 	SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
4569 
4570 	nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4571 			  startpos, smb_maxcnt);
4572 	saved_errno = errno;
4573 
4574 	if (nread < 0) {
4575 		reply_nterror(req, map_nt_error_from_unix(saved_errno));
4576 		return;
4577 	}
4578 
4579 	setup_readX_header((char *)req->outbuf, nread);
4580 
4581 	DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4582 		  fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4583 	return;
4584 
4585 out:
4586 	TALLOC_FREE(req->outbuf);
4587 	return;
4588 }
4589 
4590 /****************************************************************************
4591  Work out how much space we have for a read return.
4592 ****************************************************************************/
4593 
calc_max_read_pdu(const struct smb_request * req)4594 static size_t calc_max_read_pdu(const struct smb_request *req)
4595 {
4596 	struct smbXsrv_connection *xconn = req->xconn;
4597 
4598 	if (xconn->protocol < PROTOCOL_NT1) {
4599 		return xconn->smb1.sessions.max_send;
4600 	}
4601 
4602 	if (!lp_large_readwrite()) {
4603 		return xconn->smb1.sessions.max_send;
4604 	}
4605 
4606 	if (req_is_in_chain(req)) {
4607 		return xconn->smb1.sessions.max_send;
4608 	}
4609 
4610 	if (req->encrypted) {
4611 		/*
4612 		 * Don't take encrypted traffic up to the
4613 		 * limit. There are padding considerations
4614 		 * that make that tricky.
4615 		 */
4616 		return xconn->smb1.sessions.max_send;
4617 	}
4618 
4619 	if (srv_is_signing_active(xconn)) {
4620 		return 0x1FFFF;
4621 	}
4622 
4623 	if (!lp_unix_extensions()) {
4624 		return 0x1FFFF;
4625 	}
4626 
4627 	/*
4628 	 * We can do ultra-large POSIX reads.
4629 	 */
4630 	return 0xFFFFFF;
4631 }
4632 
4633 /****************************************************************************
4634  Calculate how big a read can be. Copes with all clients. It's always
4635  safe to return a short read - Windows does this.
4636 ****************************************************************************/
4637 
calc_read_size(const struct smb_request * req,size_t upper_size,size_t lower_size)4638 static size_t calc_read_size(const struct smb_request *req,
4639 			     size_t upper_size,
4640 			     size_t lower_size)
4641 {
4642 	struct smbXsrv_connection *xconn = req->xconn;
4643 	size_t max_pdu = calc_max_read_pdu(req);
4644 	size_t total_size = 0;
4645 	size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4646 	size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4647 
4648 	/*
4649 	 * Windows explicitly ignores upper size of 0xFFFF.
4650 	 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4651 	 * We must do the same as these will never fit even in
4652 	 * an extended size NetBIOS packet.
4653 	 */
4654 	if (upper_size == 0xFFFF) {
4655 		upper_size = 0;
4656 	}
4657 
4658 	if (xconn->protocol < PROTOCOL_NT1) {
4659 		upper_size = 0;
4660 	}
4661 
4662 	total_size = ((upper_size<<16) | lower_size);
4663 
4664 	/*
4665 	 * LARGE_READX test shows it's always safe to return
4666 	 * a short read. Windows does so.
4667 	 */
4668 	return MIN(total_size, max_len);
4669 }
4670 
4671 /****************************************************************************
4672  Reply to a read and X.
4673 ****************************************************************************/
4674 
reply_read_and_X(struct smb_request * req)4675 void reply_read_and_X(struct smb_request *req)
4676 {
4677 	connection_struct *conn = req->conn;
4678 	files_struct *fsp;
4679 	off_t startpos;
4680 	size_t smb_maxcnt;
4681 	size_t upper_size;
4682 	bool big_readX = False;
4683 #if 0
4684 	size_t smb_mincnt = SVAL(req->vwv+6, 0);
4685 #endif
4686 
4687 	START_PROFILE(SMBreadX);
4688 
4689 	if ((req->wct != 10) && (req->wct != 12)) {
4690 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4691 		return;
4692 	}
4693 
4694 	fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4695 	startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4696 	smb_maxcnt = SVAL(req->vwv+5, 0);
4697 
4698 	/* If it's an IPC, pass off the pipe handler. */
4699 	if (IS_IPC(conn)) {
4700 		reply_pipe_read_and_X(req);
4701 		END_PROFILE(SMBreadX);
4702 		return;
4703 	}
4704 
4705 	if (!check_fsp(conn, req, fsp)) {
4706 		END_PROFILE(SMBreadX);
4707 		return;
4708 	}
4709 
4710 	if (!CHECK_READ(fsp,req)) {
4711 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4712 		END_PROFILE(SMBreadX);
4713 		return;
4714 	}
4715 
4716 	upper_size = SVAL(req->vwv+7, 0);
4717 	smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4718 	if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4719 		/*
4720 		 * This is a heuristic to avoid keeping large
4721 		 * outgoing buffers around over long-lived aio
4722 		 * requests.
4723 		 */
4724 		big_readX = True;
4725 	}
4726 
4727 	if (req->wct == 12) {
4728 		/*
4729 		 * This is a large offset (64 bit) read.
4730 		 */
4731 		startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4732 
4733 	}
4734 
4735 	if (!big_readX) {
4736 		NTSTATUS status = schedule_aio_read_and_X(conn,
4737 					req,
4738 					fsp,
4739 					startpos,
4740 					smb_maxcnt);
4741 		if (NT_STATUS_IS_OK(status)) {
4742 			/* Read scheduled - we're done. */
4743 			goto out;
4744 		}
4745 		if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4746 			/* Real error - report to client. */
4747 			END_PROFILE(SMBreadX);
4748 			reply_nterror(req, status);
4749 			return;
4750 		}
4751 		/* NT_STATUS_RETRY - fall back to sync read. */
4752 	}
4753 
4754 	smbd_lock_socket(req->xconn);
4755 	send_file_readX(conn, req, fsp,	startpos, smb_maxcnt);
4756 	smbd_unlock_socket(req->xconn);
4757 
4758  out:
4759 	END_PROFILE(SMBreadX);
4760 	return;
4761 }
4762 
4763 /****************************************************************************
4764  Error replies to writebraw must have smb_wct == 1. Fix this up.
4765 ****************************************************************************/
4766 
error_to_writebrawerr(struct smb_request * req)4767 void error_to_writebrawerr(struct smb_request *req)
4768 {
4769 	uint8_t *old_outbuf = req->outbuf;
4770 
4771 	reply_outbuf(req, 1, 0);
4772 
4773 	memcpy(req->outbuf, old_outbuf, smb_size);
4774 	TALLOC_FREE(old_outbuf);
4775 }
4776 
4777 /****************************************************************************
4778  Read 4 bytes of a smb packet and return the smb length of the packet.
4779  Store the result in the buffer. This version of the function will
4780  never return a session keepalive (length of zero).
4781  Timeout is in milliseconds.
4782 ****************************************************************************/
4783 
read_smb_length(int fd,char * inbuf,unsigned int timeout,size_t * len)4784 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4785 				size_t *len)
4786 {
4787 	uint8_t msgtype = NBSSkeepalive;
4788 
4789 	while (msgtype == NBSSkeepalive) {
4790 		NTSTATUS status;
4791 
4792 		status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4793 							  len);
4794 		if (!NT_STATUS_IS_OK(status)) {
4795 			char addr[INET6_ADDRSTRLEN];
4796 			/* Try and give an error message
4797 			 * saying what client failed. */
4798 			DEBUG(0, ("read_smb_length_return_keepalive failed for "
4799 				  "client %s read error = %s.\n",
4800 				  get_peer_addr(fd,addr,sizeof(addr)),
4801 				  nt_errstr(status)));
4802 			return status;
4803 		}
4804 
4805 		msgtype = CVAL(inbuf, 0);
4806 	}
4807 
4808 	DEBUG(10,("read_smb_length: got smb length of %lu\n",
4809 		  (unsigned long)len));
4810 
4811 	return NT_STATUS_OK;
4812 }
4813 
4814 /****************************************************************************
4815  Reply to a writebraw (core+ or LANMAN1.0 protocol).
4816 ****************************************************************************/
4817 
reply_writebraw(struct smb_request * req)4818 void reply_writebraw(struct smb_request *req)
4819 {
4820 	connection_struct *conn = req->conn;
4821 	struct smbXsrv_connection *xconn = req->xconn;
4822 	char *buf = NULL;
4823 	ssize_t nwritten=0;
4824 	ssize_t total_written=0;
4825 	size_t numtowrite=0;
4826 	size_t tcount;
4827 	off_t startpos;
4828 	const char *data=NULL;
4829 	bool write_through;
4830 	files_struct *fsp;
4831 	struct lock_struct lock;
4832 	NTSTATUS status;
4833 
4834 	START_PROFILE(SMBwritebraw);
4835 
4836 	/*
4837 	 * If we ever reply with an error, it must have the SMB command
4838 	 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4839 	 * we're finished.
4840 	 */
4841 	SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4842 
4843 	if (srv_is_signing_active(xconn)) {
4844 		END_PROFILE(SMBwritebraw);
4845 		exit_server_cleanly("reply_writebraw: SMB signing is active - "
4846 				"raw reads/writes are disallowed.");
4847 	}
4848 
4849 	if (req->wct < 12) {
4850 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4851 		error_to_writebrawerr(req);
4852 		END_PROFILE(SMBwritebraw);
4853 		return;
4854 	}
4855 
4856 	if (xconn->smb1.echo_handler.trusted_fde) {
4857 		DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4858 			 "'async smb echo handler = yes'\n"));
4859 		reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4860 		error_to_writebrawerr(req);
4861 		END_PROFILE(SMBwritebraw);
4862 		return;
4863 	}
4864 
4865 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4866 	if (!check_fsp(conn, req, fsp)) {
4867 		error_to_writebrawerr(req);
4868 		END_PROFILE(SMBwritebraw);
4869 		return;
4870 	}
4871 
4872 	if (!CHECK_WRITE(fsp)) {
4873 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4874 		error_to_writebrawerr(req);
4875 		END_PROFILE(SMBwritebraw);
4876 		return;
4877 	}
4878 
4879 	tcount = IVAL(req->vwv+1, 0);
4880 	startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4881 	write_through = BITSETW(req->vwv+7,0);
4882 
4883 	/* We have to deal with slightly different formats depending
4884 		on whether we are using the core+ or lanman1.0 protocol */
4885 
4886 	if(get_Protocol() <= PROTOCOL_COREPLUS) {
4887 		numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4888 		data = smb_buf_const(req->inbuf);
4889 	} else {
4890 		numtowrite = SVAL(req->vwv+10, 0);
4891 		data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4892 	}
4893 
4894 	/* Ensure we don't write bytes past the end of this packet. */
4895 	/*
4896 	 * This already protects us against CVE-2017-12163.
4897 	 */
4898 	if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4899 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4900 		error_to_writebrawerr(req);
4901 		END_PROFILE(SMBwritebraw);
4902 		return;
4903 	}
4904 
4905 	if (!fsp->print_file) {
4906 		init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4907 		    (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4908 		    &lock);
4909 
4910 		if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4911 			reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4912 			error_to_writebrawerr(req);
4913 			END_PROFILE(SMBwritebraw);
4914 			return;
4915 		}
4916 	}
4917 
4918 	if (numtowrite>0) {
4919 		nwritten = write_file(req,fsp,data,startpos,numtowrite);
4920 	}
4921 
4922 	DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4923 			"wrote=%d sync=%d\n",
4924 		fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4925 		(int)nwritten, (int)write_through));
4926 
4927 	if (nwritten < (ssize_t)numtowrite)  {
4928 		reply_nterror(req, NT_STATUS_DISK_FULL);
4929 		error_to_writebrawerr(req);
4930 		goto out;
4931 	}
4932 
4933 	total_written = nwritten;
4934 
4935 	/* Allocate a buffer of 64k + length. */
4936 	buf = talloc_array(NULL, char, 65540);
4937 	if (!buf) {
4938 		reply_nterror(req, NT_STATUS_NO_MEMORY);
4939 		error_to_writebrawerr(req);
4940 		goto out;
4941 	}
4942 
4943 	/* Return a SMBwritebraw message to the redirector to tell
4944 	 * it to send more bytes */
4945 
4946 	memcpy(buf, req->inbuf, smb_size);
4947 	srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4948 	SCVAL(buf,smb_com,SMBwritebraw);
4949 	SSVALS(buf,smb_vwv0,0xFFFF);
4950 	show_msg(buf);
4951 	if (!srv_send_smb(req->xconn,
4952 			  buf,
4953 			  false, 0, /* no signing */
4954 			  IS_CONN_ENCRYPTED(conn),
4955 			  &req->pcd)) {
4956 		exit_server_cleanly("reply_writebraw: srv_send_smb "
4957 			"failed.");
4958 	}
4959 
4960 	/* Now read the raw data into the buffer and write it */
4961 	status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4962 				 &numtowrite);
4963 	if (!NT_STATUS_IS_OK(status)) {
4964 		exit_server_cleanly("secondary writebraw failed");
4965 	}
4966 
4967 	/* Set up outbuf to return the correct size */
4968 	reply_outbuf(req, 1, 0);
4969 
4970 	if (numtowrite != 0) {
4971 
4972 		if (numtowrite > 0xFFFF) {
4973 			DEBUG(0,("reply_writebraw: Oversize secondary write "
4974 				"raw requested (%u). Terminating\n",
4975 				(unsigned int)numtowrite ));
4976 			exit_server_cleanly("secondary writebraw failed");
4977 		}
4978 
4979 		if (tcount > nwritten+numtowrite) {
4980 			DEBUG(3,("reply_writebraw: Client overestimated the "
4981 				"write %d %d %d\n",
4982 				(int)tcount,(int)nwritten,(int)numtowrite));
4983 		}
4984 
4985 		status = read_data_ntstatus(xconn->transport.sock, buf+4,
4986 					    numtowrite);
4987 
4988 		if (!NT_STATUS_IS_OK(status)) {
4989 			/* Try and give an error message
4990 			 * saying what client failed. */
4991 			DEBUG(0, ("reply_writebraw: Oversize secondary write "
4992 				  "raw read failed (%s) for client %s. "
4993 				  "Terminating\n", nt_errstr(status),
4994 				  smbXsrv_connection_dbg(xconn)));
4995 			exit_server_cleanly("secondary writebraw failed");
4996 		}
4997 
4998 		/*
4999 		 * We are not vulnerable to CVE-2017-12163
5000 		 * here as we are guaranteed to have numtowrite
5001 		 * bytes available - we just read from the client.
5002 		 */
5003 		nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
5004 		if (nwritten == -1) {
5005 			TALLOC_FREE(buf);
5006 			reply_nterror(req, map_nt_error_from_unix(errno));
5007 			error_to_writebrawerr(req);
5008 			goto out;
5009 		}
5010 
5011 		if (nwritten < (ssize_t)numtowrite) {
5012 			SCVAL(req->outbuf,smb_rcls,ERRHRD);
5013 			SSVAL(req->outbuf,smb_err,ERRdiskfull);
5014 		}
5015 
5016 		if (nwritten > 0) {
5017 			total_written += nwritten;
5018 		}
5019  	}
5020 
5021 	TALLOC_FREE(buf);
5022 	SSVAL(req->outbuf,smb_vwv0,total_written);
5023 
5024 	status = sync_file(conn, fsp, write_through);
5025 	if (!NT_STATUS_IS_OK(status)) {
5026 		DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5027 			 fsp_str_dbg(fsp), nt_errstr(status)));
5028 		reply_nterror(req, status);
5029 		error_to_writebrawerr(req);
5030 		goto out;
5031 	}
5032 
5033 	DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5034 		"wrote=%d\n",
5035 		fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5036 		(int)total_written));
5037 
5038 	/* We won't return a status if write through is not selected - this
5039 	 * follows what WfWg does */
5040 	END_PROFILE(SMBwritebraw);
5041 
5042 	if (!write_through && total_written==tcount) {
5043 
5044 #if RABBIT_PELLET_FIX
5045 		/*
5046 		 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5047 		 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5048 		 * JRA.
5049 		 */
5050 		if (!send_keepalive(xconn->transport.sock)) {
5051 			exit_server_cleanly("reply_writebraw: send of "
5052 				"keepalive failed");
5053 		}
5054 #endif
5055 		TALLOC_FREE(req->outbuf);
5056 	}
5057 	return;
5058 
5059 out:
5060 	END_PROFILE(SMBwritebraw);
5061 	return;
5062 }
5063 
5064 #undef DBGC_CLASS
5065 #define DBGC_CLASS DBGC_LOCKING
5066 
5067 /****************************************************************************
5068  Reply to a writeunlock (core+).
5069 ****************************************************************************/
5070 
reply_writeunlock(struct smb_request * req)5071 void reply_writeunlock(struct smb_request *req)
5072 {
5073 	connection_struct *conn = req->conn;
5074 	ssize_t nwritten = -1;
5075 	size_t numtowrite;
5076 	size_t remaining;
5077 	off_t startpos;
5078 	const char *data;
5079 	NTSTATUS status = NT_STATUS_OK;
5080 	files_struct *fsp;
5081 	struct lock_struct lock;
5082 	int saved_errno = 0;
5083 
5084 	START_PROFILE(SMBwriteunlock);
5085 
5086 	if (req->wct < 5) {
5087 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5088 		END_PROFILE(SMBwriteunlock);
5089 		return;
5090 	}
5091 
5092 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5093 
5094 	if (!check_fsp(conn, req, fsp)) {
5095 		END_PROFILE(SMBwriteunlock);
5096 		return;
5097 	}
5098 
5099 	if (!CHECK_WRITE(fsp)) {
5100 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5101 		END_PROFILE(SMBwriteunlock);
5102 		return;
5103 	}
5104 
5105 	numtowrite = SVAL(req->vwv+1, 0);
5106 	startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5107 	data = (const char *)req->buf + 3;
5108 
5109 	/*
5110 	 * Ensure client isn't asking us to write more than
5111 	 * they sent. CVE-2017-12163.
5112 	 */
5113 	remaining = smbreq_bufrem(req, data);
5114 	if (numtowrite > remaining) {
5115 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5116 		END_PROFILE(SMBwriteunlock);
5117 		return;
5118 	}
5119 
5120 	if (!fsp->print_file && numtowrite > 0) {
5121 		init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5122 		    (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5123 		    &lock);
5124 
5125 		if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5126 			reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5127 			END_PROFILE(SMBwriteunlock);
5128 			return;
5129 		}
5130 	}
5131 
5132 	/* The special X/Open SMB protocol handling of
5133 	   zero length writes is *NOT* done for
5134 	   this call */
5135 	if(numtowrite == 0) {
5136 		nwritten = 0;
5137 	} else {
5138 		nwritten = write_file(req,fsp,data,startpos,numtowrite);
5139 		saved_errno = errno;
5140 	}
5141 
5142 	status = sync_file(conn, fsp, False /* write through */);
5143 	if (!NT_STATUS_IS_OK(status)) {
5144 		DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5145 			 fsp_str_dbg(fsp), nt_errstr(status)));
5146 		reply_nterror(req, status);
5147 		goto out;
5148 	}
5149 
5150 	if(nwritten < 0) {
5151 		reply_nterror(req, map_nt_error_from_unix(saved_errno));
5152 		goto out;
5153 	}
5154 
5155 	if((nwritten < numtowrite) && (numtowrite != 0)) {
5156 		reply_nterror(req, NT_STATUS_DISK_FULL);
5157 		goto out;
5158 	}
5159 
5160 	if (numtowrite && !fsp->print_file) {
5161 		struct smbd_lock_element l = {
5162 			.req_guid = smbd_request_guid(req, 0),
5163 			.smblctx = req->smbpid,
5164 			.brltype = UNLOCK_LOCK,
5165 			.offset = startpos,
5166 			.count = numtowrite,
5167 		};
5168 		status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5169 		if (NT_STATUS_V(status)) {
5170 			reply_nterror(req, status);
5171 			goto out;
5172 		}
5173 	}
5174 
5175 	reply_outbuf(req, 1, 0);
5176 
5177 	SSVAL(req->outbuf,smb_vwv0,nwritten);
5178 
5179 	DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5180 		  fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5181 
5182 out:
5183 	END_PROFILE(SMBwriteunlock);
5184 	return;
5185 }
5186 
5187 #undef DBGC_CLASS
5188 #define DBGC_CLASS DBGC_ALL
5189 
5190 /****************************************************************************
5191  Reply to a write.
5192 ****************************************************************************/
5193 
reply_write(struct smb_request * req)5194 void reply_write(struct smb_request *req)
5195 {
5196 	connection_struct *conn = req->conn;
5197 	size_t numtowrite;
5198 	size_t remaining;
5199 	ssize_t nwritten = -1;
5200 	off_t startpos;
5201 	const char *data;
5202 	files_struct *fsp;
5203 	struct lock_struct lock;
5204 	NTSTATUS status;
5205 	int saved_errno = 0;
5206 
5207 	START_PROFILE(SMBwrite);
5208 
5209 	if (req->wct < 5) {
5210 		END_PROFILE(SMBwrite);
5211 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5212 		return;
5213 	}
5214 
5215 	/* If it's an IPC, pass off the pipe handler. */
5216 	if (IS_IPC(conn)) {
5217 		reply_pipe_write(req);
5218 		END_PROFILE(SMBwrite);
5219 		return;
5220 	}
5221 
5222 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5223 
5224 	if (!check_fsp(conn, req, fsp)) {
5225 		END_PROFILE(SMBwrite);
5226 		return;
5227 	}
5228 
5229 	if (!CHECK_WRITE(fsp)) {
5230 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5231 		END_PROFILE(SMBwrite);
5232 		return;
5233 	}
5234 
5235 	numtowrite = SVAL(req->vwv+1, 0);
5236 	startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5237 	data = (const char *)req->buf + 3;
5238 
5239 	/*
5240 	 * Ensure client isn't asking us to write more than
5241 	 * they sent. CVE-2017-12163.
5242 	 */
5243 	remaining = smbreq_bufrem(req, data);
5244 	if (numtowrite > remaining) {
5245 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5246 		END_PROFILE(SMBwrite);
5247 		return;
5248 	}
5249 
5250 	if (!fsp->print_file) {
5251 		init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5252 			(uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5253 			&lock);
5254 
5255 		if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5256 			reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5257 			END_PROFILE(SMBwrite);
5258 			return;
5259 		}
5260 	}
5261 
5262 	/*
5263 	 * X/Open SMB protocol says that if smb_vwv1 is
5264 	 * zero then the file size should be extended or
5265 	 * truncated to the size given in smb_vwv[2-3].
5266 	 */
5267 
5268 	if(numtowrite == 0) {
5269 		/*
5270 		 * This is actually an allocate call, and set EOF. JRA.
5271 		 */
5272 		nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5273 		if (nwritten < 0) {
5274 			reply_nterror(req, NT_STATUS_DISK_FULL);
5275 			goto out;
5276 		}
5277 		nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5278 		if (nwritten < 0) {
5279 			reply_nterror(req, NT_STATUS_DISK_FULL);
5280 			goto out;
5281 		}
5282 		trigger_write_time_update_immediate(fsp);
5283 	} else {
5284 		nwritten = write_file(req,fsp,data,startpos,numtowrite);
5285 	}
5286 
5287 	status = sync_file(conn, fsp, False);
5288 	if (!NT_STATUS_IS_OK(status)) {
5289 		DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5290 			 fsp_str_dbg(fsp), nt_errstr(status)));
5291 		reply_nterror(req, status);
5292 		goto out;
5293 	}
5294 
5295 	if(nwritten < 0) {
5296 		reply_nterror(req, map_nt_error_from_unix(saved_errno));
5297 		goto out;
5298 	}
5299 
5300 	if((nwritten == 0) && (numtowrite != 0)) {
5301 		reply_nterror(req, NT_STATUS_DISK_FULL);
5302 		goto out;
5303 	}
5304 
5305 	reply_outbuf(req, 1, 0);
5306 
5307 	SSVAL(req->outbuf,smb_vwv0,nwritten);
5308 
5309 	if (nwritten < (ssize_t)numtowrite) {
5310 		SCVAL(req->outbuf,smb_rcls,ERRHRD);
5311 		SSVAL(req->outbuf,smb_err,ERRdiskfull);
5312 	}
5313 
5314 	DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5315 
5316 out:
5317 	END_PROFILE(SMBwrite);
5318 	return;
5319 }
5320 
5321 /****************************************************************************
5322  Ensure a buffer is a valid writeX for recvfile purposes.
5323 ****************************************************************************/
5324 
5325 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5326 						(2*14) + /* word count (including bcc) */ \
5327 						1 /* pad byte */)
5328 
is_valid_writeX_buffer(struct smbXsrv_connection * xconn,const uint8_t * inbuf)5329 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5330 			    const uint8_t *inbuf)
5331 {
5332 	size_t numtowrite;
5333 	unsigned int doff = 0;
5334 	size_t len = smb_len_large(inbuf);
5335 	uint16_t fnum;
5336 	struct smbXsrv_open *op = NULL;
5337 	struct files_struct *fsp = NULL;
5338 	NTSTATUS status;
5339 
5340 	if (is_encrypted_packet(inbuf)) {
5341 		/* Can't do this on encrypted
5342 		 * connections. */
5343 		return false;
5344 	}
5345 
5346 	if (CVAL(inbuf,smb_com) != SMBwriteX) {
5347 		return false;
5348 	}
5349 
5350 	if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5351 			CVAL(inbuf,smb_wct) != 14) {
5352 		DEBUG(10,("is_valid_writeX_buffer: chained or "
5353 			"invalid word length.\n"));
5354 		return false;
5355 	}
5356 
5357 	fnum = SVAL(inbuf, smb_vwv2);
5358 	status = smb1srv_open_lookup(xconn,
5359 				     fnum,
5360 				     0, /* now */
5361 				     &op);
5362 	if (!NT_STATUS_IS_OK(status)) {
5363 		DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5364 		return false;
5365 	}
5366 	fsp = op->compat;
5367 	if (fsp == NULL) {
5368 		DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5369 		return false;
5370 	}
5371 	if (fsp->conn == NULL) {
5372 		DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5373 		return false;
5374 	}
5375 
5376 	if (IS_IPC(fsp->conn)) {
5377 		DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5378 		return false;
5379 	}
5380 	if (IS_PRINT(fsp->conn)) {
5381 		DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5382 		return false;
5383 	}
5384 	if (fsp->base_fsp != NULL) {
5385 		DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5386 		return false;
5387 	}
5388 	doff = SVAL(inbuf,smb_vwv11);
5389 
5390 	numtowrite = SVAL(inbuf,smb_vwv10);
5391 
5392 	if (len > doff && len - doff > 0xFFFF) {
5393 		numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5394 	}
5395 
5396 	if (numtowrite == 0) {
5397 		DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5398 		return false;
5399 	}
5400 
5401 	/* Ensure the sizes match up. */
5402 	if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5403 		/* no pad byte...old smbclient :-( */
5404 		DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5405 			(unsigned int)doff,
5406 			(unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5407 		return false;
5408 	}
5409 
5410 	if (len - doff != numtowrite) {
5411 		DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5412 			"len = %u, doff = %u, numtowrite = %u\n",
5413 			(unsigned int)len,
5414 			(unsigned int)doff,
5415 			(unsigned int)numtowrite ));
5416 		return false;
5417 	}
5418 
5419 	DEBUG(10,("is_valid_writeX_buffer: true "
5420 		"len = %u, doff = %u, numtowrite = %u\n",
5421 		(unsigned int)len,
5422 		(unsigned int)doff,
5423 		(unsigned int)numtowrite ));
5424 
5425 	return true;
5426 }
5427 
5428 /****************************************************************************
5429  Reply to a write and X.
5430 ****************************************************************************/
5431 
reply_write_and_X(struct smb_request * req)5432 void reply_write_and_X(struct smb_request *req)
5433 {
5434 	connection_struct *conn = req->conn;
5435 	struct smbXsrv_connection *xconn = req->xconn;
5436 	files_struct *fsp;
5437 	struct lock_struct lock;
5438 	off_t startpos;
5439 	size_t numtowrite;
5440 	bool write_through;
5441 	ssize_t nwritten;
5442 	unsigned int smb_doff;
5443 	unsigned int smblen;
5444 	const char *data;
5445 	NTSTATUS status;
5446 	int saved_errno = 0;
5447 
5448 	START_PROFILE(SMBwriteX);
5449 
5450 	if ((req->wct != 12) && (req->wct != 14)) {
5451 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5452 		goto out;
5453 	}
5454 
5455 	numtowrite = SVAL(req->vwv+10, 0);
5456 	smb_doff = SVAL(req->vwv+11, 0);
5457 	smblen = smb_len(req->inbuf);
5458 
5459 	if (req->unread_bytes > 0xFFFF ||
5460 			(smblen > smb_doff &&
5461 				smblen - smb_doff > 0xFFFF)) {
5462 		numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5463 	}
5464 
5465 	if (req->unread_bytes) {
5466 		/* Can't do a recvfile write on IPC$ */
5467 		if (IS_IPC(conn)) {
5468 			reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5469 			goto out;
5470 		}
5471 	       	if (numtowrite != req->unread_bytes) {
5472 			reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5473 			goto out;
5474 		}
5475 	} else {
5476 		/*
5477 		 * This already protects us against CVE-2017-12163.
5478 		 */
5479 		if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5480 				smb_doff + numtowrite > smblen) {
5481 			reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5482 			goto out;
5483 		}
5484 	}
5485 
5486 	/* If it's an IPC, pass off the pipe handler. */
5487 	if (IS_IPC(conn)) {
5488 		if (req->unread_bytes) {
5489 			reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5490 			goto out;
5491 		}
5492 		reply_pipe_write_and_X(req);
5493 		goto out;
5494 	}
5495 
5496 	fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5497 	startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5498 	write_through = BITSETW(req->vwv+7,0);
5499 
5500 	if (!check_fsp(conn, req, fsp)) {
5501 		goto out;
5502 	}
5503 
5504 	if (!CHECK_WRITE(fsp)) {
5505 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5506 		goto out;
5507 	}
5508 
5509 	data = smb_base(req->inbuf) + smb_doff;
5510 
5511 	if(req->wct == 14) {
5512 		/*
5513 		 * This is a large offset (64 bit) write.
5514 		 */
5515 		startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5516 
5517 	}
5518 
5519 	/* X/Open SMB protocol says that, unlike SMBwrite
5520 	if the length is zero then NO truncation is
5521 	done, just a write of zero. To truncate a file,
5522 	use SMBwrite. */
5523 
5524 	if(numtowrite == 0) {
5525 		nwritten = 0;
5526 	} else {
5527 		if (req->unread_bytes == 0) {
5528 			status = schedule_aio_write_and_X(conn,
5529 						req,
5530 						fsp,
5531 						data,
5532 						startpos,
5533 						numtowrite);
5534 
5535 			if (NT_STATUS_IS_OK(status)) {
5536 				/* write scheduled - we're done. */
5537 				goto out;
5538 			}
5539 			if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5540 				/* Real error - report to client. */
5541 				reply_nterror(req, status);
5542 				goto out;
5543 			}
5544 			/* NT_STATUS_RETRY - fall through to sync write. */
5545 		}
5546 
5547 		init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5548 		    (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5549 		    &lock);
5550 
5551 		if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5552 			reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5553 			goto out;
5554 		}
5555 
5556 		nwritten = write_file(req,fsp,data,startpos,numtowrite);
5557 		saved_errno = errno;
5558 	}
5559 
5560 	if(nwritten < 0) {
5561 		reply_nterror(req, map_nt_error_from_unix(saved_errno));
5562 		goto out;
5563 	}
5564 
5565 	if((nwritten == 0) && (numtowrite != 0)) {
5566 		reply_nterror(req, NT_STATUS_DISK_FULL);
5567 		goto out;
5568 	}
5569 
5570 	reply_outbuf(req, 6, 0);
5571 	SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5572 	SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
5573 	SSVAL(req->outbuf,smb_vwv2,nwritten);
5574 	SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5575 
5576 	DEBUG(3,("writeX %s num=%d wrote=%d\n",
5577 		fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5578 
5579 	status = sync_file(conn, fsp, write_through);
5580 	if (!NT_STATUS_IS_OK(status)) {
5581 		DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5582 			 fsp_str_dbg(fsp), nt_errstr(status)));
5583 		reply_nterror(req, status);
5584 		goto out;
5585 	}
5586 
5587 	END_PROFILE(SMBwriteX);
5588 	return;
5589 
5590 out:
5591 	if (req->unread_bytes) {
5592 		/* writeX failed. drain socket. */
5593 		if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5594 				req->unread_bytes) {
5595 			smb_panic("failed to drain pending bytes");
5596 		}
5597 		req->unread_bytes = 0;
5598 	}
5599 
5600 	END_PROFILE(SMBwriteX);
5601 	return;
5602 }
5603 
5604 /****************************************************************************
5605  Reply to a lseek.
5606 ****************************************************************************/
5607 
reply_lseek(struct smb_request * req)5608 void reply_lseek(struct smb_request *req)
5609 {
5610 	connection_struct *conn = req->conn;
5611 	off_t startpos;
5612 	off_t res= -1;
5613 	int mode,umode;
5614 	files_struct *fsp;
5615 	NTSTATUS status;
5616 
5617 	START_PROFILE(SMBlseek);
5618 
5619 	if (req->wct < 4) {
5620 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5621 		END_PROFILE(SMBlseek);
5622 		return;
5623 	}
5624 
5625 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5626 
5627 	if (!check_fsp(conn, req, fsp)) {
5628 		return;
5629 	}
5630 
5631 	mode = SVAL(req->vwv+1, 0) & 3;
5632 	/* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5633 	startpos = (off_t)IVALS(req->vwv+2, 0);
5634 
5635 	switch (mode) {
5636 		case 0:
5637 			umode = SEEK_SET;
5638 			res = startpos;
5639 			break;
5640 		case 1:
5641 			umode = SEEK_CUR;
5642 			res = fsp->fh->pos + startpos;
5643 			break;
5644 		case 2:
5645 			umode = SEEK_END;
5646 			break;
5647 		default:
5648 			umode = SEEK_SET;
5649 			res = startpos;
5650 			break;
5651 	}
5652 
5653 	if (umode == SEEK_END) {
5654 		if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5655 			if(errno == EINVAL) {
5656 				off_t current_pos = startpos;
5657 
5658 				status = vfs_stat_fsp(fsp);
5659 				if (!NT_STATUS_IS_OK(status)) {
5660 					reply_nterror(req, status);
5661 					END_PROFILE(SMBlseek);
5662 					return;
5663 				}
5664 
5665 				current_pos += fsp->fsp_name->st.st_ex_size;
5666 				if(current_pos < 0)
5667 					res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5668 			}
5669 		}
5670 
5671 		if(res == -1) {
5672 			reply_nterror(req, map_nt_error_from_unix(errno));
5673 			END_PROFILE(SMBlseek);
5674 			return;
5675 		}
5676 	}
5677 
5678 	fsp->fh->pos = res;
5679 
5680 	reply_outbuf(req, 2, 0);
5681 	SIVAL(req->outbuf,smb_vwv0,res);
5682 
5683 	DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5684 		fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5685 
5686 	END_PROFILE(SMBlseek);
5687 	return;
5688 }
5689 
file_sync_one_fn(struct files_struct * fsp,void * private_data)5690 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5691 					     void *private_data)
5692 {
5693 	connection_struct *conn = talloc_get_type_abort(
5694 		private_data, connection_struct);
5695 
5696 	if (conn != fsp->conn) {
5697 		return NULL;
5698 	}
5699 	if (fsp->fh->fd == -1) {
5700 		return NULL;
5701 	}
5702 	sync_file(conn, fsp, True /* write through */);
5703 
5704 	if (fsp->modified) {
5705 		trigger_write_time_update_immediate(fsp);
5706 	}
5707 
5708 	return NULL;
5709 }
5710 
5711 /****************************************************************************
5712  Reply to a flush.
5713 ****************************************************************************/
5714 
reply_flush(struct smb_request * req)5715 void reply_flush(struct smb_request *req)
5716 {
5717 	connection_struct *conn = req->conn;
5718 	uint16_t fnum;
5719 	files_struct *fsp;
5720 
5721 	START_PROFILE(SMBflush);
5722 
5723 	if (req->wct < 1) {
5724 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5725 		return;
5726 	}
5727 
5728 	fnum = SVAL(req->vwv+0, 0);
5729 	fsp = file_fsp(req, fnum);
5730 
5731 	if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5732 		return;
5733 	}
5734 
5735 	if (!fsp) {
5736 		files_forall(req->sconn, file_sync_one_fn, conn);
5737 	} else {
5738 		NTSTATUS status = sync_file(conn, fsp, True);
5739 		if (!NT_STATUS_IS_OK(status)) {
5740 			DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5741 				fsp_str_dbg(fsp), nt_errstr(status)));
5742 			reply_nterror(req, status);
5743 			END_PROFILE(SMBflush);
5744 			return;
5745 		}
5746 		if (fsp->modified) {
5747 			trigger_write_time_update_immediate(fsp);
5748 		}
5749 	}
5750 
5751 	reply_outbuf(req, 0, 0);
5752 
5753 	DEBUG(3,("flush\n"));
5754 	END_PROFILE(SMBflush);
5755 	return;
5756 }
5757 
5758 /****************************************************************************
5759  Reply to a exit.
5760  conn POINTER CAN BE NULL HERE !
5761 ****************************************************************************/
5762 
5763 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5764 static void reply_exit_done(struct tevent_req *req);
5765 
reply_exit(struct smb_request * smb1req)5766 void reply_exit(struct smb_request *smb1req)
5767 {
5768 	struct tevent_req *req;
5769 
5770 	/*
5771 	 * Don't setup the profile charge here, take
5772 	 * it in reply_exit_done(). Not strictly correct
5773 	 * but better than the other SMB1 async
5774 	 * code that double-charges at the moment.
5775 	 */
5776 	req = reply_exit_send(smb1req);
5777 	if (req == NULL) {
5778 		/* Not going async, profile here. */
5779 		START_PROFILE(SMBexit);
5780 		reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5781 		END_PROFILE(SMBexit);
5782 		return;
5783 	}
5784 
5785 	/* We're async. This will complete later. */
5786 	tevent_req_set_callback(req, reply_exit_done, smb1req);
5787 	return;
5788 }
5789 
5790 struct reply_exit_state {
5791 	struct tevent_queue *wait_queue;
5792 };
5793 
5794 static void reply_exit_wait_done(struct tevent_req *subreq);
5795 
5796 /****************************************************************************
5797  Async SMB1 exit.
5798  Note, on failure here we deallocate and return NULL to allow the caller to
5799  SMB1 return an error of ERRnomem immediately.
5800 ****************************************************************************/
5801 
reply_exit_send(struct smb_request * smb1req)5802 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5803 {
5804 	struct tevent_req *req;
5805 	struct reply_exit_state *state;
5806 	struct tevent_req *subreq;
5807 	files_struct *fsp;
5808 	struct smbd_server_connection *sconn = smb1req->sconn;
5809 
5810 	req = tevent_req_create(smb1req, &state,
5811 			struct reply_exit_state);
5812 	if (req == NULL) {
5813 		return NULL;
5814 	}
5815 	state->wait_queue = tevent_queue_create(state,
5816 				"reply_exit_wait_queue");
5817 	if (tevent_req_nomem(state->wait_queue, req)) {
5818 		TALLOC_FREE(req);
5819 		return NULL;
5820 	}
5821 
5822 	for (fsp = sconn->files; fsp; fsp = fsp->next) {
5823 		if (fsp->file_pid != smb1req->smbpid) {
5824 			continue;
5825 		}
5826 		if (fsp->vuid != smb1req->vuid) {
5827 			continue;
5828 		}
5829 		/*
5830 		 * Flag the file as close in progress.
5831 		 * This will prevent any more IO being
5832 		 * done on it.
5833 		 */
5834 		fsp->closing = true;
5835 
5836 		if (fsp->num_aio_requests > 0) {
5837 			/*
5838 			 * Now wait until all aio requests on this fsp are
5839 			 * finished.
5840 			 *
5841 			 * We don't set a callback, as we just want to block the
5842 			 * wait queue and the talloc_free() of fsp->aio_request
5843 			 * will remove the item from the wait queue.
5844 			 */
5845 			subreq = tevent_queue_wait_send(fsp->aio_requests,
5846 						sconn->ev_ctx,
5847 						state->wait_queue);
5848 			if (tevent_req_nomem(subreq, req)) {
5849 				TALLOC_FREE(req);
5850 				return NULL;
5851 			}
5852 		}
5853 	}
5854 
5855 	/*
5856 	 * Now we add our own waiter to the end of the queue,
5857 	 * this way we get notified when all pending requests are finished
5858 	 * and reply to the outstanding SMB1 request.
5859 	 */
5860 	subreq = tevent_queue_wait_send(state,
5861 				sconn->ev_ctx,
5862 				state->wait_queue);
5863 	if (tevent_req_nomem(subreq, req)) {
5864 		TALLOC_FREE(req);
5865 		return NULL;
5866 	}
5867 
5868 	/*
5869 	 * We're really going async - move the SMB1 request from
5870 	 * a talloc stackframe above us to the conn talloc-context.
5871 	 * We need this to stick around until the wait_done
5872 	 * callback is invoked.
5873 	 */
5874 	smb1req = talloc_move(sconn, &smb1req);
5875 
5876 	tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5877 
5878 	return req;
5879 }
5880 
reply_exit_wait_done(struct tevent_req * subreq)5881 static void reply_exit_wait_done(struct tevent_req *subreq)
5882 {
5883 	struct tevent_req *req = tevent_req_callback_data(
5884 		subreq, struct tevent_req);
5885 
5886 	tevent_queue_wait_recv(subreq);
5887 	TALLOC_FREE(subreq);
5888 	tevent_req_done(req);
5889 }
5890 
reply_exit_recv(struct tevent_req * req)5891 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5892 {
5893 	return tevent_req_simple_recv_ntstatus(req);
5894 }
5895 
reply_exit_done(struct tevent_req * req)5896 static void reply_exit_done(struct tevent_req *req)
5897 {
5898 	struct smb_request *smb1req = tevent_req_callback_data(
5899 		req, struct smb_request);
5900 	struct smbd_server_connection *sconn = smb1req->sconn;
5901 	struct smbXsrv_connection *xconn = smb1req->xconn;
5902 	NTTIME now = timeval_to_nttime(&smb1req->request_time);
5903 	struct smbXsrv_session *session = NULL;
5904 	files_struct *fsp, *next;
5905 	NTSTATUS status;
5906 
5907 	/*
5908 	 * Take the profile charge here. Not strictly
5909 	 * correct but better than the other SMB1 async
5910 	 * code that double-charges at the moment.
5911 	 */
5912 	START_PROFILE(SMBexit);
5913 
5914 	status = reply_exit_recv(req);
5915 	TALLOC_FREE(req);
5916 	if (!NT_STATUS_IS_OK(status)) {
5917 		TALLOC_FREE(smb1req);
5918 		END_PROFILE(SMBexit);
5919 		exit_server(__location__ ": reply_exit_recv failed");
5920 		return;
5921 	}
5922 
5923 	/*
5924 	 * Ensure the session is still valid.
5925 	 */
5926 	status = smb1srv_session_lookup(xconn,
5927 					smb1req->vuid,
5928 					now,
5929 					&session);
5930 	if (!NT_STATUS_IS_OK(status)) {
5931 		reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5932 		smb_request_done(smb1req);
5933 		END_PROFILE(SMBexit);
5934 	}
5935 
5936 	/*
5937 	 * Ensure the vuid is still valid - no one
5938 	 * called reply_ulogoffX() in the meantime.
5939 	 * reply_exit() doesn't have AS_USER set, so
5940 	 * use set_current_user_info() directly.
5941 	 * This is the same logic as in switch_message().
5942 	 */
5943 	if (session->global->auth_session_info != NULL) {
5944 		set_current_user_info(
5945 			session->global->auth_session_info->unix_info->sanitized_username,
5946 			session->global->auth_session_info->unix_info->unix_name,
5947 			session->global->auth_session_info->info->domain_name);
5948 	}
5949 
5950 	/* No more aio - do the actual closes. */
5951 	for (fsp = sconn->files; fsp; fsp = next) {
5952 		bool ok;
5953 		next = fsp->next;
5954 
5955 		if (fsp->file_pid != smb1req->smbpid) {
5956 			continue;
5957 		}
5958 		if (fsp->vuid != smb1req->vuid) {
5959 			continue;
5960 		}
5961 		if (!fsp->closing) {
5962 			continue;
5963 		}
5964 
5965 		/*
5966 		 * reply_exit() has the DO_CHDIR flag set.
5967 		 */
5968 		ok = chdir_current_service(fsp->conn);
5969 		if (!ok) {
5970 			reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5971 			smb_request_done(smb1req);
5972 			END_PROFILE(SMBexit);
5973 		}
5974 		close_file(NULL, fsp, SHUTDOWN_CLOSE);
5975 	}
5976 
5977 	reply_outbuf(smb1req, 0, 0);
5978 	/*
5979 	 * The following call is needed to push the
5980 	 * reply data back out the socket after async
5981 	 * return. Plus it frees smb1req.
5982 	 */
5983 	smb_request_done(smb1req);
5984 	DBG_INFO("reply_exit complete\n");
5985 	END_PROFILE(SMBexit);
5986 	return;
5987 }
5988 
5989 struct reply_close_state {
5990 	files_struct *fsp;
5991 	struct smb_request *smbreq;
5992 };
5993 
5994 static void do_smb1_close(struct tevent_req *req);
5995 
reply_close(struct smb_request * req)5996 void reply_close(struct smb_request *req)
5997 {
5998 	connection_struct *conn = req->conn;
5999 	NTSTATUS status = NT_STATUS_OK;
6000 	files_struct *fsp = NULL;
6001 	START_PROFILE(SMBclose);
6002 
6003 	if (req->wct < 3) {
6004 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6005 		END_PROFILE(SMBclose);
6006 		return;
6007 	}
6008 
6009 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6010 
6011 	/*
6012 	 * We can only use check_fsp if we know it's not a directory.
6013 	 */
6014 
6015 	if (!check_fsp_open(conn, req, fsp)) {
6016 		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6017 		END_PROFILE(SMBclose);
6018 		return;
6019 	}
6020 
6021 	DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
6022 		  fsp->is_directory ? "directory" : "file",
6023 		  fsp->fh->fd, fsp_fnum_dbg(fsp),
6024 		  conn->num_files_open));
6025 
6026 	if (!fsp->is_directory) {
6027 		time_t t;
6028 
6029 		/*
6030 		 * Take care of any time sent in the close.
6031 		 */
6032 
6033 		t = srv_make_unix_date3(req->vwv+1);
6034 		set_close_write_time(fsp, time_t_to_full_timespec(t));
6035 	}
6036 
6037 	if (fsp->num_aio_requests != 0) {
6038 
6039 		struct reply_close_state *state;
6040 
6041 		DEBUG(10, ("closing with aio %u requests pending\n",
6042 			   fsp->num_aio_requests));
6043 
6044 		/*
6045 		 * Flag the file as close in progress.
6046 		 * This will prevent any more IO being
6047 		 * done on it.
6048 		 */
6049 		fsp->closing = true;
6050 
6051 		/*
6052 		 * We depend on the aio_extra destructor to take care of this
6053 		 * close request once fsp->num_aio_request drops to 0.
6054 		 */
6055 
6056 		fsp->deferred_close = tevent_wait_send(
6057 			fsp, fsp->conn->sconn->ev_ctx);
6058 		if (fsp->deferred_close == NULL) {
6059 			status = NT_STATUS_NO_MEMORY;
6060 			goto done;
6061 		}
6062 
6063 		state = talloc(fsp, struct reply_close_state);
6064 		if (state == NULL) {
6065 			TALLOC_FREE(fsp->deferred_close);
6066 			status = NT_STATUS_NO_MEMORY;
6067 			goto done;
6068 		}
6069 		state->fsp = fsp;
6070 		state->smbreq = talloc_move(fsp, &req);
6071 		tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
6072 					state);
6073 		END_PROFILE(SMBclose);
6074 		return;
6075 	}
6076 
6077 	/*
6078 	 * close_file() returns the unix errno if an error was detected on
6079 	 * close - normally this is due to a disk full error. If not then it
6080 	 * was probably an I/O error.
6081 	 */
6082 
6083 	status = close_file(req, fsp, NORMAL_CLOSE);
6084 done:
6085 	if (!NT_STATUS_IS_OK(status)) {
6086 		reply_nterror(req, status);
6087 		END_PROFILE(SMBclose);
6088 		return;
6089 	}
6090 
6091 	reply_outbuf(req, 0, 0);
6092 	END_PROFILE(SMBclose);
6093 	return;
6094 }
6095 
do_smb1_close(struct tevent_req * req)6096 static void do_smb1_close(struct tevent_req *req)
6097 {
6098 	struct reply_close_state *state = tevent_req_callback_data(
6099 		req, struct reply_close_state);
6100 	struct smb_request *smbreq;
6101 	NTSTATUS status;
6102 	int ret;
6103 
6104 	ret = tevent_wait_recv(req);
6105 	TALLOC_FREE(req);
6106 	if (ret != 0) {
6107 		DEBUG(10, ("tevent_wait_recv returned %s\n",
6108 			   strerror(ret)));
6109 		/*
6110 		 * Continue anyway, this should never happen
6111 		 */
6112 	}
6113 
6114 	/*
6115 	 * fsp->smb2_close_request right now is a talloc grandchild of
6116 	 * fsp. When we close_file(fsp), it would go with it. No chance to
6117 	 * reply...
6118 	 */
6119 	smbreq = talloc_move(talloc_tos(), &state->smbreq);
6120 
6121 	status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
6122 	if (NT_STATUS_IS_OK(status)) {
6123 		reply_outbuf(smbreq, 0, 0);
6124 	} else {
6125 		reply_nterror(smbreq, status);
6126 	}
6127 	if (!srv_send_smb(smbreq->xconn,
6128 			(char *)smbreq->outbuf,
6129 			true,
6130 			smbreq->seqnum+1,
6131 			IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
6132 			NULL)) {
6133 		exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
6134 				    "failed.");
6135 	}
6136 	TALLOC_FREE(smbreq);
6137 }
6138 
6139 /****************************************************************************
6140  Reply to a writeclose (Core+ protocol).
6141 ****************************************************************************/
6142 
reply_writeclose(struct smb_request * req)6143 void reply_writeclose(struct smb_request *req)
6144 {
6145 	connection_struct *conn = req->conn;
6146 	size_t numtowrite;
6147 	size_t remaining;
6148 	ssize_t nwritten = -1;
6149 	NTSTATUS close_status = NT_STATUS_OK;
6150 	off_t startpos;
6151 	const char *data;
6152 	struct timespec mtime;
6153 	files_struct *fsp;
6154 	struct lock_struct lock;
6155 
6156 	START_PROFILE(SMBwriteclose);
6157 
6158 	if (req->wct < 6) {
6159 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6160 		END_PROFILE(SMBwriteclose);
6161 		return;
6162 	}
6163 
6164 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6165 
6166 	if (!check_fsp(conn, req, fsp)) {
6167 		END_PROFILE(SMBwriteclose);
6168 		return;
6169 	}
6170 	if (!CHECK_WRITE(fsp)) {
6171 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6172 		END_PROFILE(SMBwriteclose);
6173 		return;
6174 	}
6175 
6176 	numtowrite = SVAL(req->vwv+1, 0);
6177 	startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6178 	mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6179 	data = (const char *)req->buf + 1;
6180 
6181 	/*
6182 	 * Ensure client isn't asking us to write more than
6183 	 * they sent. CVE-2017-12163.
6184 	 */
6185 	remaining = smbreq_bufrem(req, data);
6186 	if (numtowrite > remaining) {
6187 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6188 		END_PROFILE(SMBwriteclose);
6189 		return;
6190 	}
6191 
6192 	if (fsp->print_file == NULL) {
6193 		init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6194 		    (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6195 		    &lock);
6196 
6197 		if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6198 			reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6199 			END_PROFILE(SMBwriteclose);
6200 			return;
6201 		}
6202 	}
6203 
6204 	nwritten = write_file(req,fsp,data,startpos,numtowrite);
6205 
6206 	set_close_write_time(fsp, mtime);
6207 
6208 	/*
6209 	 * More insanity. W2K only closes the file if writelen > 0.
6210 	 * JRA.
6211 	 */
6212 
6213 	DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6214 		fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6215 		(numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6216 
6217 	if (numtowrite) {
6218 		DEBUG(3,("reply_writeclose: zero length write doesn't close "
6219 			 "file %s\n", fsp_str_dbg(fsp)));
6220 		close_status = close_file(req, fsp, NORMAL_CLOSE);
6221 		fsp = NULL;
6222 	}
6223 
6224 	if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6225 		reply_nterror(req, NT_STATUS_DISK_FULL);
6226 		goto out;
6227 	}
6228 
6229 	if(!NT_STATUS_IS_OK(close_status)) {
6230 		reply_nterror(req, close_status);
6231 		goto out;
6232 	}
6233 
6234 	reply_outbuf(req, 1, 0);
6235 
6236 	SSVAL(req->outbuf,smb_vwv0,nwritten);
6237 
6238 out:
6239 
6240 	END_PROFILE(SMBwriteclose);
6241 	return;
6242 }
6243 
6244 #undef DBGC_CLASS
6245 #define DBGC_CLASS DBGC_LOCKING
6246 
6247 /****************************************************************************
6248  Reply to a lock.
6249 ****************************************************************************/
6250 
6251 static void reply_lock_done(struct tevent_req *subreq);
6252 
reply_lock(struct smb_request * req)6253 void reply_lock(struct smb_request *req)
6254 {
6255 	struct tevent_req *subreq = NULL;
6256 	connection_struct *conn = req->conn;
6257 	files_struct *fsp;
6258 	struct smbd_lock_element *lck = NULL;
6259 
6260 	START_PROFILE(SMBlock);
6261 
6262 	if (req->wct < 5) {
6263 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6264 		END_PROFILE(SMBlock);
6265 		return;
6266 	}
6267 
6268 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6269 
6270 	if (!check_fsp(conn, req, fsp)) {
6271 		END_PROFILE(SMBlock);
6272 		return;
6273 	}
6274 
6275 	lck = talloc(req, struct smbd_lock_element);
6276 	if (lck == NULL) {
6277 		reply_nterror(req, NT_STATUS_NO_MEMORY);
6278 		END_PROFILE(SMBlock);
6279 		return;
6280 	}
6281 
6282 	*lck = (struct smbd_lock_element) {
6283 		.req_guid = smbd_request_guid(req, 0),
6284 		.smblctx = req->smbpid,
6285 		.brltype = WRITE_LOCK,
6286 		.count = IVAL(req->vwv+1, 0),
6287 		.offset = IVAL(req->vwv+3, 0),
6288 	};
6289 
6290 	DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6291 		   fsp->fh->fd,
6292 		   fsp_fnum_dbg(fsp),
6293 		   lck->offset,
6294 		   lck->count);
6295 
6296 	subreq = smbd_smb1_do_locks_send(
6297 		fsp,
6298 		req->sconn->ev_ctx,
6299 		&req,
6300 		fsp,
6301 		0,
6302 		false,		/* large_offset */
6303 		WINDOWS_LOCK,
6304 		1,
6305 		lck);
6306 	if (subreq == NULL) {
6307 		reply_nterror(req, NT_STATUS_NO_MEMORY);
6308 		END_PROFILE(SMBlock);
6309 		return;
6310 	}
6311 	tevent_req_set_callback(subreq, reply_lock_done, NULL);
6312 	END_PROFILE(SMBlock);
6313 }
6314 
reply_lock_done(struct tevent_req * subreq)6315 static void reply_lock_done(struct tevent_req *subreq)
6316 {
6317 	struct smb_request *req = NULL;
6318 	NTSTATUS status;
6319 	bool ok;
6320 
6321 	START_PROFILE(SMBlock);
6322 
6323 	ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6324 	SMB_ASSERT(ok);
6325 
6326 	status = smbd_smb1_do_locks_recv(subreq);
6327 	TALLOC_FREE(subreq);
6328 
6329 	if (NT_STATUS_IS_OK(status)) {
6330 		reply_outbuf(req, 0, 0);
6331 	} else {
6332 		reply_nterror(req, status);
6333 	}
6334 
6335 	ok = srv_send_smb(req->xconn,
6336 			  (char *)req->outbuf,
6337 			  true,
6338 			  req->seqnum+1,
6339 			  IS_CONN_ENCRYPTED(req->conn),
6340 			  NULL);
6341 	if (!ok) {
6342 		exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6343 	}
6344 	TALLOC_FREE(req);
6345 	END_PROFILE(SMBlock);
6346 }
6347 
6348 /****************************************************************************
6349  Reply to a unlock.
6350 ****************************************************************************/
6351 
reply_unlock(struct smb_request * req)6352 void reply_unlock(struct smb_request *req)
6353 {
6354 	connection_struct *conn = req->conn;
6355 	NTSTATUS status;
6356 	files_struct *fsp;
6357 	struct smbd_lock_element lck;
6358 
6359 	START_PROFILE(SMBunlock);
6360 
6361 	if (req->wct < 5) {
6362 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6363 		END_PROFILE(SMBunlock);
6364 		return;
6365 	}
6366 
6367 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6368 
6369 	if (!check_fsp(conn, req, fsp)) {
6370 		END_PROFILE(SMBunlock);
6371 		return;
6372 	}
6373 
6374 	lck = (struct smbd_lock_element) {
6375 		.req_guid = smbd_request_guid(req, 0),
6376 		.smblctx = req->smbpid,
6377 		.brltype = UNLOCK_LOCK,
6378 		.offset = IVAL(req->vwv+3, 0),
6379 		.count = IVAL(req->vwv+1, 0),
6380 	};
6381 
6382 	status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6383 
6384 	if (!NT_STATUS_IS_OK(status)) {
6385 		reply_nterror(req, status);
6386 		END_PROFILE(SMBunlock);
6387 		return;
6388 	}
6389 
6390 	DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6391 		   fsp->fh->fd,
6392 		   fsp_fnum_dbg(fsp),
6393 		   lck.offset,
6394 		   lck.count);
6395 
6396 	reply_outbuf(req, 0, 0);
6397 
6398 	END_PROFILE(SMBunlock);
6399 	return;
6400 }
6401 
6402 #undef DBGC_CLASS
6403 #define DBGC_CLASS DBGC_ALL
6404 
6405 /****************************************************************************
6406  Reply to a tdis.
6407  conn POINTER CAN BE NULL HERE !
6408 ****************************************************************************/
6409 
6410 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6411 static void reply_tdis_done(struct tevent_req *req);
6412 
reply_tdis(struct smb_request * smb1req)6413 void reply_tdis(struct smb_request *smb1req)
6414 {
6415 	connection_struct *conn = smb1req->conn;
6416 	struct tevent_req *req;
6417 
6418 	/*
6419 	 * Don't setup the profile charge here, take
6420 	 * it in reply_tdis_done(). Not strictly correct
6421 	 * but better than the other SMB1 async
6422 	 * code that double-charges at the moment.
6423 	 */
6424 
6425 	if (conn == NULL) {
6426 		/* Not going async, profile here. */
6427 		START_PROFILE(SMBtdis);
6428 		DBG_INFO("Invalid connection in tdis\n");
6429 		reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6430 		END_PROFILE(SMBtdis);
6431 		return;
6432 	}
6433 
6434 	req = reply_tdis_send(smb1req);
6435 	if (req == NULL) {
6436 		/* Not going async, profile here. */
6437 		START_PROFILE(SMBtdis);
6438 		reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6439 		END_PROFILE(SMBtdis);
6440 		return;
6441 	}
6442 	/* We're async. This will complete later. */
6443 	tevent_req_set_callback(req, reply_tdis_done, smb1req);
6444 	return;
6445 }
6446 
6447 struct reply_tdis_state {
6448 	struct tevent_queue *wait_queue;
6449 };
6450 
6451 static void reply_tdis_wait_done(struct tevent_req *subreq);
6452 
6453 /****************************************************************************
6454  Async SMB1 tdis.
6455  Note, on failure here we deallocate and return NULL to allow the caller to
6456  SMB1 return an error of ERRnomem immediately.
6457 ****************************************************************************/
6458 
reply_tdis_send(struct smb_request * smb1req)6459 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6460 {
6461 	struct tevent_req *req;
6462 	struct reply_tdis_state *state;
6463 	struct tevent_req *subreq;
6464 	connection_struct *conn = smb1req->conn;
6465 	files_struct *fsp;
6466 
6467 	req = tevent_req_create(smb1req, &state,
6468 			struct reply_tdis_state);
6469 	if (req == NULL) {
6470 		return NULL;
6471 	}
6472 	state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6473 	if (tevent_req_nomem(state->wait_queue, req)) {
6474 		TALLOC_FREE(req);
6475 		return NULL;
6476 	}
6477 
6478 	/*
6479 	 * Make sure that no new request will be able to use this tcon.
6480 	 * This ensures that once all outstanding fsp->aio_requests
6481 	 * on this tcon are done, we are safe to close it.
6482 	 */
6483 	conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6484 
6485 	for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6486 		if (fsp->conn != conn) {
6487 			continue;
6488 		}
6489 		/*
6490 		 * Flag the file as close in progress.
6491 		 * This will prevent any more IO being
6492 		 * done on it. Not strictly needed, but
6493 		 * doesn't hurt to flag it as closing.
6494 		 */
6495 		fsp->closing = true;
6496 
6497 		if (fsp->num_aio_requests > 0) {
6498 			/*
6499 			 * Now wait until all aio requests on this fsp are
6500 			 * finished.
6501 			 *
6502 			 * We don't set a callback, as we just want to block the
6503 			 * wait queue and the talloc_free() of fsp->aio_request
6504 			 * will remove the item from the wait queue.
6505 			 */
6506 			subreq = tevent_queue_wait_send(fsp->aio_requests,
6507 						conn->sconn->ev_ctx,
6508 						state->wait_queue);
6509 			if (tevent_req_nomem(subreq, req)) {
6510 				TALLOC_FREE(req);
6511 				return NULL;
6512 			}
6513 		}
6514 	}
6515 
6516 	/*
6517 	 * Now we add our own waiter to the end of the queue,
6518 	 * this way we get notified when all pending requests are finished
6519 	 * and reply to the outstanding SMB1 request.
6520 	 */
6521 	subreq = tevent_queue_wait_send(state,
6522 				conn->sconn->ev_ctx,
6523 				state->wait_queue);
6524 	if (tevent_req_nomem(subreq, req)) {
6525 		TALLOC_FREE(req);
6526 		return NULL;
6527 	}
6528 
6529 	/*
6530 	 * We're really going async - move the SMB1 request from
6531 	 * a talloc stackframe above us to the sconn talloc-context.
6532 	 * We need this to stick around until the wait_done
6533 	 * callback is invoked.
6534 	 */
6535 	smb1req = talloc_move(smb1req->sconn, &smb1req);
6536 
6537 	tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6538 
6539 	return req;
6540 }
6541 
reply_tdis_wait_done(struct tevent_req * subreq)6542 static void reply_tdis_wait_done(struct tevent_req *subreq)
6543 {
6544 	struct tevent_req *req = tevent_req_callback_data(
6545 		subreq, struct tevent_req);
6546 
6547 	tevent_queue_wait_recv(subreq);
6548 	TALLOC_FREE(subreq);
6549 	tevent_req_done(req);
6550 }
6551 
reply_tdis_recv(struct tevent_req * req)6552 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6553 {
6554 	return tevent_req_simple_recv_ntstatus(req);
6555 }
6556 
reply_tdis_done(struct tevent_req * req)6557 static void reply_tdis_done(struct tevent_req *req)
6558 {
6559 	struct smb_request *smb1req = tevent_req_callback_data(
6560 		req, struct smb_request);
6561 	NTSTATUS status;
6562 	struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6563 	bool ok;
6564 
6565 	/*
6566 	 * Take the profile charge here. Not strictly
6567 	 * correct but better than the other SMB1 async
6568 	 * code that double-charges at the moment.
6569 	 */
6570 	START_PROFILE(SMBtdis);
6571 
6572 	status = reply_tdis_recv(req);
6573 	TALLOC_FREE(req);
6574 	if (!NT_STATUS_IS_OK(status)) {
6575 		TALLOC_FREE(smb1req);
6576 		END_PROFILE(SMBtdis);
6577 		exit_server(__location__ ": reply_tdis_recv failed");
6578 		return;
6579 	}
6580 
6581 	/*
6582 	 * As we've been awoken, we may have changed
6583 	 * directory in the meantime.
6584 	 * reply_tdis() has the DO_CHDIR flag set.
6585 	 */
6586 	ok = chdir_current_service(smb1req->conn);
6587 	if (!ok) {
6588 		reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6589 		smb_request_done(smb1req);
6590 		END_PROFILE(SMBtdis);
6591 	}
6592 
6593 	status = smbXsrv_tcon_disconnect(tcon,
6594 					 smb1req->vuid);
6595 	if (!NT_STATUS_IS_OK(status)) {
6596 		TALLOC_FREE(smb1req);
6597 		END_PROFILE(SMBtdis);
6598 		exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6599 		return;
6600 	}
6601 
6602 	/* smbXsrv_tcon_disconnect frees smb1req->conn. */
6603 	smb1req->conn = NULL;
6604 
6605 	TALLOC_FREE(tcon);
6606 
6607 	reply_outbuf(smb1req, 0, 0);
6608 	/*
6609 	 * The following call is needed to push the
6610 	 * reply data back out the socket after async
6611 	 * return. Plus it frees smb1req.
6612 	 */
6613 	smb_request_done(smb1req);
6614 	END_PROFILE(SMBtdis);
6615 }
6616 
6617 /****************************************************************************
6618  Reply to a echo.
6619  conn POINTER CAN BE NULL HERE !
6620 ****************************************************************************/
6621 
reply_echo(struct smb_request * req)6622 void reply_echo(struct smb_request *req)
6623 {
6624 	connection_struct *conn = req->conn;
6625 	struct smb_perfcount_data local_pcd;
6626 	struct smb_perfcount_data *cur_pcd;
6627 	int smb_reverb;
6628 	int seq_num;
6629 
6630 	START_PROFILE(SMBecho);
6631 
6632 	smb_init_perfcount_data(&local_pcd);
6633 
6634 	if (req->wct < 1) {
6635 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6636 		END_PROFILE(SMBecho);
6637 		return;
6638 	}
6639 
6640 	smb_reverb = SVAL(req->vwv+0, 0);
6641 
6642 	reply_outbuf(req, 1, req->buflen);
6643 
6644 	/* copy any incoming data back out */
6645 	if (req->buflen > 0) {
6646 		memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6647 	}
6648 
6649 	if (smb_reverb > 100) {
6650 		DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6651 		smb_reverb = 100;
6652 	}
6653 
6654 	for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6655 
6656 		/* this makes sure we catch the request pcd */
6657 		if (seq_num == smb_reverb) {
6658 			cur_pcd = &req->pcd;
6659 		} else {
6660 			SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6661 			cur_pcd = &local_pcd;
6662 		}
6663 
6664 		SSVAL(req->outbuf,smb_vwv0,seq_num);
6665 
6666 		show_msg((char *)req->outbuf);
6667 		if (!srv_send_smb(req->xconn,
6668 				(char *)req->outbuf,
6669 				true, req->seqnum+1,
6670 				IS_CONN_ENCRYPTED(conn)||req->encrypted,
6671 				cur_pcd))
6672 			exit_server_cleanly("reply_echo: srv_send_smb failed.");
6673 	}
6674 
6675 	DEBUG(3,("echo %d times\n", smb_reverb));
6676 
6677 	TALLOC_FREE(req->outbuf);
6678 
6679 	END_PROFILE(SMBecho);
6680 	return;
6681 }
6682 
6683 /****************************************************************************
6684  Reply to a printopen.
6685 ****************************************************************************/
6686 
reply_printopen(struct smb_request * req)6687 void reply_printopen(struct smb_request *req)
6688 {
6689 	connection_struct *conn = req->conn;
6690 	files_struct *fsp;
6691 	NTSTATUS status;
6692 
6693 	START_PROFILE(SMBsplopen);
6694 
6695 	if (req->wct < 2) {
6696 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6697 		END_PROFILE(SMBsplopen);
6698 		return;
6699 	}
6700 
6701 	if (!CAN_PRINT(conn)) {
6702 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6703 		END_PROFILE(SMBsplopen);
6704 		return;
6705 	}
6706 
6707 	status = file_new(req, conn, &fsp);
6708 	if(!NT_STATUS_IS_OK(status)) {
6709 		reply_nterror(req, status);
6710 		END_PROFILE(SMBsplopen);
6711 		return;
6712 	}
6713 
6714 	/* Open for exclusive use, write only. */
6715 	status = print_spool_open(fsp, NULL, req->vuid);
6716 
6717 	if (!NT_STATUS_IS_OK(status)) {
6718 		file_free(req, fsp);
6719 		reply_nterror(req, status);
6720 		END_PROFILE(SMBsplopen);
6721 		return;
6722 	}
6723 
6724 	reply_outbuf(req, 1, 0);
6725 	SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6726 
6727 	DEBUG(3,("openprint fd=%d %s\n",
6728 		 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6729 
6730 	END_PROFILE(SMBsplopen);
6731 	return;
6732 }
6733 
6734 /****************************************************************************
6735  Reply to a printclose.
6736 ****************************************************************************/
6737 
reply_printclose(struct smb_request * req)6738 void reply_printclose(struct smb_request *req)
6739 {
6740 	connection_struct *conn = req->conn;
6741 	files_struct *fsp;
6742 	NTSTATUS status;
6743 
6744 	START_PROFILE(SMBsplclose);
6745 
6746 	if (req->wct < 1) {
6747 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6748 		END_PROFILE(SMBsplclose);
6749 		return;
6750 	}
6751 
6752 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6753 
6754 	if (!check_fsp(conn, req, fsp)) {
6755 		END_PROFILE(SMBsplclose);
6756                 return;
6757         }
6758 
6759 	if (!CAN_PRINT(conn)) {
6760 		reply_force_doserror(req, ERRSRV, ERRerror);
6761 		END_PROFILE(SMBsplclose);
6762 		return;
6763 	}
6764 
6765 	DEBUG(3,("printclose fd=%d %s\n",
6766 		 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6767 
6768 	status = close_file(req, fsp, NORMAL_CLOSE);
6769 
6770 	if(!NT_STATUS_IS_OK(status)) {
6771 		reply_nterror(req, status);
6772 		END_PROFILE(SMBsplclose);
6773 		return;
6774 	}
6775 
6776 	reply_outbuf(req, 0, 0);
6777 
6778 	END_PROFILE(SMBsplclose);
6779 	return;
6780 }
6781 
6782 /****************************************************************************
6783  Reply to a printqueue.
6784 ****************************************************************************/
6785 
reply_printqueue(struct smb_request * req)6786 void reply_printqueue(struct smb_request *req)
6787 {
6788 	const struct loadparm_substitution *lp_sub =
6789 		loadparm_s3_global_substitution();
6790 	connection_struct *conn = req->conn;
6791 	int max_count;
6792 	int start_index;
6793 
6794 	START_PROFILE(SMBsplretq);
6795 
6796 	if (req->wct < 2) {
6797 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6798 		END_PROFILE(SMBsplretq);
6799 		return;
6800 	}
6801 
6802 	max_count = SVAL(req->vwv+0, 0);
6803 	start_index = SVAL(req->vwv+1, 0);
6804 
6805 	/* we used to allow the client to get the cnum wrong, but that
6806 	   is really quite gross and only worked when there was only
6807 	   one printer - I think we should now only accept it if they
6808 	   get it right (tridge) */
6809 	if (!CAN_PRINT(conn)) {
6810 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6811 		END_PROFILE(SMBsplretq);
6812 		return;
6813 	}
6814 
6815 	reply_outbuf(req, 2, 3);
6816 	SSVAL(req->outbuf,smb_vwv0,0);
6817 	SSVAL(req->outbuf,smb_vwv1,0);
6818 	SCVAL(smb_buf(req->outbuf),0,1);
6819 	SSVAL(smb_buf(req->outbuf),1,0);
6820 
6821 	DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6822 		 start_index, max_count));
6823 
6824 	{
6825 		TALLOC_CTX *mem_ctx = talloc_tos();
6826 		NTSTATUS status;
6827 		WERROR werr;
6828 		const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6829 		struct rpc_pipe_client *cli = NULL;
6830 		struct dcerpc_binding_handle *b = NULL;
6831 		struct policy_handle handle;
6832 		struct spoolss_DevmodeContainer devmode_ctr;
6833 		union spoolss_JobInfo *info;
6834 		uint32_t count;
6835 		uint32_t num_to_get;
6836 		uint32_t first;
6837 		uint32_t i;
6838 
6839 		ZERO_STRUCT(handle);
6840 
6841 		status = rpc_pipe_open_interface(mem_ctx,
6842 						 &ndr_table_spoolss,
6843 						 conn->session_info,
6844 						 conn->sconn->remote_address,
6845 						 conn->sconn->local_address,
6846 						 conn->sconn->msg_ctx,
6847 						 &cli);
6848 		if (!NT_STATUS_IS_OK(status)) {
6849 			DEBUG(0, ("reply_printqueue: "
6850 				  "could not connect to spoolss: %s\n",
6851 				  nt_errstr(status)));
6852 			reply_nterror(req, status);
6853 			goto out;
6854 		}
6855 		b = cli->binding_handle;
6856 
6857 		ZERO_STRUCT(devmode_ctr);
6858 
6859 		status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6860 						sharename,
6861 						NULL, devmode_ctr,
6862 						SEC_FLAG_MAXIMUM_ALLOWED,
6863 						&handle,
6864 						&werr);
6865 		if (!NT_STATUS_IS_OK(status)) {
6866 			reply_nterror(req, status);
6867 			goto out;
6868 		}
6869 		if (!W_ERROR_IS_OK(werr)) {
6870 			reply_nterror(req, werror_to_ntstatus(werr));
6871 			goto out;
6872 		}
6873 
6874 		werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6875 					       &handle,
6876 					       0, /* firstjob */
6877 					       0xff, /* numjobs */
6878 					       2, /* level */
6879 					       0, /* offered */
6880 					       &count,
6881 					       &info);
6882 		if (!W_ERROR_IS_OK(werr)) {
6883 			reply_nterror(req, werror_to_ntstatus(werr));
6884 			goto out;
6885 		}
6886 
6887 		if (max_count > 0) {
6888 			first = start_index;
6889 		} else {
6890 			first = start_index + max_count + 1;
6891 		}
6892 
6893 		if (first >= count) {
6894 			num_to_get = first;
6895 		} else {
6896 			num_to_get = first + MIN(ABS(max_count), count - first);
6897 		}
6898 
6899 		for (i = first; i < num_to_get; i++) {
6900 			char blob[28];
6901 			char *p = blob;
6902 			time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6903 			int qstatus;
6904 			size_t len = 0;
6905 			uint16_t qrapjobid = pjobid_to_rap(sharename,
6906 							info[i].info2.job_id);
6907 
6908 			if (info[i].info2.status == JOB_STATUS_PRINTING) {
6909 				qstatus = 2;
6910 			} else {
6911 				qstatus = 3;
6912 			}
6913 
6914 			srv_put_dos_date2(p, 0, qtime);
6915 			SCVAL(p, 4, qstatus);
6916 			SSVAL(p, 5, qrapjobid);
6917 			SIVAL(p, 7, info[i].info2.size);
6918 			SCVAL(p, 11, 0);
6919 			status = srvstr_push(blob, req->flags2, p+12,
6920 				    info[i].info2.notify_name, 16, STR_ASCII, &len);
6921 			if (!NT_STATUS_IS_OK(status)) {
6922 				reply_nterror(req, status);
6923 				goto out;
6924 			}
6925 			if (message_push_blob(
6926 				    &req->outbuf,
6927 				    data_blob_const(
6928 					    blob, sizeof(blob))) == -1) {
6929 				reply_nterror(req, NT_STATUS_NO_MEMORY);
6930 				goto out;
6931 			}
6932 		}
6933 
6934 		if (count > 0) {
6935 			SSVAL(req->outbuf,smb_vwv0,count);
6936 			SSVAL(req->outbuf,smb_vwv1,
6937 			      (max_count>0?first+count:first-1));
6938 			SCVAL(smb_buf(req->outbuf),0,1);
6939 			SSVAL(smb_buf(req->outbuf),1,28*count);
6940 		}
6941 
6942 
6943 		DEBUG(3, ("%u entries returned in queue\n",
6944 			  (unsigned)count));
6945 
6946 out:
6947 		if (b && is_valid_policy_hnd(&handle)) {
6948 			dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6949 		}
6950 
6951 	}
6952 
6953 	END_PROFILE(SMBsplretq);
6954 	return;
6955 }
6956 
6957 /****************************************************************************
6958  Reply to a printwrite.
6959 ****************************************************************************/
6960 
reply_printwrite(struct smb_request * req)6961 void reply_printwrite(struct smb_request *req)
6962 {
6963 	connection_struct *conn = req->conn;
6964 	int numtowrite;
6965 	const char *data;
6966 	files_struct *fsp;
6967 
6968 	START_PROFILE(SMBsplwr);
6969 
6970 	if (req->wct < 1) {
6971 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6972 		END_PROFILE(SMBsplwr);
6973 		return;
6974 	}
6975 
6976 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6977 
6978 	if (!check_fsp(conn, req, fsp)) {
6979 		END_PROFILE(SMBsplwr);
6980                 return;
6981         }
6982 
6983 	if (!fsp->print_file) {
6984 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6985 		END_PROFILE(SMBsplwr);
6986 		return;
6987 	}
6988 
6989 	if (!CHECK_WRITE(fsp)) {
6990 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6991 		END_PROFILE(SMBsplwr);
6992 		return;
6993 	}
6994 
6995 	numtowrite = SVAL(req->buf, 1);
6996 
6997 	/*
6998 	 * This already protects us against CVE-2017-12163.
6999 	 */
7000 	if (req->buflen < numtowrite + 3) {
7001 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7002 		END_PROFILE(SMBsplwr);
7003 		return;
7004 	}
7005 
7006 	data = (const char *)req->buf + 3;
7007 
7008 	if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7009 		reply_nterror(req, map_nt_error_from_unix(errno));
7010 		END_PROFILE(SMBsplwr);
7011 		return;
7012 	}
7013 
7014 	DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7015 
7016 	END_PROFILE(SMBsplwr);
7017 	return;
7018 }
7019 
7020 /****************************************************************************
7021  Reply to a mkdir.
7022 ****************************************************************************/
7023 
reply_mkdir(struct smb_request * req)7024 void reply_mkdir(struct smb_request *req)
7025 {
7026 	connection_struct *conn = req->conn;
7027 	struct smb_filename *smb_dname = NULL;
7028 	char *directory = NULL;
7029 	NTSTATUS status;
7030 	uint32_t ucf_flags;
7031 	TALLOC_CTX *ctx = talloc_tos();
7032 
7033 	START_PROFILE(SMBmkdir);
7034 
7035 	srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7036 			    STR_TERMINATE, &status);
7037 	if (!NT_STATUS_IS_OK(status)) {
7038 		reply_nterror(req, status);
7039 		goto out;
7040 	}
7041 
7042 	ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7043 	status = filename_convert(ctx, conn,
7044 				 directory,
7045 				 ucf_flags,
7046 				 NULL,
7047 				 NULL,
7048 				 &smb_dname);
7049 	if (!NT_STATUS_IS_OK(status)) {
7050 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7051 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7052 					ERRSRV, ERRbadpath);
7053 			goto out;
7054 		}
7055 		reply_nterror(req, status);
7056 		goto out;
7057 	}
7058 
7059 	status = create_directory(conn, req, smb_dname);
7060 
7061 	DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7062 
7063 	if (!NT_STATUS_IS_OK(status)) {
7064 
7065 		if (!use_nt_status()
7066 		    && NT_STATUS_EQUAL(status,
7067 				       NT_STATUS_OBJECT_NAME_COLLISION)) {
7068 			/*
7069 			 * Yes, in the DOS error code case we get a
7070 			 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7071 			 * samba4 torture test.
7072 			 */
7073 			status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7074 		}
7075 
7076 		reply_nterror(req, status);
7077 		goto out;
7078 	}
7079 
7080 	reply_outbuf(req, 0, 0);
7081 
7082 	DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7083  out:
7084 	TALLOC_FREE(smb_dname);
7085 	END_PROFILE(SMBmkdir);
7086 	return;
7087 }
7088 
7089 /****************************************************************************
7090  Reply to a rmdir.
7091 ****************************************************************************/
7092 
reply_rmdir(struct smb_request * req)7093 void reply_rmdir(struct smb_request *req)
7094 {
7095 	connection_struct *conn = req->conn;
7096 	struct smb_filename *smb_dname = NULL;
7097 	char *directory = NULL;
7098 	NTSTATUS status;
7099 	TALLOC_CTX *ctx = talloc_tos();
7100 	files_struct *fsp = NULL;
7101 	int info = 0;
7102 	uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7103 
7104 	START_PROFILE(SMBrmdir);
7105 
7106 	srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7107 			    STR_TERMINATE, &status);
7108 	if (!NT_STATUS_IS_OK(status)) {
7109 		reply_nterror(req, status);
7110 		goto out;
7111 	}
7112 
7113 	status = filename_convert(ctx, conn,
7114 				 directory,
7115 				 ucf_flags,
7116 				 NULL,
7117 				 NULL,
7118 				 &smb_dname);
7119 	if (!NT_STATUS_IS_OK(status)) {
7120 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7121 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7122 					ERRSRV, ERRbadpath);
7123 			goto out;
7124 		}
7125 		reply_nterror(req, status);
7126 		goto out;
7127 	}
7128 
7129 	if (is_ntfs_stream_smb_fname(smb_dname)) {
7130 		reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7131 		goto out;
7132 	}
7133 
7134 	status = SMB_VFS_CREATE_FILE(
7135 		conn,                                   /* conn */
7136 		req,                                    /* req */
7137 		0,                                      /* root_dir_fid */
7138 		smb_dname,                              /* fname */
7139 		DELETE_ACCESS,                          /* access_mask */
7140 		(FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7141 			FILE_SHARE_DELETE),
7142 		FILE_OPEN,                              /* create_disposition*/
7143 		FILE_DIRECTORY_FILE,                    /* create_options */
7144 		FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
7145 		0,                                      /* oplock_request */
7146 		NULL,					/* lease */
7147 		0,                                      /* allocation_size */
7148 		0,					/* private_flags */
7149 		NULL,                                   /* sd */
7150 		NULL,                                   /* ea_list */
7151 		&fsp,                                   /* result */
7152 		&info,                                  /* pinfo */
7153 		NULL, NULL);				/* create context */
7154 
7155 	if (!NT_STATUS_IS_OK(status)) {
7156 		if (open_was_deferred(req->xconn, req->mid)) {
7157 			/* We have re-scheduled this call. */
7158 			goto out;
7159 		}
7160 		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7161 			bool ok = defer_smb1_sharing_violation(req);
7162 			if (ok) {
7163 				goto out;
7164 			}
7165 		}
7166 		reply_nterror(req, status);
7167 		goto out;
7168 	}
7169 
7170 	status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7171 	if (!NT_STATUS_IS_OK(status)) {
7172 		close_file(req, fsp, ERROR_CLOSE);
7173 		reply_nterror(req, status);
7174 		goto out;
7175 	}
7176 
7177 	if (!set_delete_on_close(fsp, true,
7178 			conn->session_info->security_token,
7179 			conn->session_info->unix_token)) {
7180 		close_file(req, fsp, ERROR_CLOSE);
7181 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7182 		goto out;
7183 	}
7184 
7185 	status = close_file(req, fsp, NORMAL_CLOSE);
7186 	if (!NT_STATUS_IS_OK(status)) {
7187 		reply_nterror(req, status);
7188 	} else {
7189 		reply_outbuf(req, 0, 0);
7190 	}
7191 
7192 	DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7193  out:
7194 	TALLOC_FREE(smb_dname);
7195 	END_PROFILE(SMBrmdir);
7196 	return;
7197 }
7198 
7199 /*******************************************************************
7200  Resolve wildcards in a filename rename.
7201 ********************************************************************/
7202 
resolve_wildcards(TALLOC_CTX * ctx,const char * name1,const char * name2,char ** pp_newname)7203 static bool resolve_wildcards(TALLOC_CTX *ctx,
7204 				const char *name1,
7205 				const char *name2,
7206 				char **pp_newname)
7207 {
7208 	char *name2_copy = NULL;
7209 	char *root1 = NULL;
7210 	char *root2 = NULL;
7211 	char *ext1 = NULL;
7212 	char *ext2 = NULL;
7213 	char *p,*p2, *pname1, *pname2;
7214 
7215 	name2_copy = talloc_strdup(ctx, name2);
7216 	if (!name2_copy) {
7217 		return False;
7218 	}
7219 
7220 	pname1 = strrchr_m(name1,'/');
7221 	pname2 = strrchr_m(name2_copy,'/');
7222 
7223 	if (!pname1 || !pname2) {
7224 		return False;
7225 	}
7226 
7227 	/* Truncate the copy of name2 at the last '/' */
7228 	*pname2 = '\0';
7229 
7230 	/* Now go past the '/' */
7231 	pname1++;
7232 	pname2++;
7233 
7234 	root1 = talloc_strdup(ctx, pname1);
7235 	root2 = talloc_strdup(ctx, pname2);
7236 
7237 	if (!root1 || !root2) {
7238 		return False;
7239 	}
7240 
7241 	p = strrchr_m(root1,'.');
7242 	if (p) {
7243 		*p = 0;
7244 		ext1 = talloc_strdup(ctx, p+1);
7245 	} else {
7246 		ext1 = talloc_strdup(ctx, "");
7247 	}
7248 	p = strrchr_m(root2,'.');
7249 	if (p) {
7250 		*p = 0;
7251 		ext2 = talloc_strdup(ctx, p+1);
7252 	} else {
7253 		ext2 = talloc_strdup(ctx, "");
7254 	}
7255 
7256 	if (!ext1 || !ext2) {
7257 		return False;
7258 	}
7259 
7260 	p = root1;
7261 	p2 = root2;
7262 	while (*p2) {
7263 		if (*p2 == '?') {
7264 			/* Hmmm. Should this be mb-aware ? */
7265 			*p2 = *p;
7266 			p2++;
7267 		} else if (*p2 == '*') {
7268 			*p2 = '\0';
7269 			root2 = talloc_asprintf(ctx, "%s%s",
7270 						root2,
7271 						p);
7272 			if (!root2) {
7273 				return False;
7274 			}
7275 			break;
7276 		} else {
7277 			p2++;
7278 		}
7279 		if (*p) {
7280 			p++;
7281 		}
7282 	}
7283 
7284 	p = ext1;
7285 	p2 = ext2;
7286 	while (*p2) {
7287 		if (*p2 == '?') {
7288 			/* Hmmm. Should this be mb-aware ? */
7289 			*p2 = *p;
7290 			p2++;
7291 		} else if (*p2 == '*') {
7292 			*p2 = '\0';
7293 			ext2 = talloc_asprintf(ctx, "%s%s",
7294 						ext2,
7295 						p);
7296 			if (!ext2) {
7297 				return False;
7298 			}
7299 			break;
7300 		} else {
7301 			p2++;
7302 		}
7303 		if (*p) {
7304 			p++;
7305 		}
7306 	}
7307 
7308 	if (*ext2) {
7309 		*pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7310 				name2_copy,
7311 				root2,
7312 				ext2);
7313 	} else {
7314 		*pp_newname = talloc_asprintf(ctx, "%s/%s",
7315 				name2_copy,
7316 				root2);
7317 	}
7318 
7319 	if (!*pp_newname) {
7320 		return False;
7321 	}
7322 
7323 	return True;
7324 }
7325 
7326 /****************************************************************************
7327  Ensure open files have their names updated. Updated to notify other smbd's
7328  asynchronously.
7329 ****************************************************************************/
7330 
rename_open_files(connection_struct * conn,struct share_mode_lock * lck,struct file_id id,uint32_t orig_name_hash,const struct smb_filename * smb_fname_dst)7331 static void rename_open_files(connection_struct *conn,
7332 			      struct share_mode_lock *lck,
7333 			      struct file_id id,
7334 			      uint32_t orig_name_hash,
7335 			      const struct smb_filename *smb_fname_dst)
7336 {
7337 	files_struct *fsp;
7338 	bool did_rename = False;
7339 	NTSTATUS status;
7340 	uint32_t new_name_hash = 0;
7341 
7342 	for(fsp = file_find_di_first(conn->sconn, id); fsp;
7343 	    fsp = file_find_di_next(fsp)) {
7344 		struct file_id_buf idbuf;
7345 		/* fsp_name is a relative path under the fsp. To change this for other
7346 		   sharepaths we need to manipulate relative paths. */
7347 		/* TODO - create the absolute path and manipulate the newname
7348 		   relative to the sharepath. */
7349 		if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7350 			continue;
7351 		}
7352 		if (fsp->name_hash != orig_name_hash) {
7353 			continue;
7354 		}
7355 		DBG_DEBUG("renaming file %s "
7356 			  "(file_id %s) from %s -> %s\n",
7357 			  fsp_fnum_dbg(fsp),
7358 			  file_id_str_buf(fsp->file_id, &idbuf),
7359 			  fsp_str_dbg(fsp),
7360 			  smb_fname_str_dbg(smb_fname_dst));
7361 
7362 		status = fsp_set_smb_fname(fsp, smb_fname_dst);
7363 		if (NT_STATUS_IS_OK(status)) {
7364 			did_rename = True;
7365 			new_name_hash = fsp->name_hash;
7366 		}
7367 	}
7368 
7369 	if (!did_rename) {
7370 		struct file_id_buf idbuf;
7371 		DBG_DEBUG("no open files on file_id %s "
7372 			  "for %s\n",
7373 			  file_id_str_buf(id, &idbuf),
7374 			  smb_fname_str_dbg(smb_fname_dst));
7375 	}
7376 
7377 	/* Send messages to all smbd's (not ourself) that the name has changed. */
7378 	rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7379 			      orig_name_hash, new_name_hash,
7380 			      smb_fname_dst);
7381 
7382 }
7383 
7384 /****************************************************************************
7385  We need to check if the source path is a parent directory of the destination
7386  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7387  refuse the rename with a sharing violation. Under UNIX the above call can
7388  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7389  probably need to check that the client is a Windows one before disallowing
7390  this as a UNIX client (one with UNIX extensions) can know the source is a
7391  symlink and make this decision intelligently. Found by an excellent bug
7392  report from <AndyLiebman@aol.com>.
7393 ****************************************************************************/
7394 
rename_path_prefix_equal(const struct smb_filename * smb_fname_src,const struct smb_filename * smb_fname_dst)7395 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7396 				     const struct smb_filename *smb_fname_dst)
7397 {
7398 	const char *psrc = smb_fname_src->base_name;
7399 	const char *pdst = smb_fname_dst->base_name;
7400 	size_t slen;
7401 
7402 	if (psrc[0] == '.' && psrc[1] == '/') {
7403 		psrc += 2;
7404 	}
7405 	if (pdst[0] == '.' && pdst[1] == '/') {
7406 		pdst += 2;
7407 	}
7408 	if ((slen = strlen(psrc)) > strlen(pdst)) {
7409 		return False;
7410 	}
7411 	return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7412 }
7413 
7414 /*
7415  * Do the notify calls from a rename
7416  */
7417 
notify_rename(connection_struct * conn,bool is_dir,const struct smb_filename * smb_fname_src,const struct smb_filename * smb_fname_dst)7418 static void notify_rename(connection_struct *conn, bool is_dir,
7419 			  const struct smb_filename *smb_fname_src,
7420 			  const struct smb_filename *smb_fname_dst)
7421 {
7422 	char *parent_dir_src = NULL;
7423 	char *parent_dir_dst = NULL;
7424 	uint32_t mask;
7425 
7426 	mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7427 		: FILE_NOTIFY_CHANGE_FILE_NAME;
7428 
7429 	if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7430 			    &parent_dir_src, NULL) ||
7431 	    !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7432 			    &parent_dir_dst, NULL)) {
7433 		goto out;
7434 	}
7435 
7436 	if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7437 		notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7438 			     smb_fname_src->base_name);
7439 		notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7440 			     smb_fname_dst->base_name);
7441 	}
7442 	else {
7443 		notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7444 			     smb_fname_src->base_name);
7445 		notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7446 			     smb_fname_dst->base_name);
7447 	}
7448 
7449 	/* this is a strange one. w2k3 gives an additional event for
7450 	   CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7451 	   files, but not directories */
7452 	if (!is_dir) {
7453 		notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7454 			     FILE_NOTIFY_CHANGE_ATTRIBUTES
7455 			     |FILE_NOTIFY_CHANGE_CREATION,
7456 			     smb_fname_dst->base_name);
7457 	}
7458  out:
7459 	TALLOC_FREE(parent_dir_src);
7460 	TALLOC_FREE(parent_dir_dst);
7461 }
7462 
7463 /****************************************************************************
7464  Returns an error if the parent directory for a filename is open in an
7465  incompatible way.
7466 ****************************************************************************/
7467 
parent_dirname_compatible_open(connection_struct * conn,const struct smb_filename * smb_fname_dst_in)7468 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7469 					const struct smb_filename *smb_fname_dst_in)
7470 {
7471 	char *parent_dir = NULL;
7472 	struct smb_filename smb_fname_parent;
7473 	struct file_id id;
7474 	files_struct *fsp = NULL;
7475 	int ret;
7476 
7477 	if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
7478 			&parent_dir, NULL)) {
7479 		return NT_STATUS_NO_MEMORY;
7480 	}
7481 	ZERO_STRUCT(smb_fname_parent);
7482 	smb_fname_parent.base_name = parent_dir;
7483 
7484 	ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
7485 	if (ret == -1) {
7486 		return map_nt_error_from_unix(errno);
7487 	}
7488 
7489 	/*
7490 	 * We're only checking on this smbd here, mostly good
7491 	 * enough.. and will pass tests.
7492 	 */
7493 
7494 	id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
7495 	for (fsp = file_find_di_first(conn->sconn, id); fsp;
7496 			fsp = file_find_di_next(fsp)) {
7497 		if (fsp->access_mask & DELETE_ACCESS) {
7498 			return NT_STATUS_SHARING_VIOLATION;
7499                 }
7500         }
7501 	return NT_STATUS_OK;
7502 }
7503 
7504 /****************************************************************************
7505  Rename an open file - given an fsp.
7506 ****************************************************************************/
7507 
rename_internals_fsp(connection_struct * conn,files_struct * fsp,const struct smb_filename * smb_fname_dst_in,uint32_t attrs,bool replace_if_exists)7508 NTSTATUS rename_internals_fsp(connection_struct *conn,
7509 			files_struct *fsp,
7510 			const struct smb_filename *smb_fname_dst_in,
7511 			uint32_t attrs,
7512 			bool replace_if_exists)
7513 {
7514 	TALLOC_CTX *ctx = talloc_tos();
7515 	struct smb_filename *smb_fname_dst = NULL;
7516 	NTSTATUS status = NT_STATUS_OK;
7517 	struct share_mode_lock *lck = NULL;
7518 	uint32_t access_mask = SEC_DIR_ADD_FILE;
7519 	bool dst_exists, old_is_stream, new_is_stream;
7520 	int ret;
7521 
7522 	status = check_name(conn, smb_fname_dst_in);
7523 	if (!NT_STATUS_IS_OK(status)) {
7524 		return status;
7525 	}
7526 
7527 	status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7528 	if (!NT_STATUS_IS_OK(status)) {
7529 		return status;
7530 	}
7531 
7532 	if (file_has_open_streams(fsp)) {
7533 		return NT_STATUS_ACCESS_DENIED;
7534 	}
7535 
7536 	/* Make a copy of the dst smb_fname structs */
7537 
7538 	smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7539 	if (smb_fname_dst == NULL) {
7540 		status = NT_STATUS_NO_MEMORY;
7541 		goto out;
7542 	}
7543 
7544 	/*
7545 	 * Check for special case with case preserving and not
7546 	 * case sensitive. If the new last component differs from the original
7547 	 * last component only by case, then we should allow
7548 	 * the rename (user is trying to change the case of the
7549 	 * filename).
7550 	 */
7551 	if (!conn->case_sensitive && conn->case_preserve &&
7552 	    strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7553 	    strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7554 		char *fname_dst_parent = NULL;
7555 		const char *fname_dst_lcomp = NULL;
7556 		char *orig_lcomp_path = NULL;
7557 		char *orig_lcomp_stream = NULL;
7558 		bool ok = true;
7559 
7560 		/*
7561 		 * Split off the last component of the processed
7562 		 * destination name. We will compare this to
7563 		 * the split components of smb_fname_dst->original_lcomp.
7564 		 */
7565 		if (!parent_dirname(ctx,
7566 				smb_fname_dst->base_name,
7567 				&fname_dst_parent,
7568 				&fname_dst_lcomp)) {
7569 			status = NT_STATUS_NO_MEMORY;
7570 			goto out;
7571 		}
7572 
7573 		/*
7574 		 * The original_lcomp component contains
7575 		 * the last_component of the path + stream
7576 		 * name (if a stream exists).
7577 		 *
7578 		 * Split off the stream name so we
7579 		 * can check them separately.
7580 		 */
7581 
7582 		if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7583 			/* POSIX - no stream component. */
7584 			orig_lcomp_path = talloc_strdup(ctx,
7585 						smb_fname_dst->original_lcomp);
7586 			if (orig_lcomp_path == NULL) {
7587 				ok = false;
7588 			}
7589 		} else {
7590 			ok = split_stream_filename(ctx,
7591 					smb_fname_dst->original_lcomp,
7592 					&orig_lcomp_path,
7593 					&orig_lcomp_stream);
7594 		}
7595 
7596 		if (!ok) {
7597 			TALLOC_FREE(fname_dst_parent);
7598 			status = NT_STATUS_NO_MEMORY;
7599 			goto out;
7600 		}
7601 
7602 		/* If the base names only differ by case, use original. */
7603 		if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7604 			char *tmp;
7605 			/*
7606 			 * Replace the modified last component with the
7607 			 * original.
7608 			 */
7609 			if (!ISDOT(fname_dst_parent)) {
7610 				tmp = talloc_asprintf(smb_fname_dst,
7611 					"%s/%s",
7612 					fname_dst_parent,
7613 					orig_lcomp_path);
7614 			} else {
7615 				tmp = talloc_strdup(smb_fname_dst,
7616 					orig_lcomp_path);
7617 			}
7618 			if (tmp == NULL) {
7619 				status = NT_STATUS_NO_MEMORY;
7620 				TALLOC_FREE(fname_dst_parent);
7621 				TALLOC_FREE(orig_lcomp_path);
7622 				TALLOC_FREE(orig_lcomp_stream);
7623 				goto out;
7624 			}
7625 			TALLOC_FREE(smb_fname_dst->base_name);
7626 			smb_fname_dst->base_name = tmp;
7627 		}
7628 
7629 		/* If the stream_names only differ by case, use original. */
7630 		if(!strcsequal(smb_fname_dst->stream_name,
7631 			       orig_lcomp_stream)) {
7632 			/* Use the original stream. */
7633 			char *tmp = talloc_strdup(smb_fname_dst,
7634 					    orig_lcomp_stream);
7635 			if (tmp == NULL) {
7636 				status = NT_STATUS_NO_MEMORY;
7637 				TALLOC_FREE(fname_dst_parent);
7638 				TALLOC_FREE(orig_lcomp_path);
7639 				TALLOC_FREE(orig_lcomp_stream);
7640 				goto out;
7641 			}
7642 			TALLOC_FREE(smb_fname_dst->stream_name);
7643 			smb_fname_dst->stream_name = tmp;
7644 		}
7645 		TALLOC_FREE(fname_dst_parent);
7646 		TALLOC_FREE(orig_lcomp_path);
7647 		TALLOC_FREE(orig_lcomp_stream);
7648 	}
7649 
7650 	/*
7651 	 * If the src and dest names are identical - including case,
7652 	 * don't do the rename, just return success.
7653 	 */
7654 
7655 	if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7656 	    strcsequal(fsp->fsp_name->stream_name,
7657 		       smb_fname_dst->stream_name)) {
7658 		DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7659 			  "- returning success\n",
7660 			  smb_fname_str_dbg(smb_fname_dst)));
7661 		status = NT_STATUS_OK;
7662 		goto out;
7663 	}
7664 
7665 	old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7666 	new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7667 
7668 	/* Return the correct error code if both names aren't streams. */
7669 	if (!old_is_stream && new_is_stream) {
7670 		status = NT_STATUS_OBJECT_NAME_INVALID;
7671 		goto out;
7672 	}
7673 
7674 	if (old_is_stream && !new_is_stream) {
7675 		status = NT_STATUS_INVALID_PARAMETER;
7676 		goto out;
7677 	}
7678 
7679 	dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7680 
7681 	if(!replace_if_exists && dst_exists) {
7682 		DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7683 			  "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7684 			  smb_fname_str_dbg(smb_fname_dst)));
7685 		status = NT_STATUS_OBJECT_NAME_COLLISION;
7686 		goto out;
7687 	}
7688 
7689 	if (dst_exists) {
7690 		struct file_id fileid = vfs_file_id_from_sbuf(conn,
7691 		    &smb_fname_dst->st);
7692 		files_struct *dst_fsp = file_find_di_first(conn->sconn,
7693 							   fileid);
7694 		/* The file can be open when renaming a stream */
7695 		if (dst_fsp && !new_is_stream) {
7696 			DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7697 			status = NT_STATUS_ACCESS_DENIED;
7698 			goto out;
7699 		}
7700 	}
7701 
7702 	/* Ensure we have a valid stat struct for the source. */
7703 	status = vfs_stat_fsp(fsp);
7704 	if (!NT_STATUS_IS_OK(status)) {
7705 		goto out;
7706 	}
7707 
7708 	status = can_rename(conn, fsp, attrs);
7709 
7710 	if (!NT_STATUS_IS_OK(status)) {
7711 		DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7712 			  nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7713 			  smb_fname_str_dbg(smb_fname_dst)));
7714 		if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7715 			status = NT_STATUS_ACCESS_DENIED;
7716 		goto out;
7717 	}
7718 
7719 	if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7720 		status = NT_STATUS_ACCESS_DENIED;
7721 		goto out;
7722 	}
7723 
7724 	/* Do we have rights to move into the destination ? */
7725 	if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7726 		/* We're moving a directory. */
7727 		access_mask = SEC_DIR_ADD_SUBDIR;
7728 	}
7729 	status = check_parent_access(conn,
7730 				smb_fname_dst,
7731 				access_mask);
7732 	if (!NT_STATUS_IS_OK(status)) {
7733 		DBG_INFO("check_parent_access on "
7734 			"dst %s returned %s\n",
7735 			smb_fname_str_dbg(smb_fname_dst),
7736 			nt_errstr(status));
7737 		goto out;
7738 	}
7739 
7740 	lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7741 
7742 	/*
7743 	 * We have the file open ourselves, so not being able to get the
7744 	 * corresponding share mode lock is a fatal error.
7745 	 */
7746 
7747 	SMB_ASSERT(lck != NULL);
7748 
7749 	ret = SMB_VFS_RENAMEAT(conn,
7750 			conn->cwd_fsp,
7751 			fsp->fsp_name,
7752 			conn->cwd_fsp,
7753 			smb_fname_dst);
7754 	if (ret == 0) {
7755 		uint32_t create_options = fsp->fh->private_options;
7756 
7757 		DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7758 			  "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7759 			  smb_fname_str_dbg(smb_fname_dst)));
7760 
7761 		if (!fsp->is_directory &&
7762 		    !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7763 		    (lp_map_archive(SNUM(conn)) ||
7764 		    lp_store_dos_attributes(SNUM(conn)))) {
7765 			/* We must set the archive bit on the newly
7766 			   renamed file. */
7767 			if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7768 				uint32_t old_dosmode = dos_mode(conn,
7769 							smb_fname_dst);
7770 				file_set_dosmode(conn,
7771 					smb_fname_dst,
7772 					old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7773 					NULL,
7774 					true);
7775 			}
7776 		}
7777 
7778 		notify_rename(conn, fsp->is_directory, fsp->fsp_name,
7779 			      smb_fname_dst);
7780 
7781 		rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7782 				  smb_fname_dst);
7783 
7784 		/*
7785 		 * A rename acts as a new file create w.r.t. allowing an initial delete
7786 		 * on close, probably because in Windows there is a new handle to the
7787 		 * new file. If initial delete on close was requested but not
7788 		 * originally set, we need to set it here. This is probably not 100% correct,
7789 		 * but will work for the CIFSFS client which in non-posix mode
7790 		 * depends on these semantics. JRA.
7791 		 */
7792 
7793 		if (create_options & FILE_DELETE_ON_CLOSE) {
7794 			status = can_set_delete_on_close(fsp, 0);
7795 
7796 			if (NT_STATUS_IS_OK(status)) {
7797 				/* Note that here we set the *initial* delete on close flag,
7798 				 * not the regular one. The magic gets handled in close. */
7799 				fsp->initial_delete_on_close = True;
7800 			}
7801 		}
7802 		TALLOC_FREE(lck);
7803 		status = NT_STATUS_OK;
7804 		goto out;
7805 	}
7806 
7807 	TALLOC_FREE(lck);
7808 
7809 	if (errno == ENOTDIR || errno == EISDIR) {
7810 		status = NT_STATUS_OBJECT_NAME_COLLISION;
7811 	} else {
7812 		status = map_nt_error_from_unix(errno);
7813 	}
7814 
7815 	DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7816 		  nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7817 		  smb_fname_str_dbg(smb_fname_dst)));
7818 
7819  out:
7820 	TALLOC_FREE(smb_fname_dst);
7821 
7822 	return status;
7823 }
7824 
7825 /****************************************************************************
7826  The guts of the rename command, split out so it may be called by the NT SMB
7827  code.
7828 ****************************************************************************/
7829 
rename_internals(TALLOC_CTX * ctx,connection_struct * conn,struct smb_request * req,struct smb_filename * smb_fname_src,struct smb_filename * smb_fname_dst,uint32_t attrs,bool replace_if_exists,bool src_has_wild,bool dest_has_wild,uint32_t access_mask)7830 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7831 			connection_struct *conn,
7832 			struct smb_request *req,
7833 			struct smb_filename *smb_fname_src,
7834 			struct smb_filename *smb_fname_dst,
7835 			uint32_t attrs,
7836 			bool replace_if_exists,
7837 			bool src_has_wild,
7838 			bool dest_has_wild,
7839 			uint32_t access_mask)
7840 {
7841 	char *fname_src_dir = NULL;
7842 	struct smb_filename *smb_fname_src_dir = NULL;
7843 	char *fname_src_mask = NULL;
7844 	int count=0;
7845 	NTSTATUS status = NT_STATUS_OK;
7846 	struct smb_Dir *dir_hnd = NULL;
7847 	const char *dname = NULL;
7848 	char *talloced = NULL;
7849 	long offset = 0;
7850 	int create_options = 0;
7851 	bool posix_pathnames = (req != NULL && req->posix_pathnames);
7852 	int rc;
7853 
7854 	/*
7855 	 * Split the old name into directory and last component
7856 	 * strings. Note that unix_convert may have stripped off a
7857 	 * leading ./ from both name and newname if the rename is
7858 	 * at the root of the share. We need to make sure either both
7859 	 * name and newname contain a / character or neither of them do
7860 	 * as this is checked in resolve_wildcards().
7861 	 */
7862 
7863 	/* Split up the directory from the filename/mask. */
7864 	status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7865 				      &fname_src_dir, &fname_src_mask);
7866 	if (!NT_STATUS_IS_OK(status)) {
7867 		status = NT_STATUS_NO_MEMORY;
7868 		goto out;
7869 	}
7870 
7871 	/*
7872 	 * We should only check the mangled cache
7873 	 * here if unix_convert failed. This means
7874 	 * that the path in 'mask' doesn't exist
7875 	 * on the file system and so we need to look
7876 	 * for a possible mangle. This patch from
7877 	 * Tine Smukavec <valentin.smukavec@hermes.si>.
7878 	 */
7879 
7880 	if (!VALID_STAT(smb_fname_src->st) &&
7881 	    mangle_is_mangled(fname_src_mask, conn->params)) {
7882 		char *new_mask = NULL;
7883 		mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7884 					    conn->params);
7885 		if (new_mask) {
7886 			TALLOC_FREE(fname_src_mask);
7887 			fname_src_mask = new_mask;
7888 		}
7889 	}
7890 
7891 	if (!src_has_wild) {
7892 		files_struct *fsp;
7893 
7894 		/*
7895 		 * Only one file needs to be renamed. Append the mask back
7896 		 * onto the directory.
7897 		 */
7898 		TALLOC_FREE(smb_fname_src->base_name);
7899 		if (ISDOT(fname_src_dir)) {
7900 			/* Ensure we use canonical names on open. */
7901 			smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7902 							"%s",
7903 							fname_src_mask);
7904 		} else {
7905 			smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7906 							"%s/%s",
7907 							fname_src_dir,
7908 							fname_src_mask);
7909 		}
7910 		if (!smb_fname_src->base_name) {
7911 			status = NT_STATUS_NO_MEMORY;
7912 			goto out;
7913 		}
7914 
7915 		DEBUG(3, ("rename_internals: case_sensitive = %d, "
7916 			  "case_preserve = %d, short case preserve = %d, "
7917 			  "directory = %s, newname = %s, "
7918 			  "last_component_dest = %s\n",
7919 			  conn->case_sensitive, conn->case_preserve,
7920 			  conn->short_case_preserve,
7921 			  smb_fname_str_dbg(smb_fname_src),
7922 			  smb_fname_str_dbg(smb_fname_dst),
7923 			  smb_fname_dst->original_lcomp));
7924 
7925 		/* The dest name still may have wildcards. */
7926 		if (dest_has_wild) {
7927 			char *fname_dst_mod = NULL;
7928 			if (!resolve_wildcards(smb_fname_dst,
7929 					       smb_fname_src->base_name,
7930 					       smb_fname_dst->base_name,
7931 					       &fname_dst_mod)) {
7932 				DEBUG(6, ("rename_internals: resolve_wildcards "
7933 					  "%s %s failed\n",
7934 					  smb_fname_src->base_name,
7935 					  smb_fname_dst->base_name));
7936 				status = NT_STATUS_NO_MEMORY;
7937 				goto out;
7938 			}
7939 			TALLOC_FREE(smb_fname_dst->base_name);
7940 			smb_fname_dst->base_name = fname_dst_mod;
7941 		}
7942 
7943 		ZERO_STRUCT(smb_fname_src->st);
7944 		if (posix_pathnames) {
7945 			rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7946 		} else {
7947 			rc = SMB_VFS_STAT(conn, smb_fname_src);
7948 		}
7949 		if (rc == -1) {
7950 			status = map_nt_error_from_unix_common(errno);
7951 			goto out;
7952 		}
7953 
7954 		if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7955 			create_options |= FILE_DIRECTORY_FILE;
7956 		}
7957 
7958 		status = SMB_VFS_CREATE_FILE(
7959 			conn,				/* conn */
7960 			req,				/* req */
7961 			0,				/* root_dir_fid */
7962 			smb_fname_src,			/* fname */
7963 			access_mask,			/* access_mask */
7964 			(FILE_SHARE_READ |		/* share_access */
7965 			    FILE_SHARE_WRITE),
7966 			FILE_OPEN,			/* create_disposition*/
7967 			create_options,			/* create_options */
7968 			posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7969 			0,				/* oplock_request */
7970 			NULL,				/* lease */
7971 			0,				/* allocation_size */
7972 			0,				/* private_flags */
7973 			NULL,				/* sd */
7974 			NULL,				/* ea_list */
7975 			&fsp,				/* result */
7976 			NULL,				/* pinfo */
7977 			NULL, NULL);			/* create context */
7978 
7979 		if (!NT_STATUS_IS_OK(status)) {
7980 			DEBUG(3, ("Could not open rename source %s: %s\n",
7981 				  smb_fname_str_dbg(smb_fname_src),
7982 				  nt_errstr(status)));
7983 			goto out;
7984 		}
7985 
7986 		status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7987 					      attrs, replace_if_exists);
7988 
7989 		close_file(req, fsp, NORMAL_CLOSE);
7990 
7991 		DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7992 			  nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7993 			  smb_fname_str_dbg(smb_fname_dst)));
7994 
7995 		goto out;
7996 	}
7997 
7998 	/*
7999 	 * Wildcards - process each file that matches.
8000 	 */
8001 	if (strequal(fname_src_mask, "????????.???")) {
8002 		TALLOC_FREE(fname_src_mask);
8003 		fname_src_mask = talloc_strdup(ctx, "*");
8004 		if (!fname_src_mask) {
8005 			status = NT_STATUS_NO_MEMORY;
8006 			goto out;
8007 		}
8008 	}
8009 
8010 	smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8011 				fname_src_dir,
8012 				NULL,
8013 				NULL,
8014 				smb_fname_src->flags);
8015 	if (smb_fname_src_dir == NULL) {
8016 		status = NT_STATUS_NO_MEMORY;
8017 		goto out;
8018 	}
8019 
8020 	status = check_name(conn, smb_fname_src_dir);
8021 	if (!NT_STATUS_IS_OK(status)) {
8022 		goto out;
8023 	}
8024 
8025 	dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8026 			  attrs);
8027 	if (dir_hnd == NULL) {
8028 		status = map_nt_error_from_unix(errno);
8029 		goto out;
8030 	}
8031 
8032 	status = NT_STATUS_NO_SUCH_FILE;
8033 	/*
8034 	 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8035 	 * - gentest fix. JRA
8036 	 */
8037 
8038 	while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8039 				    &talloced))) {
8040 		files_struct *fsp = NULL;
8041 		char *destname = NULL;
8042 		bool sysdir_entry = False;
8043 
8044 		/* Quick check for "." and ".." */
8045 		if (ISDOT(dname) || ISDOTDOT(dname)) {
8046 			if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8047 				sysdir_entry = True;
8048 			} else {
8049 				TALLOC_FREE(talloced);
8050 				continue;
8051 			}
8052 		}
8053 
8054 		if (!is_visible_file(conn, fname_src_dir, dname,
8055 				     &smb_fname_src->st, false)) {
8056 			TALLOC_FREE(talloced);
8057 			continue;
8058 		}
8059 
8060 		if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8061 			TALLOC_FREE(talloced);
8062 			continue;
8063 		}
8064 
8065 		if (sysdir_entry) {
8066 			status = NT_STATUS_OBJECT_NAME_INVALID;
8067 			break;
8068 		}
8069 
8070 		TALLOC_FREE(smb_fname_src->base_name);
8071 		if (ISDOT(fname_src_dir)) {
8072 			/* Ensure we use canonical names on open. */
8073 			smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8074 							"%s",
8075 							dname);
8076 		} else {
8077 			smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8078 							"%s/%s",
8079 							fname_src_dir,
8080 							dname);
8081 		}
8082 		if (!smb_fname_src->base_name) {
8083 			status = NT_STATUS_NO_MEMORY;
8084 			goto out;
8085 		}
8086 
8087 		if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8088 				       smb_fname_dst->base_name,
8089 				       &destname)) {
8090 			DEBUG(6, ("resolve_wildcards %s %s failed\n",
8091 				  smb_fname_src->base_name, destname));
8092 			TALLOC_FREE(talloced);
8093 			continue;
8094 		}
8095 		if (!destname) {
8096 			status = NT_STATUS_NO_MEMORY;
8097 			goto out;
8098 		}
8099 
8100 		TALLOC_FREE(smb_fname_dst->base_name);
8101 		smb_fname_dst->base_name = destname;
8102 
8103 		ZERO_STRUCT(smb_fname_src->st);
8104 		if (posix_pathnames) {
8105 			SMB_VFS_LSTAT(conn, smb_fname_src);
8106 		} else {
8107 			SMB_VFS_STAT(conn, smb_fname_src);
8108 		}
8109 
8110 		create_options = 0;
8111 
8112 		if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8113 			create_options |= FILE_DIRECTORY_FILE;
8114 		}
8115 
8116 		status = SMB_VFS_CREATE_FILE(
8117 			conn,				/* conn */
8118 			req,				/* req */
8119 			0,				/* root_dir_fid */
8120 			smb_fname_src,			/* fname */
8121 			access_mask,			/* access_mask */
8122 			(FILE_SHARE_READ |		/* share_access */
8123 			    FILE_SHARE_WRITE),
8124 			FILE_OPEN,			/* create_disposition*/
8125 			create_options,			/* create_options */
8126 			posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
8127 			0,				/* oplock_request */
8128 			NULL,				/* lease */
8129 			0,				/* allocation_size */
8130 			0,				/* private_flags */
8131 			NULL,				/* sd */
8132 			NULL,				/* ea_list */
8133 			&fsp,				/* result */
8134 			NULL,				/* pinfo */
8135 			NULL, NULL);			/* create context */
8136 
8137 		if (!NT_STATUS_IS_OK(status)) {
8138 			DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8139 				 "returned %s rename %s -> %s\n",
8140 				 nt_errstr(status),
8141 				 smb_fname_str_dbg(smb_fname_src),
8142 				 smb_fname_str_dbg(smb_fname_dst)));
8143 			break;
8144 		}
8145 
8146 		smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
8147 							      dname);
8148 		if (!smb_fname_dst->original_lcomp) {
8149 			status = NT_STATUS_NO_MEMORY;
8150 			goto out;
8151 		}
8152 
8153 		status = rename_internals_fsp(conn, fsp, smb_fname_dst,
8154 					      attrs, replace_if_exists);
8155 
8156 		close_file(req, fsp, NORMAL_CLOSE);
8157 
8158 		if (!NT_STATUS_IS_OK(status)) {
8159 			DEBUG(3, ("rename_internals_fsp returned %s for "
8160 				  "rename %s -> %s\n", nt_errstr(status),
8161 				  smb_fname_str_dbg(smb_fname_src),
8162 				  smb_fname_str_dbg(smb_fname_dst)));
8163 			break;
8164 		}
8165 
8166 		count++;
8167 
8168 		DEBUG(3,("rename_internals: doing rename on %s -> "
8169 			 "%s\n", smb_fname_str_dbg(smb_fname_src),
8170 			 smb_fname_str_dbg(smb_fname_src)));
8171 		TALLOC_FREE(talloced);
8172 	}
8173 	TALLOC_FREE(dir_hnd);
8174 
8175 	if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8176 		status = map_nt_error_from_unix(errno);
8177 	}
8178 
8179  out:
8180 	TALLOC_FREE(talloced);
8181 	TALLOC_FREE(smb_fname_src_dir);
8182 	TALLOC_FREE(fname_src_dir);
8183 	TALLOC_FREE(fname_src_mask);
8184 	return status;
8185 }
8186 
8187 /****************************************************************************
8188  Reply to a mv.
8189 ****************************************************************************/
8190 
reply_mv(struct smb_request * req)8191 void reply_mv(struct smb_request *req)
8192 {
8193 	connection_struct *conn = req->conn;
8194 	char *name = NULL;
8195 	char *newname = NULL;
8196 	const char *p;
8197 	uint32_t attrs;
8198 	NTSTATUS status;
8199 	bool src_has_wcard = False;
8200 	bool dest_has_wcard = False;
8201 	TALLOC_CTX *ctx = talloc_tos();
8202 	struct smb_filename *smb_fname_src = NULL;
8203 	struct smb_filename *smb_fname_dst = NULL;
8204 	uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8205 		(req->posix_pathnames ?
8206 			UCF_UNIX_NAME_LOOKUP :
8207 			UCF_COND_ALLOW_WCARD_LCOMP);
8208 	uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8209 		UCF_SAVE_LCOMP |
8210 		(req->posix_pathnames ?
8211 			0 :
8212 			UCF_COND_ALLOW_WCARD_LCOMP);
8213 	bool stream_rename = false;
8214 
8215 	START_PROFILE(SMBmv);
8216 
8217 	if (req->wct < 1) {
8218 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8219 		goto out;
8220 	}
8221 
8222 	attrs = SVAL(req->vwv+0, 0);
8223 
8224 	p = (const char *)req->buf + 1;
8225 	p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
8226 				       &status, &src_has_wcard);
8227 	if (!NT_STATUS_IS_OK(status)) {
8228 		reply_nterror(req, status);
8229 		goto out;
8230 	}
8231 	p++;
8232 	p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
8233 				       &status, &dest_has_wcard);
8234 	if (!NT_STATUS_IS_OK(status)) {
8235 		reply_nterror(req, status);
8236 		goto out;
8237 	}
8238 
8239 	if (!req->posix_pathnames) {
8240 		/* The newname must begin with a ':' if the
8241 		   name contains a ':'. */
8242 		if (strchr_m(name, ':')) {
8243 			if (newname[0] != ':') {
8244 				reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8245 				goto out;
8246 			}
8247 			stream_rename = true;
8248 		}
8249         }
8250 
8251 	status = filename_convert(ctx,
8252 				  conn,
8253 				  name,
8254 				  src_ucf_flags,
8255 				  NULL,
8256 				  &src_has_wcard,
8257 				  &smb_fname_src);
8258 
8259 	if (!NT_STATUS_IS_OK(status)) {
8260 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8261 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8262 					ERRSRV, ERRbadpath);
8263 			goto out;
8264 		}
8265 		reply_nterror(req, status);
8266 		goto out;
8267 	}
8268 
8269 	status = filename_convert(ctx,
8270 				  conn,
8271 				  newname,
8272 				  dst_ucf_flags,
8273 				  NULL,
8274 				  &dest_has_wcard,
8275 				  &smb_fname_dst);
8276 
8277 	if (!NT_STATUS_IS_OK(status)) {
8278 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8279 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8280 					ERRSRV, ERRbadpath);
8281 			goto out;
8282 		}
8283 		reply_nterror(req, status);
8284 		goto out;
8285 	}
8286 
8287 	if (stream_rename) {
8288 		/* smb_fname_dst->base_name must be the same as
8289 		   smb_fname_src->base_name. */
8290 		TALLOC_FREE(smb_fname_dst->base_name);
8291 		smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8292 						smb_fname_src->base_name);
8293 		if (!smb_fname_dst->base_name) {
8294 			reply_nterror(req, NT_STATUS_NO_MEMORY);
8295 			goto out;
8296 		}
8297 	}
8298 
8299 	DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8300 		 smb_fname_str_dbg(smb_fname_dst)));
8301 
8302 	status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
8303 				  attrs, False, src_has_wcard, dest_has_wcard,
8304 				  DELETE_ACCESS);
8305 	if (!NT_STATUS_IS_OK(status)) {
8306 		if (open_was_deferred(req->xconn, req->mid)) {
8307 			/* We have re-scheduled this call. */
8308 			goto out;
8309 		}
8310 		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8311 			bool ok = defer_smb1_sharing_violation(req);
8312 			if (ok) {
8313 				goto out;
8314 			}
8315 		}
8316 		reply_nterror(req, status);
8317 		goto out;
8318 	}
8319 
8320 	reply_outbuf(req, 0, 0);
8321  out:
8322 	TALLOC_FREE(smb_fname_src);
8323 	TALLOC_FREE(smb_fname_dst);
8324 	END_PROFILE(SMBmv);
8325 	return;
8326 }
8327 
8328 /*******************************************************************
8329  Copy a file as part of a reply_copy.
8330 ******************************************************************/
8331 
8332 /*
8333  * TODO: check error codes on all callers
8334  */
8335 
copy_file(TALLOC_CTX * ctx,connection_struct * conn,struct smb_filename * smb_fname_src,struct smb_filename * smb_fname_dst,int ofun,int count,bool target_is_directory)8336 NTSTATUS copy_file(TALLOC_CTX *ctx,
8337 			connection_struct *conn,
8338 			struct smb_filename *smb_fname_src,
8339 			struct smb_filename *smb_fname_dst,
8340 			int ofun,
8341 			int count,
8342 			bool target_is_directory)
8343 {
8344 	struct smb_filename *smb_fname_dst_tmp = NULL;
8345 	off_t ret=-1;
8346 	files_struct *fsp1,*fsp2;
8347 	uint32_t dosattrs;
8348 	uint32_t new_create_disposition;
8349 	NTSTATUS status;
8350 
8351 
8352 	smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8353 	if (smb_fname_dst_tmp == NULL) {
8354 		return NT_STATUS_NO_MEMORY;
8355 	}
8356 
8357 	/*
8358 	 * If the target is a directory, extract the last component from the
8359 	 * src filename and append it to the dst filename
8360 	 */
8361 	if (target_is_directory) {
8362 		const char *p;
8363 
8364 		/* dest/target can't be a stream if it's a directory. */
8365 		SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8366 
8367 		p = strrchr_m(smb_fname_src->base_name,'/');
8368 		if (p) {
8369 			p++;
8370 		} else {
8371 			p = smb_fname_src->base_name;
8372 		}
8373 		smb_fname_dst_tmp->base_name =
8374 		    talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8375 					   p);
8376 		if (!smb_fname_dst_tmp->base_name) {
8377 			status = NT_STATUS_NO_MEMORY;
8378 			goto out;
8379 		}
8380 	}
8381 
8382 	status = vfs_file_exist(conn, smb_fname_src);
8383 	if (!NT_STATUS_IS_OK(status)) {
8384 		goto out;
8385 	}
8386 
8387 	if (!target_is_directory && count) {
8388 		new_create_disposition = FILE_OPEN;
8389 	} else {
8390 		if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8391 						 0, ofun,
8392 						 NULL, NULL,
8393 						 &new_create_disposition,
8394 						 NULL,
8395 						 NULL)) {
8396 			status = NT_STATUS_INVALID_PARAMETER;
8397 			goto out;
8398 		}
8399 	}
8400 
8401 	/* Open the src file for reading. */
8402 	status = SMB_VFS_CREATE_FILE(
8403 		conn,					/* conn */
8404 		NULL,					/* req */
8405 		0,					/* root_dir_fid */
8406 		smb_fname_src,	       			/* fname */
8407 		FILE_GENERIC_READ,			/* access_mask */
8408 		FILE_SHARE_READ | FILE_SHARE_WRITE,	/* share_access */
8409 		FILE_OPEN,				/* create_disposition*/
8410 		0,					/* create_options */
8411 		FILE_ATTRIBUTE_NORMAL,			/* file_attributes */
8412 		INTERNAL_OPEN_ONLY,			/* oplock_request */
8413 		NULL,					/* lease */
8414 		0,					/* allocation_size */
8415 		0,					/* private_flags */
8416 		NULL,					/* sd */
8417 		NULL,					/* ea_list */
8418 		&fsp1,					/* result */
8419 		NULL,					/* psbuf */
8420 		NULL, NULL);				/* create context */
8421 
8422 	if (!NT_STATUS_IS_OK(status)) {
8423 		goto out;
8424 	}
8425 
8426 	dosattrs = dos_mode(conn, smb_fname_src);
8427 
8428 	if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8429 		ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8430 	}
8431 
8432 	/* Open the dst file for writing. */
8433 	status = SMB_VFS_CREATE_FILE(
8434 		conn,					/* conn */
8435 		NULL,					/* req */
8436 		0,					/* root_dir_fid */
8437 		smb_fname_dst,				/* fname */
8438 		FILE_GENERIC_WRITE,			/* access_mask */
8439 		FILE_SHARE_READ | FILE_SHARE_WRITE,	/* share_access */
8440 		new_create_disposition,			/* create_disposition*/
8441 		0,					/* create_options */
8442 		dosattrs,				/* file_attributes */
8443 		INTERNAL_OPEN_ONLY,			/* oplock_request */
8444 		NULL,					/* lease */
8445 		0,					/* allocation_size */
8446 		0,					/* private_flags */
8447 		NULL,					/* sd */
8448 		NULL,					/* ea_list */
8449 		&fsp2,					/* result */
8450 		NULL,					/* psbuf */
8451 		NULL, NULL);				/* create context */
8452 
8453 	if (!NT_STATUS_IS_OK(status)) {
8454 		close_file(NULL, fsp1, ERROR_CLOSE);
8455 		goto out;
8456 	}
8457 
8458 	if (ofun & OPENX_FILE_EXISTS_OPEN) {
8459 		ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8460 		if (ret == -1) {
8461 			DEBUG(0, ("error - vfs lseek returned error %s\n",
8462 				strerror(errno)));
8463 			status = map_nt_error_from_unix(errno);
8464 			close_file(NULL, fsp1, ERROR_CLOSE);
8465 			close_file(NULL, fsp2, ERROR_CLOSE);
8466 			goto out;
8467 		}
8468 	}
8469 
8470 	/* Do the actual copy. */
8471 	if (smb_fname_src->st.st_ex_size) {
8472 		ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8473 	} else {
8474 		ret = 0;
8475 	}
8476 
8477 	close_file(NULL, fsp1, NORMAL_CLOSE);
8478 
8479 	/* Ensure the modtime is set correctly on the destination file. */
8480 	set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8481 
8482 	/*
8483 	 * As we are opening fsp1 read-only we only expect
8484 	 * an error on close on fsp2 if we are out of space.
8485 	 * Thus we don't look at the error return from the
8486 	 * close of fsp1.
8487 	 */
8488 	status = close_file(NULL, fsp2, NORMAL_CLOSE);
8489 
8490 	if (!NT_STATUS_IS_OK(status)) {
8491 		goto out;
8492 	}
8493 
8494 	if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8495 		status = NT_STATUS_DISK_FULL;
8496 		goto out;
8497 	}
8498 
8499 	status = NT_STATUS_OK;
8500 
8501  out:
8502 	TALLOC_FREE(smb_fname_dst_tmp);
8503 	return status;
8504 }
8505 
8506 /****************************************************************************
8507  Reply to a file copy.
8508 ****************************************************************************/
8509 
reply_copy(struct smb_request * req)8510 void reply_copy(struct smb_request *req)
8511 {
8512 	connection_struct *conn = req->conn;
8513 	struct smb_filename *smb_fname_src = NULL;
8514 	struct smb_filename *smb_fname_src_dir = NULL;
8515 	struct smb_filename *smb_fname_dst = NULL;
8516 	char *fname_src = NULL;
8517 	char *fname_dst = NULL;
8518 	char *fname_src_mask = NULL;
8519 	char *fname_src_dir = NULL;
8520 	const char *p;
8521 	int count=0;
8522 	int error = ERRnoaccess;
8523 	int tid2;
8524 	int ofun;
8525 	int flags;
8526 	bool target_is_directory=False;
8527 	bool source_has_wild = False;
8528 	bool dest_has_wild = False;
8529 	NTSTATUS status;
8530 	uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
8531 		ucf_flags_from_smb_request(req);
8532 	uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
8533 		ucf_flags_from_smb_request(req);
8534 	TALLOC_CTX *ctx = talloc_tos();
8535 
8536 	START_PROFILE(SMBcopy);
8537 
8538 	if (req->wct < 3) {
8539 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8540 		goto out;
8541 	}
8542 
8543 	tid2 = SVAL(req->vwv+0, 0);
8544 	ofun = SVAL(req->vwv+1, 0);
8545 	flags = SVAL(req->vwv+2, 0);
8546 
8547 	p = (const char *)req->buf;
8548 	p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8549 				       &status, &source_has_wild);
8550 	if (!NT_STATUS_IS_OK(status)) {
8551 		reply_nterror(req, status);
8552 		goto out;
8553 	}
8554 	p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8555 				       &status, &dest_has_wild);
8556 	if (!NT_STATUS_IS_OK(status)) {
8557 		reply_nterror(req, status);
8558 		goto out;
8559 	}
8560 
8561 	DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8562 
8563 	if (tid2 != conn->cnum) {
8564 		/* can't currently handle inter share copies XXXX */
8565 		DEBUG(3,("Rejecting inter-share copy\n"));
8566 		reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8567 		goto out;
8568 	}
8569 
8570 	status = filename_convert(ctx, conn,
8571 				  fname_src,
8572 				  ucf_flags_src,
8573 				  NULL,
8574 				  &source_has_wild,
8575 				  &smb_fname_src);
8576 	if (!NT_STATUS_IS_OK(status)) {
8577 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8578 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8579 					ERRSRV, ERRbadpath);
8580 			goto out;
8581 		}
8582 		reply_nterror(req, status);
8583 		goto out;
8584 	}
8585 
8586 	status = filename_convert(ctx, conn,
8587 				  fname_dst,
8588 				  ucf_flags_dst,
8589 				  NULL,
8590 				  &dest_has_wild,
8591 				  &smb_fname_dst);
8592 	if (!NT_STATUS_IS_OK(status)) {
8593 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8594 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8595 					ERRSRV, ERRbadpath);
8596 			goto out;
8597 		}
8598 		reply_nterror(req, status);
8599 		goto out;
8600 	}
8601 
8602 	target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8603 
8604 	if ((flags&1) && target_is_directory) {
8605 		reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8606 		goto out;
8607 	}
8608 
8609 	if ((flags&2) && !target_is_directory) {
8610 		reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8611 		goto out;
8612 	}
8613 
8614 	if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8615 		/* wants a tree copy! XXXX */
8616 		DEBUG(3,("Rejecting tree copy\n"));
8617 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8618 		goto out;
8619 	}
8620 
8621 	/* Split up the directory from the filename/mask. */
8622 	status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8623 				      &fname_src_dir, &fname_src_mask);
8624 	if (!NT_STATUS_IS_OK(status)) {
8625 		reply_nterror(req, NT_STATUS_NO_MEMORY);
8626 		goto out;
8627 	}
8628 
8629 	/*
8630 	 * We should only check the mangled cache
8631 	 * here if unix_convert failed. This means
8632 	 * that the path in 'mask' doesn't exist
8633 	 * on the file system and so we need to look
8634 	 * for a possible mangle. This patch from
8635 	 * Tine Smukavec <valentin.smukavec@hermes.si>.
8636 	 */
8637 	if (!VALID_STAT(smb_fname_src->st) &&
8638 	    mangle_is_mangled(fname_src_mask, conn->params)) {
8639 		char *new_mask = NULL;
8640 		mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8641 					    &new_mask, conn->params);
8642 
8643 		/* Use demangled name if one was successfully found. */
8644 		if (new_mask) {
8645 			TALLOC_FREE(fname_src_mask);
8646 			fname_src_mask = new_mask;
8647 		}
8648 	}
8649 
8650 	if (!source_has_wild) {
8651 
8652 		/*
8653 		 * Only one file needs to be copied. Append the mask back onto
8654 		 * the directory.
8655 		 */
8656 		TALLOC_FREE(smb_fname_src->base_name);
8657 		if (ISDOT(fname_src_dir)) {
8658 			/* Ensure we use canonical names on open. */
8659 			smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8660 							"%s",
8661 							fname_src_mask);
8662 		} else {
8663 			smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8664 							"%s/%s",
8665 							fname_src_dir,
8666 							fname_src_mask);
8667 		}
8668 		if (!smb_fname_src->base_name) {
8669 			reply_nterror(req, NT_STATUS_NO_MEMORY);
8670 			goto out;
8671 		}
8672 
8673 		if (dest_has_wild) {
8674 			char *fname_dst_mod = NULL;
8675 			if (!resolve_wildcards(smb_fname_dst,
8676 					       smb_fname_src->base_name,
8677 					       smb_fname_dst->base_name,
8678 					       &fname_dst_mod)) {
8679 				reply_nterror(req, NT_STATUS_NO_MEMORY);
8680 				goto out;
8681 			}
8682 			TALLOC_FREE(smb_fname_dst->base_name);
8683 			smb_fname_dst->base_name = fname_dst_mod;
8684 		}
8685 
8686 		status = check_name(conn, smb_fname_src);
8687 		if (!NT_STATUS_IS_OK(status)) {
8688 			reply_nterror(req, status);
8689 			goto out;
8690 		}
8691 
8692 		status = check_name(conn, smb_fname_dst);
8693 		if (!NT_STATUS_IS_OK(status)) {
8694 			reply_nterror(req, status);
8695 			goto out;
8696 		}
8697 
8698 		status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8699 				   ofun, count, target_is_directory);
8700 
8701 		if(!NT_STATUS_IS_OK(status)) {
8702 			reply_nterror(req, status);
8703 			goto out;
8704 		} else {
8705 			count++;
8706 		}
8707 	} else {
8708 		struct smb_Dir *dir_hnd = NULL;
8709 		const char *dname = NULL;
8710 		char *talloced = NULL;
8711 		long offset = 0;
8712 
8713 		/*
8714 		 * There is a wildcard that requires us to actually read the
8715 		 * src dir and copy each file matching the mask to the dst.
8716 		 * Right now streams won't be copied, but this could
8717 		 * presumably be added with a nested loop for reach dir entry.
8718 		 */
8719 		SMB_ASSERT(!smb_fname_src->stream_name);
8720 		SMB_ASSERT(!smb_fname_dst->stream_name);
8721 
8722 		smb_fname_src->stream_name = NULL;
8723 		smb_fname_dst->stream_name = NULL;
8724 
8725 		if (strequal(fname_src_mask,"????????.???")) {
8726 			TALLOC_FREE(fname_src_mask);
8727 			fname_src_mask = talloc_strdup(ctx, "*");
8728 			if (!fname_src_mask) {
8729 				reply_nterror(req, NT_STATUS_NO_MEMORY);
8730 				goto out;
8731 			}
8732 		}
8733 
8734 		smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8735 					fname_src_dir,
8736 					NULL,
8737 					NULL,
8738 					smb_fname_src->flags);
8739 		if (smb_fname_src_dir == NULL) {
8740 			reply_nterror(req, NT_STATUS_NO_MEMORY);
8741 			goto out;
8742 		}
8743 
8744 		status = check_name(conn, smb_fname_src_dir);
8745 		if (!NT_STATUS_IS_OK(status)) {
8746 			reply_nterror(req, status);
8747 			goto out;
8748 		}
8749 
8750 		dir_hnd = OpenDir(ctx,
8751 				conn,
8752 				smb_fname_src_dir,
8753 				fname_src_mask,
8754 				0);
8755 		if (dir_hnd == NULL) {
8756 			status = map_nt_error_from_unix(errno);
8757 			reply_nterror(req, status);
8758 			goto out;
8759 		}
8760 
8761 		error = ERRbadfile;
8762 
8763 		/* Iterate over the src dir copying each entry to the dst. */
8764 		while ((dname = ReadDirName(dir_hnd, &offset,
8765 					    &smb_fname_src->st, &talloced))) {
8766 			char *destname = NULL;
8767 
8768 			if (ISDOT(dname) || ISDOTDOT(dname)) {
8769 				TALLOC_FREE(talloced);
8770 				continue;
8771 			}
8772 
8773 			if (!is_visible_file(conn, fname_src_dir, dname,
8774 					     &smb_fname_src->st, false)) {
8775 				TALLOC_FREE(talloced);
8776 				continue;
8777 			}
8778 
8779 			if(!mask_match(dname, fname_src_mask,
8780 				       conn->case_sensitive)) {
8781 				TALLOC_FREE(talloced);
8782 				continue;
8783 			}
8784 
8785 			error = ERRnoaccess;
8786 
8787 			/* Get the src smb_fname struct setup. */
8788 			TALLOC_FREE(smb_fname_src->base_name);
8789 			if (ISDOT(fname_src_dir)) {
8790 				/* Ensure we use canonical names on open. */
8791 				smb_fname_src->base_name =
8792 					talloc_asprintf(smb_fname_src, "%s",
8793 						dname);
8794 			} else {
8795 				smb_fname_src->base_name =
8796 					talloc_asprintf(smb_fname_src, "%s/%s",
8797 						fname_src_dir, dname);
8798 			}
8799 
8800 			if (!smb_fname_src->base_name) {
8801 				TALLOC_FREE(dir_hnd);
8802 				TALLOC_FREE(talloced);
8803 				reply_nterror(req, NT_STATUS_NO_MEMORY);
8804 				goto out;
8805 			}
8806 
8807 			if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8808 					       smb_fname_dst->base_name,
8809 					       &destname)) {
8810 				TALLOC_FREE(talloced);
8811 				continue;
8812 			}
8813 			if (!destname) {
8814 				TALLOC_FREE(dir_hnd);
8815 				TALLOC_FREE(talloced);
8816 				reply_nterror(req, NT_STATUS_NO_MEMORY);
8817 				goto out;
8818 			}
8819 
8820 			TALLOC_FREE(smb_fname_dst->base_name);
8821 			smb_fname_dst->base_name = destname;
8822 
8823 			status = check_name(conn, smb_fname_src);
8824 			if (!NT_STATUS_IS_OK(status)) {
8825 				TALLOC_FREE(dir_hnd);
8826 				TALLOC_FREE(talloced);
8827 				reply_nterror(req, status);
8828 				goto out;
8829 			}
8830 
8831 			status = check_name(conn, smb_fname_dst);
8832 			if (!NT_STATUS_IS_OK(status)) {
8833 				TALLOC_FREE(dir_hnd);
8834 				TALLOC_FREE(talloced);
8835 				reply_nterror(req, status);
8836 				goto out;
8837 			}
8838 
8839 			DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8840 				smb_fname_src->base_name,
8841 				smb_fname_dst->base_name));
8842 
8843 			status = copy_file(ctx, conn, smb_fname_src,
8844 					   smb_fname_dst, ofun,	count,
8845 					   target_is_directory);
8846 			if (NT_STATUS_IS_OK(status)) {
8847 				count++;
8848 			}
8849 
8850 			TALLOC_FREE(talloced);
8851 		}
8852 		TALLOC_FREE(dir_hnd);
8853 	}
8854 
8855 	if (count == 0) {
8856 		reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8857 		goto out;
8858 	}
8859 
8860 	reply_outbuf(req, 1, 0);
8861 	SSVAL(req->outbuf,smb_vwv0,count);
8862  out:
8863 	TALLOC_FREE(smb_fname_src);
8864 	TALLOC_FREE(smb_fname_src_dir);
8865 	TALLOC_FREE(smb_fname_dst);
8866 	TALLOC_FREE(fname_src);
8867 	TALLOC_FREE(fname_dst);
8868 	TALLOC_FREE(fname_src_mask);
8869 	TALLOC_FREE(fname_src_dir);
8870 
8871 	END_PROFILE(SMBcopy);
8872 	return;
8873 }
8874 
8875 #undef DBGC_CLASS
8876 #define DBGC_CLASS DBGC_LOCKING
8877 
8878 /****************************************************************************
8879  Get a lock pid, dealing with large count requests.
8880 ****************************************************************************/
8881 
get_lock_pid(const uint8_t * data,int data_offset,bool large_file_format)8882 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8883 		    bool large_file_format)
8884 {
8885 	if(!large_file_format)
8886 		return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8887 	else
8888 		return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8889 }
8890 
8891 /****************************************************************************
8892  Get a lock count, dealing with large count requests.
8893 ****************************************************************************/
8894 
get_lock_count(const uint8_t * data,int data_offset,bool large_file_format)8895 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8896 			bool large_file_format)
8897 {
8898 	uint64_t count = 0;
8899 
8900 	if(!large_file_format) {
8901 		count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8902 	} else {
8903 		/*
8904 		 * No BVAL, this is reversed!
8905 		 */
8906 		count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8907 			((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8908 	}
8909 
8910 	return count;
8911 }
8912 
8913 /****************************************************************************
8914  Get a lock offset, dealing with large offset requests.
8915 ****************************************************************************/
8916 
get_lock_offset(const uint8_t * data,int data_offset,bool large_file_format)8917 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8918 			 bool large_file_format)
8919 {
8920 	uint64_t offset = 0;
8921 
8922 	if(!large_file_format) {
8923 		offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8924 	} else {
8925 		/*
8926 		 * No BVAL, this is reversed!
8927 		 */
8928 		offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8929 				((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8930 	}
8931 
8932 	return offset;
8933 }
8934 
8935 struct smbd_do_unlocking_state {
8936 	struct files_struct *fsp;
8937 	uint16_t num_ulocks;
8938 	struct smbd_lock_element *ulocks;
8939 	enum brl_flavour lock_flav;
8940 	NTSTATUS status;
8941 };
8942 
smbd_do_unlocking_fn(TDB_DATA value,bool * pmodified_dependent,void * private_data)8943 static void smbd_do_unlocking_fn(
8944 	TDB_DATA value, bool *pmodified_dependent, void *private_data)
8945 {
8946 	struct smbd_do_unlocking_state *state = private_data;
8947 	struct files_struct *fsp = state->fsp;
8948 	enum brl_flavour lock_flav = state->lock_flav;
8949 	uint16_t i;
8950 
8951 	for (i = 0; i < state->num_ulocks; i++) {
8952 		struct smbd_lock_element *e = &state->ulocks[i];
8953 
8954 		DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
8955 			  "pid %"PRIu64", file %s\n",
8956 			  e->offset,
8957 			  e->count,
8958 			  e->smblctx,
8959 			  fsp_str_dbg(fsp));
8960 
8961 		if (e->brltype != UNLOCK_LOCK) {
8962 			/* this can only happen with SMB2 */
8963 			state->status = NT_STATUS_INVALID_PARAMETER;
8964 			return;
8965 		}
8966 
8967 		state->status = do_unlock(
8968 			fsp, e->smblctx, e->count, e->offset, lock_flav);
8969 
8970 		DBG_DEBUG("do_unlock returned %s\n",
8971 			  nt_errstr(state->status));
8972 
8973 		if (!NT_STATUS_IS_OK(state->status)) {
8974 			return;
8975 		}
8976 	}
8977 
8978 	*pmodified_dependent = true;
8979 }
8980 
smbd_do_unlocking(struct smb_request * req,files_struct * fsp,uint16_t num_ulocks,struct smbd_lock_element * ulocks,enum brl_flavour lock_flav)8981 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8982 			   files_struct *fsp,
8983 			   uint16_t num_ulocks,
8984 			   struct smbd_lock_element *ulocks,
8985 			   enum brl_flavour lock_flav)
8986 {
8987 	struct smbd_do_unlocking_state state = {
8988 		.fsp = fsp,
8989 		.num_ulocks = num_ulocks,
8990 		.ulocks = ulocks,
8991 		.lock_flav = lock_flav,
8992 	};
8993 	NTSTATUS status;
8994 
8995 	DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
8996 
8997 	status = share_mode_do_locked(
8998 		fsp->file_id, smbd_do_unlocking_fn, &state);
8999 
9000 	if (!NT_STATUS_IS_OK(status)) {
9001 		DBG_DEBUG("share_mode_do_locked failed: %s\n",
9002 			  nt_errstr(status));
9003 		return status;
9004 	}
9005 	if (!NT_STATUS_IS_OK(state.status)) {
9006 		DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9007 			  nt_errstr(status));
9008 		return state.status;
9009 	}
9010 
9011 	return NT_STATUS_OK;
9012 }
9013 
9014 /****************************************************************************
9015  Reply to a lockingX request.
9016 ****************************************************************************/
9017 
9018 static void reply_lockingx_done(struct tevent_req *subreq);
9019 
reply_lockingX(struct smb_request * req)9020 void reply_lockingX(struct smb_request *req)
9021 {
9022 	connection_struct *conn = req->conn;
9023 	files_struct *fsp;
9024 	unsigned char locktype;
9025 	enum brl_type brltype;
9026 	unsigned char oplocklevel;
9027 	uint16_t num_ulocks;
9028 	uint16_t num_locks;
9029 	int32_t lock_timeout;
9030 	uint16_t i;
9031 	const uint8_t *data;
9032 	bool large_file_format;
9033 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9034 	struct smbd_lock_element *locks = NULL;
9035 	struct tevent_req *subreq = NULL;
9036 
9037 	START_PROFILE(SMBlockingX);
9038 
9039 	if (req->wct < 8) {
9040 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9041 		END_PROFILE(SMBlockingX);
9042 		return;
9043 	}
9044 
9045 	fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9046 	locktype = CVAL(req->vwv+3, 0);
9047 	oplocklevel = CVAL(req->vwv+3, 1);
9048 	num_ulocks = SVAL(req->vwv+6, 0);
9049 	num_locks = SVAL(req->vwv+7, 0);
9050 	lock_timeout = IVAL(req->vwv+4, 0);
9051 	large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9052 
9053 	if (!check_fsp(conn, req, fsp)) {
9054 		END_PROFILE(SMBlockingX);
9055 		return;
9056 	}
9057 
9058 	data = req->buf;
9059 
9060 	if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9061 		/* we don't support these - and CANCEL_LOCK makes w2k
9062 		   and XP reboot so I don't really want to be
9063 		   compatible! (tridge) */
9064 		reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9065 		END_PROFILE(SMBlockingX);
9066 		return;
9067 	}
9068 
9069 	/* Check if this is an oplock break on a file
9070 	   we have granted an oplock on.
9071 	*/
9072 	if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9073 		/* Client can insist on breaking to none. */
9074 		bool break_to_none = (oplocklevel == 0);
9075 		bool result;
9076 
9077 		DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9078 			 "for %s\n", (unsigned int)oplocklevel,
9079 			 fsp_fnum_dbg(fsp)));
9080 
9081 		/*
9082 		 * Make sure we have granted an exclusive or batch oplock on
9083 		 * this file.
9084 		 */
9085 
9086 		if (fsp->oplock_type == 0) {
9087 
9088 			/* The Samba4 nbench simulator doesn't understand
9089 			   the difference between break to level2 and break
9090 			   to none from level2 - it sends oplock break
9091 			   replies in both cases. Don't keep logging an error
9092 			   message here - just ignore it. JRA. */
9093 
9094 			DEBUG(5,("reply_lockingX: Error : oplock break from "
9095 				 "client for %s (oplock=%d) and no "
9096 				 "oplock granted on this file (%s).\n",
9097 				 fsp_fnum_dbg(fsp), fsp->oplock_type,
9098 				 fsp_str_dbg(fsp)));
9099 
9100 			/* if this is a pure oplock break request then don't
9101 			 * send a reply */
9102 			if (num_locks == 0 && num_ulocks == 0) {
9103 				END_PROFILE(SMBlockingX);
9104 				return;
9105 			}
9106 
9107 			END_PROFILE(SMBlockingX);
9108 			reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9109 			return;
9110 		}
9111 
9112 		if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9113 		    (break_to_none)) {
9114 			result = remove_oplock(fsp);
9115 		} else {
9116 			result = downgrade_oplock(fsp);
9117 		}
9118 
9119 		if (!result) {
9120 			DEBUG(0, ("reply_lockingX: error in removing "
9121 				  "oplock on file %s\n", fsp_str_dbg(fsp)));
9122 			/* Hmmm. Is this panic justified? */
9123 			smb_panic("internal tdb error");
9124 		}
9125 
9126 		/* if this is a pure oplock break request then don't send a
9127 		 * reply */
9128 		if (num_locks == 0 && num_ulocks == 0) {
9129 			/* Sanity check - ensure a pure oplock break is not a
9130 			   chained request. */
9131 			if (CVAL(req->vwv+0, 0) != 0xff) {
9132 				DEBUG(0,("reply_lockingX: Error : pure oplock "
9133 					 "break is a chained %d request !\n",
9134 					 (unsigned int)CVAL(req->vwv+0, 0)));
9135 			}
9136 			END_PROFILE(SMBlockingX);
9137 			return;
9138 		}
9139 	}
9140 
9141 	if (req->buflen <
9142 	    (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9143 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9144 		END_PROFILE(SMBlockingX);
9145 		return;
9146 	}
9147 
9148 	if (num_ulocks != 0) {
9149 		struct smbd_lock_element *ulocks = NULL;
9150 		bool ok;
9151 
9152 		ulocks = talloc_array(
9153 			req, struct smbd_lock_element, num_ulocks);
9154 		if (ulocks == NULL) {
9155 			reply_nterror(req, NT_STATUS_NO_MEMORY);
9156 			END_PROFILE(SMBlockingX);
9157 			return;
9158 		}
9159 
9160 		/*
9161 		 * Data now points at the beginning of the list of
9162 		 * smb_unlkrng structs
9163 		 */
9164 		for (i = 0; i < num_ulocks; i++) {
9165 			ulocks[i].req_guid = smbd_request_guid(req,
9166 				UINT16_MAX - i),
9167 			ulocks[i].smblctx = get_lock_pid(
9168 				data, i, large_file_format);
9169 			ulocks[i].count = get_lock_count(
9170 				data, i, large_file_format);
9171 			ulocks[i].offset = get_lock_offset(
9172 				data, i, large_file_format);
9173 			ulocks[i].brltype = UNLOCK_LOCK;
9174 		}
9175 
9176 		/*
9177 		 * Unlock cancels pending locks
9178 		 */
9179 
9180 		ok = smbd_smb1_brl_finish_by_lock(
9181 			fsp,
9182 			large_file_format,
9183 			WINDOWS_LOCK,
9184 			ulocks[0],
9185 			NT_STATUS_OK);
9186 		if (ok) {
9187 			reply_outbuf(req, 2, 0);
9188 			SSVAL(req->outbuf, smb_vwv0, 0xff);
9189 			SSVAL(req->outbuf, smb_vwv1, 0);
9190 			END_PROFILE(SMBlockingX);
9191 			return;
9192 		}
9193 
9194 		status = smbd_do_unlocking(
9195 			req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9196 		TALLOC_FREE(ulocks);
9197 		if (!NT_STATUS_IS_OK(status)) {
9198 			END_PROFILE(SMBlockingX);
9199 			reply_nterror(req, status);
9200 			return;
9201 		}
9202 	}
9203 
9204 	/* Now do any requested locks */
9205 	data += ((large_file_format ? 20 : 10)*num_ulocks);
9206 
9207 	/* Data now points at the beginning of the list
9208 	   of smb_lkrng structs */
9209 
9210 	if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9211 		brltype = READ_LOCK;
9212 	} else {
9213 		brltype = WRITE_LOCK;
9214 	}
9215 
9216 	locks = talloc_array(req, struct smbd_lock_element, num_locks);
9217 	if (locks == NULL) {
9218 		reply_nterror(req, NT_STATUS_NO_MEMORY);
9219 		END_PROFILE(SMBlockingX);
9220 		return;
9221 	}
9222 
9223 	for (i = 0; i < num_locks; i++) {
9224 		locks[i].req_guid = smbd_request_guid(req, i),
9225 		locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9226 		locks[i].count = get_lock_count(data, i, large_file_format);
9227 		locks[i].offset = get_lock_offset(data, i, large_file_format);
9228 		locks[i].brltype = brltype;
9229 	}
9230 
9231 	if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9232 
9233 		bool ok;
9234 
9235 		if (num_locks == 0) {
9236 			/* See smbtorture3 lock11 test */
9237 			reply_outbuf(req, 2, 0);
9238 			/* andx chain ends */
9239 			SSVAL(req->outbuf, smb_vwv0, 0xff);
9240 			SSVAL(req->outbuf, smb_vwv1, 0);
9241 			END_PROFILE(SMBlockingX);
9242 			return;
9243 		}
9244 
9245 		ok = smbd_smb1_brl_finish_by_lock(
9246 			fsp,
9247 			large_file_format,
9248 			WINDOWS_LOCK,
9249 			locks[0], /* Windows only cancels the first lock */
9250 			NT_STATUS_FILE_LOCK_CONFLICT);
9251 
9252 		if (!ok) {
9253 			reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9254 			END_PROFILE(SMBlockingX);
9255 			return;
9256 		}
9257 
9258 		reply_outbuf(req, 2, 0);
9259 		SSVAL(req->outbuf, smb_vwv0, 0xff);
9260 		SSVAL(req->outbuf, smb_vwv1, 0);
9261 		END_PROFILE(SMBlockingX);
9262 		return;
9263 	}
9264 
9265 	subreq = smbd_smb1_do_locks_send(
9266 		fsp,
9267 		req->sconn->ev_ctx,
9268 		&req,
9269 		fsp,
9270 		lock_timeout,
9271 		large_file_format,
9272 		WINDOWS_LOCK,
9273 		num_locks,
9274 		locks);
9275 	if (subreq == NULL) {
9276 		reply_nterror(req, NT_STATUS_NO_MEMORY);
9277 		END_PROFILE(SMBlockingX);
9278 		return;
9279 	}
9280 	tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9281 	END_PROFILE(SMBlockingX);
9282 }
9283 
reply_lockingx_done(struct tevent_req * subreq)9284 static void reply_lockingx_done(struct tevent_req *subreq)
9285 {
9286 	struct smb_request *req = NULL;
9287 	NTSTATUS status;
9288 	bool ok;
9289 
9290 	START_PROFILE(SMBlockingX);
9291 
9292 	ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9293 	SMB_ASSERT(ok);
9294 
9295 	status = smbd_smb1_do_locks_recv(subreq);
9296 	TALLOC_FREE(subreq);
9297 
9298 	DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9299 
9300 	if (NT_STATUS_IS_OK(status)) {
9301 		reply_outbuf(req, 2, 0);
9302 		SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9303 		SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
9304 	} else {
9305 		reply_nterror(req, status);
9306 	}
9307 
9308 	ok = srv_send_smb(req->xconn,
9309 			  (char *)req->outbuf,
9310 			  true,
9311 			  req->seqnum+1,
9312 			  IS_CONN_ENCRYPTED(req->conn),
9313 			  NULL);
9314 	if (!ok) {
9315 		exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9316 	}
9317 	TALLOC_FREE(req);
9318 	END_PROFILE(SMBlockingX);
9319 }
9320 
9321 #undef DBGC_CLASS
9322 #define DBGC_CLASS DBGC_ALL
9323 
9324 /****************************************************************************
9325  Reply to a SMBreadbmpx (read block multiplex) request.
9326  Always reply with an error, if someone has a platform really needs this,
9327  please contact vl@samba.org
9328 ****************************************************************************/
9329 
reply_readbmpx(struct smb_request * req)9330 void reply_readbmpx(struct smb_request *req)
9331 {
9332 	START_PROFILE(SMBreadBmpx);
9333 	reply_force_doserror(req, ERRSRV, ERRuseSTD);
9334 	END_PROFILE(SMBreadBmpx);
9335 	return;
9336 }
9337 
9338 /****************************************************************************
9339  Reply to a SMBreadbs (read block multiplex secondary) request.
9340  Always reply with an error, if someone has a platform really needs this,
9341  please contact vl@samba.org
9342 ****************************************************************************/
9343 
reply_readbs(struct smb_request * req)9344 void reply_readbs(struct smb_request *req)
9345 {
9346 	START_PROFILE(SMBreadBs);
9347 	reply_force_doserror(req, ERRSRV, ERRuseSTD);
9348 	END_PROFILE(SMBreadBs);
9349 	return;
9350 }
9351 
9352 /****************************************************************************
9353  Reply to a SMBsetattrE.
9354 ****************************************************************************/
9355 
reply_setattrE(struct smb_request * req)9356 void reply_setattrE(struct smb_request *req)
9357 {
9358 	connection_struct *conn = req->conn;
9359 	struct smb_file_time ft;
9360 	files_struct *fsp;
9361 	NTSTATUS status;
9362 
9363 	START_PROFILE(SMBsetattrE);
9364 	init_smb_file_time(&ft);
9365 
9366 	if (req->wct < 7) {
9367 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9368 		goto out;
9369 	}
9370 
9371 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9372 
9373 	if(!fsp || (fsp->conn != conn)) {
9374 		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9375 		goto out;
9376 	}
9377 
9378 	/*
9379 	 * Convert the DOS times into unix times.
9380 	 */
9381 
9382 	ft.atime = time_t_to_full_timespec(
9383 	    srv_make_unix_date2(req->vwv+3));
9384 	ft.mtime = time_t_to_full_timespec(
9385 	    srv_make_unix_date2(req->vwv+5));
9386 	ft.create_time = time_t_to_full_timespec(
9387 	    srv_make_unix_date2(req->vwv+1));
9388 
9389 	reply_outbuf(req, 0, 0);
9390 
9391 	/*
9392 	 * Patch from Ray Frush <frush@engr.colostate.edu>
9393 	 * Sometimes times are sent as zero - ignore them.
9394 	 */
9395 
9396 	/* Ensure we have a valid stat struct for the source. */
9397 	status = vfs_stat_fsp(fsp);
9398 	if (!NT_STATUS_IS_OK(status)) {
9399 		reply_nterror(req, status);
9400 		goto out;
9401 	}
9402 
9403 	if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9404 		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9405 		goto out;
9406 	}
9407 
9408 	status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9409 	if (!NT_STATUS_IS_OK(status)) {
9410 		reply_nterror(req, status);
9411 		goto out;
9412 	}
9413 
9414 	if (fsp->modified) {
9415 		trigger_write_time_update_immediate(fsp);
9416 	}
9417 
9418 	DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9419 	       " createtime=%u\n",
9420 		fsp_fnum_dbg(fsp),
9421 		(unsigned int)ft.atime.tv_sec,
9422 		(unsigned int)ft.mtime.tv_sec,
9423 		(unsigned int)ft.create_time.tv_sec
9424 		));
9425  out:
9426 	END_PROFILE(SMBsetattrE);
9427 	return;
9428 }
9429 
9430 
9431 /* Back from the dead for OS/2..... JRA. */
9432 
9433 /****************************************************************************
9434  Reply to a SMBwritebmpx (write block multiplex primary) request.
9435  Always reply with an error, if someone has a platform really needs this,
9436  please contact vl@samba.org
9437 ****************************************************************************/
9438 
reply_writebmpx(struct smb_request * req)9439 void reply_writebmpx(struct smb_request *req)
9440 {
9441 	START_PROFILE(SMBwriteBmpx);
9442 	reply_force_doserror(req, ERRSRV, ERRuseSTD);
9443 	END_PROFILE(SMBwriteBmpx);
9444 	return;
9445 }
9446 
9447 /****************************************************************************
9448  Reply to a SMBwritebs (write block multiplex secondary) request.
9449  Always reply with an error, if someone has a platform really needs this,
9450  please contact vl@samba.org
9451 ****************************************************************************/
9452 
reply_writebs(struct smb_request * req)9453 void reply_writebs(struct smb_request *req)
9454 {
9455 	START_PROFILE(SMBwriteBs);
9456 	reply_force_doserror(req, ERRSRV, ERRuseSTD);
9457 	END_PROFILE(SMBwriteBs);
9458 	return;
9459 }
9460 
9461 /****************************************************************************
9462  Reply to a SMBgetattrE.
9463 ****************************************************************************/
9464 
reply_getattrE(struct smb_request * req)9465 void reply_getattrE(struct smb_request *req)
9466 {
9467 	connection_struct *conn = req->conn;
9468 	int mode;
9469 	files_struct *fsp;
9470 	struct timespec create_ts;
9471 	NTSTATUS status;
9472 
9473 	START_PROFILE(SMBgetattrE);
9474 
9475 	if (req->wct < 1) {
9476 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9477 		END_PROFILE(SMBgetattrE);
9478 		return;
9479 	}
9480 
9481 	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9482 
9483 	if(!fsp || (fsp->conn != conn)) {
9484 		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9485 		END_PROFILE(SMBgetattrE);
9486 		return;
9487 	}
9488 
9489 	/* Do an fstat on this file */
9490 	status = vfs_stat_fsp(fsp);
9491 	if (!NT_STATUS_IS_OK(status)) {
9492 		reply_nterror(req, status);
9493 		END_PROFILE(SMBgetattrE);
9494 		return;
9495 	}
9496 
9497 	mode = dos_mode(conn, fsp->fsp_name);
9498 
9499 	/*
9500 	 * Convert the times into dos times. Set create
9501 	 * date to be last modify date as UNIX doesn't save
9502 	 * this.
9503 	 */
9504 
9505 	reply_outbuf(req, 11, 0);
9506 
9507 	create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9508 	srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9509 	srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9510 			  convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9511 	/* Should we check pending modtime here ? JRA */
9512 	srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9513 			  convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9514 
9515 	if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9516 		SIVAL(req->outbuf, smb_vwv6, 0);
9517 		SIVAL(req->outbuf, smb_vwv8, 0);
9518 	} else {
9519 		uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9520 		SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9521 		SIVAL(req->outbuf, smb_vwv8, allocation_size);
9522 	}
9523 	SSVAL(req->outbuf,smb_vwv10, mode);
9524 
9525 	DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9526 
9527 	END_PROFILE(SMBgetattrE);
9528 	return;
9529 }
9530