Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB NT transaction handling
4 : Copyright (C) Jeremy Allison 1994-2007
5 : Copyright (C) Stefan (metze) Metzmacher 2003
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "system/filesys.h"
23 : #include "smbd/smbd.h"
24 : #include "smbd/globals.h"
25 : #include "fake_file.h"
26 : #include "../libcli/security/security.h"
27 : #include "../librpc/gen_ndr/ndr_security.h"
28 : #include "passdb/lookup_sid.h"
29 : #include "auth.h"
30 : #include "smbprofile.h"
31 : #include "libsmb/libsmb.h"
32 : #include "lib/util_ea.h"
33 : #include "librpc/gen_ndr/ndr_quota.h"
34 : #include "librpc/gen_ndr/ndr_security.h"
35 :
36 0 : static char *nttrans_realloc(char **ptr, size_t size)
37 : {
38 0 : if (ptr==NULL) {
39 0 : smb_panic("nttrans_realloc() called with NULL ptr");
40 : }
41 :
42 0 : *ptr = (char *)SMB_REALLOC(*ptr, size);
43 0 : if(*ptr == NULL) {
44 0 : return NULL;
45 : }
46 0 : memset(*ptr,'\0',size);
47 0 : return *ptr;
48 : }
49 :
50 : /****************************************************************************
51 : Send the required number of replies back.
52 : We assume all fields other than the data fields are
53 : set correctly for the type of call.
54 : HACK ! Always assumes smb_setup field is zero.
55 : ****************************************************************************/
56 :
57 0 : static void send_nt_replies(connection_struct *conn,
58 : struct smb_request *req, NTSTATUS nt_error,
59 : char *params, int paramsize,
60 : char *pdata, int datasize)
61 : {
62 0 : int data_to_send = datasize;
63 0 : int params_to_send = paramsize;
64 : int useable_space;
65 0 : char *pp = params;
66 0 : char *pd = pdata;
67 : int params_sent_thistime, data_sent_thistime, total_sent_thistime;
68 0 : int alignment_offset = 1;
69 0 : int data_alignment_offset = 0;
70 0 : struct smbXsrv_connection *xconn = req->xconn;
71 0 : int max_send = xconn->smb1.sessions.max_send;
72 :
73 : /*
74 : * If there genuinely are no parameters or data to send just send
75 : * the empty packet.
76 : */
77 :
78 0 : if(params_to_send == 0 && data_to_send == 0) {
79 0 : reply_smb1_outbuf(req, 18, 0);
80 0 : if (NT_STATUS_V(nt_error)) {
81 0 : error_packet_set((char *)req->outbuf,
82 : 0, 0, nt_error,
83 : __LINE__,__FILE__);
84 : }
85 0 : show_msg((char *)req->outbuf);
86 0 : if (!smb1_srv_send(xconn,
87 0 : (char *)req->outbuf,
88 0 : true, req->seqnum+1,
89 0 : IS_CONN_ENCRYPTED(conn),
90 : &req->pcd)) {
91 0 : exit_server_cleanly("send_nt_replies: smb1_srv_send failed.");
92 : }
93 0 : TALLOC_FREE(req->outbuf);
94 0 : return;
95 : }
96 :
97 : /*
98 : * When sending params and data ensure that both are nicely aligned.
99 : * Only do this alignment when there is also data to send - else
100 : * can cause NT redirector problems.
101 : */
102 :
103 0 : if (((params_to_send % 4) != 0) && (data_to_send != 0)) {
104 0 : data_alignment_offset = 4 - (params_to_send % 4);
105 : }
106 :
107 : /*
108 : * Space is bufsize minus Netbios over TCP header minus SMB header.
109 : * The alignment_offset is to align the param bytes on a four byte
110 : * boundary (2 bytes for data len, one byte pad).
111 : * NT needs this to work correctly.
112 : */
113 :
114 0 : useable_space = max_send - (smb_size
115 : + 2 * 18 /* wct */
116 0 : + alignment_offset
117 0 : + data_alignment_offset);
118 :
119 0 : if (useable_space < 0) {
120 0 : char *msg = talloc_asprintf(
121 0 : talloc_tos(),
122 : "send_nt_replies failed sanity useable_space = %d!!!",
123 : useable_space);
124 0 : DEBUG(0, ("%s\n", msg));
125 0 : exit_server_cleanly(msg);
126 : }
127 :
128 0 : while (params_to_send || data_to_send) {
129 :
130 : /*
131 : * Calculate whether we will totally or partially fill this packet.
132 : */
133 :
134 0 : total_sent_thistime = params_to_send + data_to_send;
135 :
136 : /*
137 : * We can never send more than useable_space.
138 : */
139 :
140 0 : total_sent_thistime = MIN(total_sent_thistime, useable_space);
141 :
142 0 : reply_smb1_outbuf(req, 18,
143 0 : total_sent_thistime + alignment_offset
144 0 : + data_alignment_offset);
145 :
146 : /*
147 : * Set total params and data to be sent.
148 : */
149 :
150 0 : SIVAL(req->outbuf,smb_ntr_TotalParameterCount,paramsize);
151 0 : SIVAL(req->outbuf,smb_ntr_TotalDataCount,datasize);
152 :
153 : /*
154 : * Calculate how many parameters and data we can fit into
155 : * this packet. Parameters get precedence.
156 : */
157 :
158 0 : params_sent_thistime = MIN(params_to_send,useable_space);
159 0 : data_sent_thistime = useable_space - params_sent_thistime;
160 0 : data_sent_thistime = MIN(data_sent_thistime,data_to_send);
161 :
162 0 : SIVAL(req->outbuf, smb_ntr_ParameterCount,
163 : params_sent_thistime);
164 :
165 0 : if(params_sent_thistime == 0) {
166 0 : SIVAL(req->outbuf,smb_ntr_ParameterOffset,0);
167 0 : SIVAL(req->outbuf,smb_ntr_ParameterDisplacement,0);
168 : } else {
169 : /*
170 : * smb_ntr_ParameterOffset is the offset from the start of the SMB header to the
171 : * parameter bytes, however the first 4 bytes of outbuf are
172 : * the Netbios over TCP header. Thus use smb_base() to subtract
173 : * them from the calculation.
174 : */
175 :
176 0 : SIVAL(req->outbuf,smb_ntr_ParameterOffset,
177 : ((smb_buf(req->outbuf)+alignment_offset)
178 : - smb_base(req->outbuf)));
179 : /*
180 : * Absolute displacement of param bytes sent in this packet.
181 : */
182 :
183 0 : SIVAL(req->outbuf, smb_ntr_ParameterDisplacement,
184 : pp - params);
185 : }
186 :
187 : /*
188 : * Deal with the data portion.
189 : */
190 :
191 0 : SIVAL(req->outbuf, smb_ntr_DataCount, data_sent_thistime);
192 :
193 0 : if(data_sent_thistime == 0) {
194 0 : SIVAL(req->outbuf,smb_ntr_DataOffset,0);
195 0 : SIVAL(req->outbuf,smb_ntr_DataDisplacement, 0);
196 : } else {
197 : /*
198 : * The offset of the data bytes is the offset of the
199 : * parameter bytes plus the number of parameters being sent this time.
200 : */
201 :
202 0 : SIVAL(req->outbuf, smb_ntr_DataOffset,
203 : ((smb_buf(req->outbuf)+alignment_offset) -
204 : smb_base(req->outbuf))
205 : + params_sent_thistime + data_alignment_offset);
206 0 : SIVAL(req->outbuf,smb_ntr_DataDisplacement, pd - pdata);
207 : }
208 :
209 : /*
210 : * Copy the param bytes into the packet.
211 : */
212 :
213 0 : if(params_sent_thistime) {
214 0 : if (alignment_offset != 0) {
215 0 : memset(smb_buf(req->outbuf), 0,
216 : alignment_offset);
217 : }
218 0 : memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
219 : params_sent_thistime);
220 : }
221 :
222 : /*
223 : * Copy in the data bytes
224 : */
225 :
226 0 : if(data_sent_thistime) {
227 0 : if (data_alignment_offset != 0) {
228 0 : memset((smb_buf(req->outbuf)+alignment_offset+
229 : params_sent_thistime), 0,
230 : data_alignment_offset);
231 : }
232 0 : memcpy(smb_buf(req->outbuf)+alignment_offset
233 0 : +params_sent_thistime+data_alignment_offset,
234 : pd,data_sent_thistime);
235 : }
236 :
237 0 : DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
238 : params_sent_thistime, data_sent_thistime, useable_space));
239 0 : DEBUG(9,("nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
240 : params_to_send, data_to_send, paramsize, datasize));
241 :
242 0 : if (NT_STATUS_V(nt_error)) {
243 0 : error_packet_set((char *)req->outbuf,
244 : 0, 0, nt_error,
245 : __LINE__,__FILE__);
246 : }
247 :
248 : /* Send the packet */
249 0 : show_msg((char *)req->outbuf);
250 0 : if (!smb1_srv_send(xconn,
251 0 : (char *)req->outbuf,
252 0 : true, req->seqnum+1,
253 0 : IS_CONN_ENCRYPTED(conn),
254 : &req->pcd)) {
255 0 : exit_server_cleanly("send_nt_replies: smb1_srv_send failed.");
256 : }
257 :
258 0 : TALLOC_FREE(req->outbuf);
259 :
260 0 : pp += params_sent_thistime;
261 0 : pd += data_sent_thistime;
262 :
263 0 : params_to_send -= params_sent_thistime;
264 0 : data_to_send -= data_sent_thistime;
265 :
266 : /*
267 : * Sanity check
268 : */
269 :
270 0 : if(params_to_send < 0 || data_to_send < 0) {
271 0 : DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!",
272 : params_to_send, data_to_send));
273 0 : exit_server_cleanly("send_nt_replies: internal error");
274 : }
275 : }
276 : }
277 :
278 : /****************************************************************************
279 : Reply to an NT create and X call on a pipe
280 : ****************************************************************************/
281 :
282 0 : static void nt_open_pipe(char *fname, connection_struct *conn,
283 : struct smb_request *req, uint16_t *ppnum)
284 : {
285 : files_struct *fsp;
286 : NTSTATUS status;
287 :
288 0 : DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname));
289 :
290 : /* Strip \\ off the name if present. */
291 0 : while (fname[0] == '\\') {
292 0 : fname++;
293 : }
294 :
295 0 : status = open_np_file(req, fname, &fsp);
296 0 : if (!NT_STATUS_IS_OK(status)) {
297 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
298 0 : reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
299 : ERRDOS, ERRbadpipe);
300 0 : return;
301 : }
302 0 : reply_nterror(req, status);
303 0 : return;
304 : }
305 :
306 0 : *ppnum = fsp->fnum;
307 0 : return;
308 : }
309 :
310 : /****************************************************************************
311 : Reply to an NT create and X call for pipes.
312 : ****************************************************************************/
313 :
314 0 : static void do_ntcreate_pipe_open(connection_struct *conn,
315 : struct smb_request *req)
316 : {
317 0 : char *fname = NULL;
318 0 : uint16_t pnum = FNUM_FIELD_INVALID;
319 0 : char *p = NULL;
320 0 : uint32_t flags = IVAL(req->vwv+3, 1);
321 0 : TALLOC_CTX *ctx = talloc_tos();
322 :
323 0 : srvstr_pull_req_talloc(ctx, req, &fname, req->buf, STR_TERMINATE);
324 :
325 0 : if (!fname) {
326 0 : reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
327 : ERRDOS, ERRbadpipe);
328 0 : return;
329 : }
330 0 : nt_open_pipe(fname, conn, req, &pnum);
331 :
332 0 : if (req->outbuf) {
333 : /* error reply */
334 0 : return;
335 : }
336 :
337 : /*
338 : * Deal with pipe return.
339 : */
340 :
341 0 : if (flags & EXTENDED_RESPONSE_REQUIRED) {
342 : /* This is very strange. We
343 : * return 50 words, but only set
344 : * the wcnt to 42 ? It's definitely
345 : * what happens on the wire....
346 : */
347 0 : reply_smb1_outbuf(req, 50, 0);
348 0 : SCVAL(req->outbuf,smb_wct,42);
349 : } else {
350 0 : reply_smb1_outbuf(req, 34, 0);
351 : }
352 :
353 0 : SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
354 0 : SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
355 :
356 0 : p = (char *)req->outbuf + smb_vwv2;
357 0 : p++;
358 0 : SSVAL(p,0,pnum);
359 0 : p += 2;
360 0 : SIVAL(p,0,FILE_WAS_OPENED);
361 0 : p += 4;
362 0 : p += 32;
363 0 : SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */
364 0 : p += 20;
365 : /* File type. */
366 0 : SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE);
367 : /* Device state. */
368 0 : SSVAL(p,2, 0x5FF); /* ? */
369 0 : p += 4;
370 :
371 0 : if (flags & EXTENDED_RESPONSE_REQUIRED) {
372 0 : p += 25;
373 0 : SIVAL(p,0,FILE_GENERIC_ALL);
374 : /*
375 : * For pipes W2K3 seems to return
376 : * 0x12019B next.
377 : * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA)
378 : */
379 0 : SIVAL(p,4,(FILE_GENERIC_READ|FILE_GENERIC_WRITE)&~FILE_APPEND_DATA);
380 : }
381 :
382 0 : DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname));
383 : }
384 :
385 : struct case_semantics_state {
386 : connection_struct *conn;
387 : bool case_sensitive;
388 : bool case_preserve;
389 : bool short_case_preserve;
390 : };
391 :
392 : /****************************************************************************
393 : Restore case semantics.
394 : ****************************************************************************/
395 :
396 0 : static int restore_case_semantics(struct case_semantics_state *state)
397 : {
398 0 : state->conn->case_sensitive = state->case_sensitive;
399 0 : state->conn->case_preserve = state->case_preserve;
400 0 : state->conn->short_case_preserve = state->short_case_preserve;
401 0 : return 0;
402 : }
403 :
404 : /****************************************************************************
405 : Save case semantics.
406 : ****************************************************************************/
407 :
408 0 : static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx,
409 : connection_struct *conn)
410 : {
411 : struct case_semantics_state *result;
412 :
413 0 : if (!(result = talloc(mem_ctx, struct case_semantics_state))) {
414 0 : return NULL;
415 : }
416 :
417 0 : result->conn = conn;
418 0 : result->case_sensitive = conn->case_sensitive;
419 0 : result->case_preserve = conn->case_preserve;
420 0 : result->short_case_preserve = conn->short_case_preserve;
421 :
422 : /* Set to POSIX. */
423 0 : conn->case_sensitive = True;
424 0 : conn->case_preserve = True;
425 0 : conn->short_case_preserve = True;
426 :
427 0 : talloc_set_destructor(result, restore_case_semantics);
428 :
429 0 : return result;
430 : }
431 :
432 : /*
433 : * Calculate the full path name given a relative fid.
434 : */
435 0 : static NTSTATUS get_relative_fid_filename(connection_struct *conn,
436 : struct smb_request *req,
437 : uint16_t root_dir_fid,
438 : char *path,
439 : char **path_out)
440 : {
441 0 : struct files_struct *dir_fsp = NULL;
442 0 : char *new_path = NULL;
443 :
444 0 : if (root_dir_fid == 0 || path == NULL) {
445 0 : return NT_STATUS_INTERNAL_ERROR;
446 : }
447 :
448 0 : dir_fsp = file_fsp(req, root_dir_fid);
449 0 : if (dir_fsp == NULL) {
450 0 : return NT_STATUS_INVALID_HANDLE;
451 : }
452 :
453 0 : if (fsp_is_alternate_stream(dir_fsp)) {
454 0 : return NT_STATUS_INVALID_HANDLE;
455 : }
456 :
457 0 : if (!dir_fsp->fsp_flags.is_directory) {
458 : /*
459 : * Check to see if this is a mac fork of some kind.
460 : */
461 0 : if (conn->fs_capabilities & FILE_NAMED_STREAMS) {
462 0 : char *stream = NULL;
463 :
464 0 : stream = strchr_m(path, ':');
465 0 : if (stream != NULL) {
466 0 : return NT_STATUS_OBJECT_PATH_NOT_FOUND;
467 : }
468 : }
469 :
470 : /*
471 : * We need to handle the case when we get a relative open
472 : * relative to a file and the pathname is blank - this is a
473 : * reopen! (hint from demyn plantenberg)
474 : */
475 0 : return NT_STATUS_INVALID_HANDLE;
476 : }
477 :
478 0 : if (ISDOT(dir_fsp->fsp_name->base_name)) {
479 : /*
480 : * We're at the toplevel dir, the final file name
481 : * must not contain ./, as this is filtered out
482 : * normally by srvstr_get_path and unix_convert
483 : * explicitly rejects paths containing ./.
484 : */
485 0 : new_path = talloc_strdup(talloc_tos(), path);
486 : } else {
487 : /*
488 : * Copy in the base directory name.
489 : */
490 :
491 0 : new_path = talloc_asprintf(talloc_tos(),
492 : "%s/%s",
493 0 : dir_fsp->fsp_name->base_name,
494 : path);
495 : }
496 0 : if (new_path == NULL) {
497 0 : return NT_STATUS_NO_MEMORY;
498 : }
499 :
500 0 : *path_out = new_path;
501 0 : return NT_STATUS_OK;
502 : }
503 :
504 : /****************************************************************************
505 : Reply to an NT create and X call.
506 : ****************************************************************************/
507 :
508 0 : void reply_ntcreate_and_X(struct smb_request *req)
509 : {
510 0 : connection_struct *conn = req->conn;
511 0 : struct files_struct *dirfsp = NULL;
512 0 : struct smb_filename *smb_fname = NULL;
513 0 : char *fname = NULL;
514 : uint32_t flags;
515 : uint32_t access_mask;
516 : uint32_t file_attributes;
517 : uint32_t share_access;
518 : uint32_t create_disposition;
519 : uint32_t create_options;
520 : uint16_t root_dir_fid;
521 : uint64_t allocation_size;
522 : /* Breakout the oplock request bits so we can set the
523 : reply bits separately. */
524 0 : uint32_t fattr=0;
525 0 : off_t file_len = 0;
526 0 : int info = 0;
527 0 : files_struct *fsp = NULL;
528 0 : char *p = NULL;
529 : struct timespec create_timespec;
530 : struct timespec c_timespec;
531 : struct timespec a_timespec;
532 : struct timespec m_timespec;
533 : NTSTATUS status;
534 : int oplock_request;
535 0 : uint8_t oplock_granted = NO_OPLOCK_RETURN;
536 0 : struct case_semantics_state *case_state = NULL;
537 : uint32_t ucf_flags;
538 0 : NTTIME twrp = 0;
539 0 : TALLOC_CTX *ctx = talloc_tos();
540 :
541 0 : START_PROFILE(SMBntcreateX);
542 :
543 0 : if (req->wct < 24) {
544 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
545 0 : goto out;
546 : }
547 :
548 0 : flags = IVAL(req->vwv+3, 1);
549 0 : access_mask = IVAL(req->vwv+7, 1);
550 0 : file_attributes = IVAL(req->vwv+13, 1);
551 0 : share_access = IVAL(req->vwv+15, 1);
552 0 : create_disposition = IVAL(req->vwv+17, 1);
553 0 : create_options = IVAL(req->vwv+19, 1);
554 0 : root_dir_fid = (uint16_t)IVAL(req->vwv+5, 1);
555 :
556 0 : allocation_size = BVAL(req->vwv+9, 1);
557 :
558 0 : srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
559 : STR_TERMINATE, &status);
560 :
561 0 : if (!NT_STATUS_IS_OK(status)) {
562 0 : reply_nterror(req, status);
563 0 : goto out;
564 : }
565 :
566 0 : DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x "
567 : "file_attributes = 0x%x, share_access = 0x%x, "
568 : "create_disposition = 0x%x create_options = 0x%x "
569 : "root_dir_fid = 0x%x, fname = %s\n",
570 : (unsigned int)flags,
571 : (unsigned int)access_mask,
572 : (unsigned int)file_attributes,
573 : (unsigned int)share_access,
574 : (unsigned int)create_disposition,
575 : (unsigned int)create_options,
576 : (unsigned int)root_dir_fid,
577 : fname));
578 :
579 : /*
580 : * we need to remove ignored bits when they come directly from the client
581 : * because we reuse some of them for internal stuff
582 : */
583 0 : create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
584 :
585 : /*
586 : * If it's an IPC, use the pipe handler.
587 : */
588 :
589 0 : if (IS_IPC(conn)) {
590 0 : if (lp_nt_pipe_support()) {
591 0 : do_ntcreate_pipe_open(conn, req);
592 0 : goto out;
593 : }
594 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
595 0 : goto out;
596 : }
597 :
598 0 : oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
599 0 : if (oplock_request) {
600 0 : oplock_request |= (flags & REQUEST_BATCH_OPLOCK)
601 0 : ? BATCH_OPLOCK : 0;
602 : }
603 :
604 0 : if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
605 0 : case_state = set_posix_case_semantics(ctx, conn);
606 0 : if (!case_state) {
607 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
608 0 : goto out;
609 : }
610 : }
611 :
612 0 : if (root_dir_fid != 0) {
613 0 : char *new_fname = NULL;
614 :
615 0 : status = get_relative_fid_filename(conn,
616 : req,
617 : root_dir_fid,
618 : fname,
619 : &new_fname);
620 0 : if (!NT_STATUS_IS_OK(status)) {
621 0 : reply_nterror(req, status);
622 0 : goto out;
623 : }
624 0 : fname = new_fname;
625 : }
626 :
627 0 : ucf_flags = filename_create_ucf_flags(req, create_disposition);
628 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
629 0 : extract_snapshot_token(fname, &twrp);
630 : }
631 0 : status = filename_convert_dirfsp(
632 : ctx, conn, fname, ucf_flags, twrp, &dirfsp, &smb_fname);
633 :
634 0 : TALLOC_FREE(case_state);
635 :
636 0 : if (!NT_STATUS_IS_OK(status)) {
637 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
638 0 : reply_botherror(req,
639 : NT_STATUS_PATH_NOT_COVERED,
640 : ERRSRV, ERRbadpath);
641 0 : goto out;
642 : }
643 0 : reply_nterror(req, status);
644 0 : goto out;
645 : }
646 :
647 : /*
648 : * Bug #6898 - clients using Windows opens should
649 : * never be able to set this attribute into the
650 : * VFS.
651 : */
652 0 : file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
653 :
654 0 : status = SMB_VFS_CREATE_FILE(
655 : conn, /* conn */
656 : req, /* req */
657 : dirfsp, /* dirfsp */
658 : smb_fname, /* fname */
659 : access_mask, /* access_mask */
660 : share_access, /* share_access */
661 : create_disposition, /* create_disposition*/
662 : create_options, /* create_options */
663 : file_attributes, /* file_attributes */
664 : oplock_request, /* oplock_request */
665 : NULL, /* lease */
666 : allocation_size, /* allocation_size */
667 : 0, /* private_flags */
668 : NULL, /* sd */
669 : NULL, /* ea_list */
670 : &fsp, /* result */
671 : &info, /* pinfo */
672 : NULL, NULL); /* create context */
673 :
674 0 : if (!NT_STATUS_IS_OK(status)) {
675 0 : if (open_was_deferred(req->xconn, req->mid)) {
676 : /* We have re-scheduled this call, no error. */
677 0 : goto out;
678 : }
679 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
680 0 : bool ok = defer_smb1_sharing_violation(req);
681 0 : if (ok) {
682 0 : goto out;
683 : }
684 : }
685 0 : reply_openerror(req, status);
686 0 : goto out;
687 : }
688 :
689 : /* Ensure we're pointing at the correct stat struct. */
690 0 : smb_fname = fsp->fsp_name;
691 :
692 : /*
693 : * If the caller set the extended oplock request bit
694 : * and we granted one (by whatever means) - set the
695 : * correct bit for extended oplock reply.
696 : */
697 :
698 0 : if (oplock_request &&
699 0 : (lp_fake_oplocks(SNUM(conn))
700 0 : || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) {
701 :
702 : /*
703 : * Exclusive oplock granted
704 : */
705 :
706 0 : if (flags & REQUEST_BATCH_OPLOCK) {
707 0 : oplock_granted = BATCH_OPLOCK_RETURN;
708 : } else {
709 0 : oplock_granted = EXCLUSIVE_OPLOCK_RETURN;
710 : }
711 0 : } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
712 0 : oplock_granted = LEVEL_II_OPLOCK_RETURN;
713 : } else {
714 0 : oplock_granted = NO_OPLOCK_RETURN;
715 : }
716 :
717 0 : file_len = smb_fname->st.st_ex_size;
718 :
719 0 : if (flags & EXTENDED_RESPONSE_REQUIRED) {
720 : /* This is very strange. We
721 : * return 50 words, but only set
722 : * the wcnt to 42 ? It's definitely
723 : * what happens on the wire....
724 : */
725 0 : reply_smb1_outbuf(req, 50, 0);
726 0 : SCVAL(req->outbuf,smb_wct,42);
727 : } else {
728 0 : reply_smb1_outbuf(req, 34, 0);
729 : }
730 :
731 0 : SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
732 0 : SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
733 :
734 0 : p = (char *)req->outbuf + smb_vwv2;
735 :
736 0 : SCVAL(p, 0, oplock_granted);
737 :
738 0 : p++;
739 0 : SSVAL(p,0,fsp->fnum);
740 0 : p += 2;
741 0 : if ((create_disposition == FILE_SUPERSEDE)
742 0 : && (info == FILE_WAS_OVERWRITTEN)) {
743 0 : SIVAL(p,0,FILE_WAS_SUPERSEDED);
744 : } else {
745 0 : SIVAL(p,0,info);
746 : }
747 0 : p += 4;
748 :
749 0 : fattr = fdos_mode(fsp);
750 0 : if (fattr == 0) {
751 0 : fattr = FILE_ATTRIBUTE_NORMAL;
752 : }
753 :
754 : /* Create time. */
755 0 : create_timespec = get_create_timespec(conn, fsp, smb_fname);
756 0 : a_timespec = smb_fname->st.st_ex_atime;
757 0 : m_timespec = smb_fname->st.st_ex_mtime;
758 0 : c_timespec = get_change_timespec(conn, fsp, smb_fname);
759 :
760 0 : if (lp_dos_filetime_resolution(SNUM(conn))) {
761 0 : dos_filetime_timespec(&create_timespec);
762 0 : dos_filetime_timespec(&a_timespec);
763 0 : dos_filetime_timespec(&m_timespec);
764 0 : dos_filetime_timespec(&c_timespec);
765 : }
766 :
767 0 : put_long_date_full_timespec(conn->ts_res, p, &create_timespec); /* create time. */
768 0 : p += 8;
769 0 : put_long_date_full_timespec(conn->ts_res, p, &a_timespec); /* access time */
770 0 : p += 8;
771 0 : put_long_date_full_timespec(conn->ts_res, p, &m_timespec); /* write time */
772 0 : p += 8;
773 0 : put_long_date_full_timespec(conn->ts_res, p, &c_timespec); /* change time */
774 0 : p += 8;
775 0 : SIVAL(p,0,fattr); /* File Attributes. */
776 0 : p += 4;
777 0 : SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&smb_fname->st));
778 0 : p += 8;
779 0 : SOFF_T(p,0,file_len);
780 0 : p += 8;
781 0 : if (flags & EXTENDED_RESPONSE_REQUIRED) {
782 0 : uint16_t file_status = (NO_EAS|NO_SUBSTREAMS|NO_REPARSETAG);
783 0 : unsigned int num_streams = 0;
784 0 : struct stream_struct *streams = NULL;
785 :
786 0 : if (lp_ea_support(SNUM(conn))) {
787 0 : size_t num_names = 0;
788 : /* Do we have any EA's ? */
789 0 : status = get_ea_names_from_fsp(
790 0 : ctx, smb_fname->fsp, NULL, &num_names);
791 0 : if (NT_STATUS_IS_OK(status) && num_names) {
792 0 : file_status &= ~NO_EAS;
793 : }
794 : }
795 :
796 0 : status = vfs_fstreaminfo(smb_fname->fsp, ctx,
797 : &num_streams, &streams);
798 : /* There is always one stream, ::$DATA. */
799 0 : if (NT_STATUS_IS_OK(status) && num_streams > 1) {
800 0 : file_status &= ~NO_SUBSTREAMS;
801 : }
802 0 : TALLOC_FREE(streams);
803 0 : SSVAL(p,2,file_status);
804 : }
805 0 : p += 4;
806 0 : SCVAL(p,0,fsp->fsp_flags.is_directory ? 1 : 0);
807 :
808 0 : if (flags & EXTENDED_RESPONSE_REQUIRED) {
809 0 : uint32_t perms = 0;
810 0 : p += 25;
811 0 : if (fsp->fsp_flags.is_directory ||
812 0 : fsp->fsp_flags.can_write ||
813 0 : can_write_to_fsp(fsp))
814 : {
815 0 : perms = FILE_GENERIC_ALL;
816 : } else {
817 0 : perms = FILE_GENERIC_READ|FILE_EXECUTE;
818 : }
819 0 : SIVAL(p,0,perms);
820 : }
821 :
822 0 : DEBUG(5,("reply_ntcreate_and_X: %s, open name = %s\n",
823 : fsp_fnum_dbg(fsp), smb_fname_str_dbg(smb_fname)));
824 :
825 0 : out:
826 0 : END_PROFILE(SMBntcreateX);
827 0 : return;
828 : }
829 :
830 : /****************************************************************************
831 : Reply to a NT_TRANSACT_CREATE call to open a pipe.
832 : ****************************************************************************/
833 :
834 0 : static void do_nt_transact_create_pipe(connection_struct *conn,
835 : struct smb_request *req,
836 : uint16_t **ppsetup, uint32_t setup_count,
837 : char **ppparams, uint32_t parameter_count,
838 : char **ppdata, uint32_t data_count)
839 : {
840 0 : char *fname = NULL;
841 0 : char *params = *ppparams;
842 0 : uint16_t pnum = FNUM_FIELD_INVALID;
843 0 : char *p = NULL;
844 : NTSTATUS status;
845 : size_t param_len;
846 : uint32_t flags;
847 0 : TALLOC_CTX *ctx = talloc_tos();
848 :
849 : /*
850 : * Ensure minimum number of parameters sent.
851 : */
852 :
853 0 : if(parameter_count < 54) {
854 0 : DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)parameter_count));
855 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
856 0 : return;
857 : }
858 :
859 0 : flags = IVAL(params,0);
860 :
861 0 : if (req->posix_pathnames) {
862 0 : srvstr_get_path_posix(ctx,
863 : params,
864 0 : req->flags2,
865 : &fname,
866 0 : params+53,
867 0 : parameter_count-53,
868 : STR_TERMINATE,
869 : &status);
870 : } else {
871 0 : srvstr_get_path(ctx,
872 : params,
873 0 : req->flags2,
874 : &fname,
875 0 : params+53,
876 0 : parameter_count-53,
877 : STR_TERMINATE,
878 : &status);
879 : }
880 0 : if (!NT_STATUS_IS_OK(status)) {
881 0 : reply_nterror(req, status);
882 0 : return;
883 : }
884 :
885 0 : nt_open_pipe(fname, conn, req, &pnum);
886 :
887 0 : if (req->outbuf) {
888 : /* Error return */
889 0 : return;
890 : }
891 :
892 : /* Realloc the size of parameters and data we will return */
893 0 : if (flags & EXTENDED_RESPONSE_REQUIRED) {
894 : /* Extended response is 32 more byyes. */
895 0 : param_len = 101;
896 : } else {
897 0 : param_len = 69;
898 : }
899 0 : params = nttrans_realloc(ppparams, param_len);
900 0 : if(params == NULL) {
901 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
902 0 : return;
903 : }
904 :
905 0 : p = params;
906 0 : SCVAL(p,0,NO_OPLOCK_RETURN);
907 :
908 0 : p += 2;
909 0 : SSVAL(p,0,pnum);
910 0 : p += 2;
911 0 : SIVAL(p,0,FILE_WAS_OPENED);
912 0 : p += 8;
913 :
914 0 : p += 32;
915 0 : SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */
916 0 : p += 20;
917 : /* File type. */
918 0 : SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE);
919 : /* Device state. */
920 0 : SSVAL(p,2, 0x5FF); /* ? */
921 0 : p += 4;
922 :
923 0 : if (flags & EXTENDED_RESPONSE_REQUIRED) {
924 0 : p += 25;
925 0 : SIVAL(p,0,FILE_GENERIC_ALL);
926 : /*
927 : * For pipes W2K3 seems to return
928 : * 0x12019B next.
929 : * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA)
930 : */
931 0 : SIVAL(p,4,(FILE_GENERIC_READ|FILE_GENERIC_WRITE)&~FILE_APPEND_DATA);
932 : }
933 :
934 0 : DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
935 :
936 : /* Send the required number of replies */
937 0 : send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
938 :
939 0 : return;
940 : }
941 :
942 : /****************************************************************************
943 : Reply to a NT_TRANSACT_CREATE call (needs to process SD's).
944 : ****************************************************************************/
945 :
946 0 : static void call_nt_transact_create(connection_struct *conn,
947 : struct smb_request *req,
948 : uint16_t **ppsetup, uint32_t setup_count,
949 : char **ppparams, uint32_t parameter_count,
950 : char **ppdata, uint32_t data_count,
951 : uint32_t max_data_count)
952 : {
953 0 : struct smb_filename *smb_fname = NULL;
954 0 : char *fname = NULL;
955 0 : char *params = *ppparams;
956 0 : char *data = *ppdata;
957 : /* Breakout the oplock request bits so we can set the reply bits separately. */
958 0 : uint32_t fattr=0;
959 0 : off_t file_len = 0;
960 0 : int info = 0;
961 0 : struct files_struct *dirfsp = NULL;
962 0 : files_struct *fsp = NULL;
963 0 : char *p = NULL;
964 : uint32_t flags;
965 : uint32_t access_mask;
966 : uint32_t file_attributes;
967 : uint32_t share_access;
968 : uint32_t create_disposition;
969 : uint32_t create_options;
970 : uint32_t sd_len;
971 0 : struct security_descriptor *sd = NULL;
972 : uint32_t ea_len;
973 : uint16_t root_dir_fid;
974 : struct timespec create_timespec;
975 : struct timespec c_timespec;
976 : struct timespec a_timespec;
977 : struct timespec m_timespec;
978 0 : struct ea_list *ea_list = NULL;
979 : NTSTATUS status;
980 : size_t param_len;
981 : uint64_t allocation_size;
982 : int oplock_request;
983 : uint8_t oplock_granted;
984 0 : struct case_semantics_state *case_state = NULL;
985 : uint32_t ucf_flags;
986 0 : NTTIME twrp = 0;
987 0 : TALLOC_CTX *ctx = talloc_tos();
988 :
989 0 : DEBUG(5,("call_nt_transact_create\n"));
990 :
991 : /*
992 : * If it's an IPC, use the pipe handler.
993 : */
994 :
995 0 : if (IS_IPC(conn)) {
996 0 : if (lp_nt_pipe_support()) {
997 0 : do_nt_transact_create_pipe(
998 : conn, req,
999 : ppsetup, setup_count,
1000 : ppparams, parameter_count,
1001 : ppdata, data_count);
1002 0 : goto out;
1003 : }
1004 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1005 0 : goto out;
1006 : }
1007 :
1008 : /*
1009 : * Ensure minimum number of parameters sent.
1010 : */
1011 :
1012 0 : if(parameter_count < 54) {
1013 0 : DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count));
1014 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1015 0 : goto out;
1016 : }
1017 :
1018 0 : flags = IVAL(params,0);
1019 0 : access_mask = IVAL(params,8);
1020 0 : file_attributes = IVAL(params,20);
1021 0 : share_access = IVAL(params,24);
1022 0 : create_disposition = IVAL(params,28);
1023 0 : create_options = IVAL(params,32);
1024 0 : sd_len = IVAL(params,36);
1025 0 : ea_len = IVAL(params,40);
1026 0 : root_dir_fid = (uint16_t)IVAL(params,4);
1027 0 : allocation_size = BVAL(params,12);
1028 :
1029 : /*
1030 : * we need to remove ignored bits when they come directly from the client
1031 : * because we reuse some of them for internal stuff
1032 : */
1033 0 : create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
1034 :
1035 0 : if (req->posix_pathnames) {
1036 0 : srvstr_get_path_posix(ctx,
1037 : params,
1038 0 : req->flags2,
1039 : &fname,
1040 0 : params+53,
1041 0 : parameter_count-53,
1042 : STR_TERMINATE,
1043 : &status);
1044 : } else {
1045 0 : srvstr_get_path(ctx,
1046 : params,
1047 0 : req->flags2,
1048 : &fname,
1049 0 : params+53,
1050 0 : parameter_count-53,
1051 : STR_TERMINATE,
1052 : &status);
1053 : }
1054 0 : if (!NT_STATUS_IS_OK(status)) {
1055 0 : reply_nterror(req, status);
1056 0 : goto out;
1057 : }
1058 :
1059 0 : if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
1060 0 : case_state = set_posix_case_semantics(ctx, conn);
1061 0 : if (!case_state) {
1062 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1063 0 : goto out;
1064 : }
1065 : }
1066 :
1067 0 : if (root_dir_fid != 0) {
1068 0 : char *new_fname = NULL;
1069 :
1070 0 : status = get_relative_fid_filename(conn,
1071 : req,
1072 : root_dir_fid,
1073 : fname,
1074 : &new_fname);
1075 0 : if (!NT_STATUS_IS_OK(status)) {
1076 0 : reply_nterror(req, status);
1077 0 : goto out;
1078 : }
1079 0 : fname = new_fname;
1080 : }
1081 :
1082 0 : ucf_flags = filename_create_ucf_flags(req, create_disposition);
1083 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
1084 0 : extract_snapshot_token(fname, &twrp);
1085 : }
1086 0 : status = filename_convert_dirfsp(ctx,
1087 : conn,
1088 : fname,
1089 : ucf_flags,
1090 : twrp,
1091 : &dirfsp,
1092 : &smb_fname);
1093 :
1094 0 : TALLOC_FREE(case_state);
1095 :
1096 0 : if (!NT_STATUS_IS_OK(status)) {
1097 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1098 0 : reply_botherror(req,
1099 : NT_STATUS_PATH_NOT_COVERED,
1100 : ERRSRV, ERRbadpath);
1101 0 : goto out;
1102 : }
1103 0 : reply_nterror(req, status);
1104 0 : goto out;
1105 : }
1106 :
1107 : /* Ensure the data_len is correct for the sd and ea values given. */
1108 0 : if ((ea_len + sd_len > data_count)
1109 0 : || (ea_len > data_count) || (sd_len > data_count)
1110 0 : || (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) {
1111 0 : DEBUG(10, ("call_nt_transact_create - ea_len = %u, sd_len = "
1112 : "%u, data_count = %u\n", (unsigned int)ea_len,
1113 : (unsigned int)sd_len, (unsigned int)data_count));
1114 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1115 0 : goto out;
1116 : }
1117 :
1118 0 : if (sd_len) {
1119 0 : DEBUG(10, ("call_nt_transact_create - sd_len = %d\n",
1120 : sd_len));
1121 :
1122 0 : status = unmarshall_sec_desc(ctx, (uint8_t *)data, sd_len,
1123 : &sd);
1124 0 : if (!NT_STATUS_IS_OK(status)) {
1125 0 : DEBUG(10, ("call_nt_transact_create: "
1126 : "unmarshall_sec_desc failed: %s\n",
1127 : nt_errstr(status)));
1128 0 : reply_nterror(req, status);
1129 0 : goto out;
1130 : }
1131 : }
1132 :
1133 0 : if (ea_len) {
1134 0 : if (!lp_ea_support(SNUM(conn))) {
1135 0 : DEBUG(10, ("call_nt_transact_create - ea_len = %u but "
1136 : "EA's not supported.\n",
1137 : (unsigned int)ea_len));
1138 0 : reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1139 0 : goto out;
1140 : }
1141 :
1142 0 : if (ea_len < 10) {
1143 0 : DEBUG(10,("call_nt_transact_create - ea_len = %u - "
1144 : "too small (should be more than 10)\n",
1145 : (unsigned int)ea_len ));
1146 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1147 0 : goto out;
1148 : }
1149 :
1150 : /* We have already checked that ea_len <= data_count here. */
1151 0 : ea_list = read_nttrans_ea_list(talloc_tos(), data + sd_len,
1152 : ea_len);
1153 0 : if (ea_list == NULL) {
1154 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1155 0 : goto out;
1156 : }
1157 :
1158 0 : if (!req->posix_pathnames &&
1159 0 : ea_list_has_invalid_name(ea_list)) {
1160 : /* Realloc the size of parameters and data we will return */
1161 0 : if (flags & EXTENDED_RESPONSE_REQUIRED) {
1162 : /* Extended response is 32 more bytes. */
1163 0 : param_len = 101;
1164 : } else {
1165 0 : param_len = 69;
1166 : }
1167 0 : params = nttrans_realloc(ppparams, param_len);
1168 0 : if(params == NULL) {
1169 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1170 0 : goto out;
1171 : }
1172 :
1173 0 : memset(params, '\0', param_len);
1174 0 : send_nt_replies(conn, req, STATUS_INVALID_EA_NAME,
1175 : params, param_len, NULL, 0);
1176 0 : goto out;
1177 : }
1178 : }
1179 :
1180 0 : oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1181 0 : if (oplock_request) {
1182 0 : oplock_request |= (flags & REQUEST_BATCH_OPLOCK)
1183 0 : ? BATCH_OPLOCK : 0;
1184 : }
1185 :
1186 : /*
1187 : * Bug #6898 - clients using Windows opens should
1188 : * never be able to set this attribute into the
1189 : * VFS.
1190 : */
1191 0 : file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
1192 :
1193 0 : status = SMB_VFS_CREATE_FILE(
1194 : conn, /* conn */
1195 : req, /* req */
1196 : dirfsp, /* dirfsp */
1197 : smb_fname, /* fname */
1198 : access_mask, /* access_mask */
1199 : share_access, /* share_access */
1200 : create_disposition, /* create_disposition*/
1201 : create_options, /* create_options */
1202 : file_attributes, /* file_attributes */
1203 : oplock_request, /* oplock_request */
1204 : NULL, /* lease */
1205 : allocation_size, /* allocation_size */
1206 : 0, /* private_flags */
1207 : sd, /* sd */
1208 : ea_list, /* ea_list */
1209 : &fsp, /* result */
1210 : &info, /* pinfo */
1211 : NULL, NULL); /* create context */
1212 :
1213 0 : if(!NT_STATUS_IS_OK(status)) {
1214 0 : if (open_was_deferred(req->xconn, req->mid)) {
1215 : /* We have re-scheduled this call, no error. */
1216 0 : return;
1217 : }
1218 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1219 0 : bool ok = defer_smb1_sharing_violation(req);
1220 0 : if (ok) {
1221 0 : return;
1222 : }
1223 : }
1224 0 : reply_openerror(req, status);
1225 0 : goto out;
1226 : }
1227 :
1228 : /* Ensure we're pointing at the correct stat struct. */
1229 0 : TALLOC_FREE(smb_fname);
1230 0 : smb_fname = fsp->fsp_name;
1231 :
1232 : /*
1233 : * If the caller set the extended oplock request bit
1234 : * and we granted one (by whatever means) - set the
1235 : * correct bit for extended oplock reply.
1236 : */
1237 :
1238 0 : if (oplock_request &&
1239 0 : (lp_fake_oplocks(SNUM(conn))
1240 0 : || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) {
1241 :
1242 : /*
1243 : * Exclusive oplock granted
1244 : */
1245 :
1246 0 : if (flags & REQUEST_BATCH_OPLOCK) {
1247 0 : oplock_granted = BATCH_OPLOCK_RETURN;
1248 : } else {
1249 0 : oplock_granted = EXCLUSIVE_OPLOCK_RETURN;
1250 : }
1251 0 : } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
1252 0 : oplock_granted = LEVEL_II_OPLOCK_RETURN;
1253 : } else {
1254 0 : oplock_granted = NO_OPLOCK_RETURN;
1255 : }
1256 :
1257 0 : file_len = smb_fname->st.st_ex_size;
1258 :
1259 : /* Realloc the size of parameters and data we will return */
1260 0 : if (flags & EXTENDED_RESPONSE_REQUIRED) {
1261 : /* Extended response is 32 more byyes. */
1262 0 : param_len = 101;
1263 : } else {
1264 0 : param_len = 69;
1265 : }
1266 0 : params = nttrans_realloc(ppparams, param_len);
1267 0 : if(params == NULL) {
1268 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1269 0 : goto out;
1270 : }
1271 :
1272 0 : p = params;
1273 0 : SCVAL(p, 0, oplock_granted);
1274 :
1275 0 : p += 2;
1276 0 : SSVAL(p,0,fsp->fnum);
1277 0 : p += 2;
1278 0 : if ((create_disposition == FILE_SUPERSEDE)
1279 0 : && (info == FILE_WAS_OVERWRITTEN)) {
1280 0 : SIVAL(p,0,FILE_WAS_SUPERSEDED);
1281 : } else {
1282 0 : SIVAL(p,0,info);
1283 : }
1284 0 : p += 8;
1285 :
1286 0 : fattr = fdos_mode(fsp);
1287 0 : if (fattr == 0) {
1288 0 : fattr = FILE_ATTRIBUTE_NORMAL;
1289 : }
1290 :
1291 : /* Create time. */
1292 0 : create_timespec = get_create_timespec(conn, fsp, smb_fname);
1293 0 : a_timespec = smb_fname->st.st_ex_atime;
1294 0 : m_timespec = smb_fname->st.st_ex_mtime;
1295 0 : c_timespec = get_change_timespec(conn, fsp, smb_fname);
1296 :
1297 0 : if (lp_dos_filetime_resolution(SNUM(conn))) {
1298 0 : dos_filetime_timespec(&create_timespec);
1299 0 : dos_filetime_timespec(&a_timespec);
1300 0 : dos_filetime_timespec(&m_timespec);
1301 0 : dos_filetime_timespec(&c_timespec);
1302 : }
1303 :
1304 0 : put_long_date_full_timespec(conn->ts_res, p, &create_timespec); /* create time. */
1305 0 : p += 8;
1306 0 : put_long_date_full_timespec(conn->ts_res, p, &a_timespec); /* access time */
1307 0 : p += 8;
1308 0 : put_long_date_full_timespec(conn->ts_res, p, &m_timespec); /* write time */
1309 0 : p += 8;
1310 0 : put_long_date_full_timespec(conn->ts_res, p, &c_timespec); /* change time */
1311 0 : p += 8;
1312 0 : SIVAL(p,0,fattr); /* File Attributes. */
1313 0 : p += 4;
1314 0 : SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st));
1315 0 : p += 8;
1316 0 : SOFF_T(p,0,file_len);
1317 0 : p += 8;
1318 0 : if (flags & EXTENDED_RESPONSE_REQUIRED) {
1319 0 : uint16_t file_status = (NO_EAS|NO_SUBSTREAMS|NO_REPARSETAG);
1320 0 : unsigned int num_streams = 0;
1321 0 : struct stream_struct *streams = NULL;
1322 :
1323 0 : if (lp_ea_support(SNUM(conn))) {
1324 0 : size_t num_names = 0;
1325 : /* Do we have any EA's ? */
1326 0 : status = get_ea_names_from_fsp(
1327 0 : ctx, smb_fname->fsp, NULL, &num_names);
1328 0 : if (NT_STATUS_IS_OK(status) && num_names) {
1329 0 : file_status &= ~NO_EAS;
1330 : }
1331 : }
1332 :
1333 0 : status = vfs_fstreaminfo(smb_fname->fsp, ctx,
1334 : &num_streams, &streams);
1335 : /* There is always one stream, ::$DATA. */
1336 0 : if (NT_STATUS_IS_OK(status) && num_streams > 1) {
1337 0 : file_status &= ~NO_SUBSTREAMS;
1338 : }
1339 0 : TALLOC_FREE(streams);
1340 0 : SSVAL(p,2,file_status);
1341 : }
1342 0 : p += 4;
1343 0 : SCVAL(p,0,fsp->fsp_flags.is_directory ? 1 : 0);
1344 :
1345 0 : if (flags & EXTENDED_RESPONSE_REQUIRED) {
1346 0 : uint32_t perms = 0;
1347 0 : p += 25;
1348 0 : if (fsp->fsp_flags.is_directory ||
1349 0 : fsp->fsp_flags.can_write ||
1350 0 : can_write_to_fsp(fsp))
1351 : {
1352 0 : perms = FILE_GENERIC_ALL;
1353 : } else {
1354 0 : perms = FILE_GENERIC_READ|FILE_EXECUTE;
1355 : }
1356 0 : SIVAL(p,0,perms);
1357 : }
1358 :
1359 0 : DEBUG(5,("call_nt_transact_create: open name = %s\n",
1360 : smb_fname_str_dbg(smb_fname)));
1361 :
1362 : /* Send the required number of replies */
1363 0 : send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
1364 0 : out:
1365 0 : return;
1366 : }
1367 :
1368 : /****************************************************************************
1369 : Reply to a NT CANCEL request.
1370 : conn POINTER CAN BE NULL HERE !
1371 : ****************************************************************************/
1372 :
1373 0 : void reply_ntcancel(struct smb_request *req)
1374 : {
1375 0 : struct smbXsrv_connection *xconn = req->xconn;
1376 0 : struct smbd_server_connection *sconn = req->sconn;
1377 : bool found;
1378 :
1379 : /*
1380 : * Go through and cancel any pending change notifies.
1381 : */
1382 :
1383 0 : START_PROFILE(SMBntcancel);
1384 0 : smb1_srv_cancel_sign_response(xconn);
1385 0 : found = remove_pending_change_notify_requests_by_mid(sconn, req->mid);
1386 0 : if (!found) {
1387 0 : smbd_smb1_brl_finish_by_mid(sconn, req->mid);
1388 : }
1389 :
1390 0 : DEBUG(3,("reply_ntcancel: cancel called on mid = %llu.\n",
1391 : (unsigned long long)req->mid));
1392 :
1393 0 : END_PROFILE(SMBntcancel);
1394 0 : return;
1395 : }
1396 :
1397 : /****************************************************************************
1398 : Reply to a NT rename request.
1399 : ****************************************************************************/
1400 :
1401 0 : void reply_ntrename(struct smb_request *req)
1402 : {
1403 0 : connection_struct *conn = req->conn;
1404 0 : struct files_struct *src_dirfsp = NULL;
1405 0 : struct smb_filename *smb_fname_old = NULL;
1406 0 : struct files_struct *dst_dirfsp = NULL;
1407 0 : struct smb_filename *smb_fname_new = NULL;
1408 0 : char *oldname = NULL;
1409 0 : char *newname = NULL;
1410 0 : const char *dst_original_lcomp = NULL;
1411 : const char *p;
1412 : NTSTATUS status;
1413 : uint32_t attrs;
1414 0 : uint32_t ucf_flags_src = ucf_flags_from_smb_request(req);
1415 0 : NTTIME src_twrp = 0;
1416 0 : uint32_t ucf_flags_dst = ucf_flags_from_smb_request(req);
1417 0 : NTTIME dst_twrp = 0;
1418 : uint16_t rename_type;
1419 0 : TALLOC_CTX *ctx = talloc_tos();
1420 0 : bool stream_rename = false;
1421 :
1422 0 : START_PROFILE(SMBntrename);
1423 :
1424 0 : if (req->wct < 4) {
1425 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1426 0 : goto out;
1427 : }
1428 :
1429 0 : attrs = SVAL(req->vwv+0, 0);
1430 0 : rename_type = SVAL(req->vwv+1, 0);
1431 :
1432 0 : p = (const char *)req->buf + 1;
1433 0 : p += srvstr_get_path_req(ctx, req, &oldname, p, STR_TERMINATE,
1434 : &status);
1435 0 : if (!NT_STATUS_IS_OK(status)) {
1436 0 : reply_nterror(req, status);
1437 0 : goto out;
1438 : }
1439 :
1440 0 : if (!req->posix_pathnames && ms_has_wild(oldname)) {
1441 0 : reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
1442 0 : goto out;
1443 : }
1444 :
1445 0 : p++;
1446 0 : p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
1447 : &status);
1448 0 : if (!NT_STATUS_IS_OK(status)) {
1449 0 : reply_nterror(req, status);
1450 0 : goto out;
1451 : }
1452 :
1453 0 : if (!req->posix_pathnames && ms_has_wild(newname)) {
1454 0 : reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
1455 0 : goto out;
1456 : }
1457 :
1458 0 : if (!req->posix_pathnames) {
1459 : /* The newname must begin with a ':' if the
1460 : oldname contains a ':'. */
1461 0 : if (strchr_m(oldname, ':')) {
1462 0 : if (newname[0] != ':') {
1463 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1464 0 : goto out;
1465 : }
1466 0 : stream_rename = true;
1467 : }
1468 : }
1469 :
1470 0 : if (ucf_flags_src & UCF_GMT_PATHNAME) {
1471 0 : extract_snapshot_token(oldname, &src_twrp);
1472 : }
1473 0 : status = filename_convert_dirfsp(ctx,
1474 : conn,
1475 : oldname,
1476 : ucf_flags_src,
1477 : src_twrp,
1478 : &src_dirfsp,
1479 : &smb_fname_old);
1480 0 : if (!NT_STATUS_IS_OK(status)) {
1481 0 : if (NT_STATUS_EQUAL(status,
1482 : NT_STATUS_PATH_NOT_COVERED)) {
1483 0 : reply_botherror(req,
1484 : NT_STATUS_PATH_NOT_COVERED,
1485 : ERRSRV, ERRbadpath);
1486 0 : goto out;
1487 : }
1488 0 : reply_nterror(req, status);
1489 0 : goto out;
1490 : }
1491 :
1492 0 : if (stream_rename) {
1493 : /*
1494 : * No point in calling filename_convert()
1495 : * on a raw stream name. It can never find
1496 : * the file anyway. Use the same logic as
1497 : * SMB2_FILE_RENAME_INFORMATION_INTERNAL
1498 : * and generate smb_fname_new directly.
1499 : */
1500 0 : smb_fname_new = synthetic_smb_fname(talloc_tos(),
1501 0 : smb_fname_old->base_name,
1502 : newname,
1503 : NULL,
1504 0 : smb_fname_old->twrp,
1505 0 : smb_fname_old->flags);
1506 0 : if (smb_fname_new == NULL) {
1507 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1508 0 : goto out;
1509 : }
1510 : } else {
1511 0 : if (ucf_flags_dst & UCF_GMT_PATHNAME) {
1512 0 : extract_snapshot_token(newname,
1513 : &dst_twrp);
1514 : }
1515 0 : status = filename_convert_dirfsp(ctx,
1516 : conn,
1517 : newname,
1518 : ucf_flags_dst,
1519 : dst_twrp,
1520 : &dst_dirfsp,
1521 : &smb_fname_new);
1522 0 : if (!NT_STATUS_IS_OK(status)) {
1523 0 : if (NT_STATUS_EQUAL(status,
1524 : NT_STATUS_PATH_NOT_COVERED)) {
1525 0 : reply_botherror(req,
1526 : NT_STATUS_PATH_NOT_COVERED,
1527 : ERRSRV, ERRbadpath);
1528 0 : goto out;
1529 : }
1530 0 : reply_nterror(req, status);
1531 0 : goto out;
1532 : }
1533 : }
1534 :
1535 : /* Get the last component of the destination for rename_internals(). */
1536 0 : dst_original_lcomp = get_original_lcomp(ctx,
1537 : conn,
1538 : newname,
1539 : ucf_flags_dst);
1540 0 : if (dst_original_lcomp == NULL) {
1541 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1542 0 : goto out;
1543 : }
1544 :
1545 :
1546 0 : DEBUG(3,("reply_ntrename: %s -> %s\n",
1547 : smb_fname_str_dbg(smb_fname_old),
1548 : smb_fname_str_dbg(smb_fname_new)));
1549 :
1550 0 : switch(rename_type) {
1551 0 : case RENAME_FLAG_RENAME:
1552 0 : status = rename_internals(ctx,
1553 : conn,
1554 : req,
1555 : src_dirfsp,
1556 : smb_fname_old,
1557 : dst_dirfsp,
1558 : smb_fname_new,
1559 : dst_original_lcomp,
1560 : attrs,
1561 : false,
1562 : DELETE_ACCESS);
1563 0 : break;
1564 0 : case RENAME_FLAG_HARD_LINK:
1565 0 : status = hardlink_internals(ctx,
1566 : conn,
1567 : req,
1568 : false,
1569 : src_dirfsp,
1570 : smb_fname_old,
1571 : dst_dirfsp,
1572 : smb_fname_new);
1573 0 : break;
1574 0 : case RENAME_FLAG_COPY:
1575 0 : status = copy_internals(ctx,
1576 : conn,
1577 : req,
1578 : src_dirfsp,
1579 : smb_fname_old,
1580 : dst_dirfsp,
1581 : smb_fname_new,
1582 : attrs);
1583 0 : break;
1584 0 : case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
1585 0 : status = NT_STATUS_INVALID_PARAMETER;
1586 0 : break;
1587 0 : default:
1588 0 : status = NT_STATUS_ACCESS_DENIED; /* Default error. */
1589 0 : break;
1590 : }
1591 :
1592 0 : if (!NT_STATUS_IS_OK(status)) {
1593 0 : if (open_was_deferred(req->xconn, req->mid)) {
1594 : /* We have re-scheduled this call. */
1595 0 : goto out;
1596 : }
1597 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1598 0 : bool ok = defer_smb1_sharing_violation(req);
1599 0 : if (ok) {
1600 0 : goto out;
1601 : }
1602 : }
1603 :
1604 0 : reply_nterror(req, status);
1605 0 : goto out;
1606 : }
1607 :
1608 0 : reply_smb1_outbuf(req, 0, 0);
1609 0 : out:
1610 0 : END_PROFILE(SMBntrename);
1611 0 : return;
1612 : }
1613 :
1614 : /****************************************************************************
1615 : Reply to a notify change - queue the request and
1616 : don't allow a directory to be opened.
1617 : ****************************************************************************/
1618 :
1619 0 : static void smbd_smb1_notify_reply(struct smb_request *req,
1620 : NTSTATUS error_code,
1621 : uint8_t *buf, size_t len)
1622 : {
1623 0 : send_nt_replies(req->conn, req, error_code, (char *)buf, len, NULL, 0);
1624 0 : }
1625 :
1626 0 : static void call_nt_transact_notify_change(connection_struct *conn,
1627 : struct smb_request *req,
1628 : uint16_t **ppsetup,
1629 : uint32_t setup_count,
1630 : char **ppparams,
1631 : uint32_t parameter_count,
1632 : char **ppdata, uint32_t data_count,
1633 : uint32_t max_data_count,
1634 : uint32_t max_param_count)
1635 : {
1636 0 : uint16_t *setup = *ppsetup;
1637 : files_struct *fsp;
1638 : uint32_t filter;
1639 : NTSTATUS status;
1640 : bool recursive;
1641 :
1642 0 : if(setup_count < 6) {
1643 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1644 0 : return;
1645 : }
1646 :
1647 0 : fsp = file_fsp(req, SVAL(setup,4));
1648 0 : filter = IVAL(setup, 0);
1649 0 : recursive = (SVAL(setup, 6) != 0) ? True : False;
1650 :
1651 0 : DEBUG(3,("call_nt_transact_notify_change\n"));
1652 :
1653 0 : if(!fsp) {
1654 0 : reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1655 0 : return;
1656 : }
1657 :
1658 : {
1659 : char *filter_string;
1660 :
1661 0 : if (!(filter_string = notify_filter_string(NULL, filter))) {
1662 0 : reply_nterror(req,NT_STATUS_NO_MEMORY);
1663 0 : return;
1664 : }
1665 :
1666 0 : DEBUG(3,("call_nt_transact_notify_change: notify change "
1667 : "called on %s, filter = %s, recursive = %d\n",
1668 : fsp_str_dbg(fsp), filter_string, recursive));
1669 :
1670 0 : TALLOC_FREE(filter_string);
1671 : }
1672 :
1673 0 : if((!fsp->fsp_flags.is_directory) || (conn != fsp->conn)) {
1674 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1675 0 : return;
1676 : }
1677 :
1678 0 : if (fsp->notify == NULL) {
1679 :
1680 0 : status = change_notify_create(fsp,
1681 : max_param_count,
1682 : filter,
1683 : recursive);
1684 0 : if (!NT_STATUS_IS_OK(status)) {
1685 0 : DEBUG(10, ("change_notify_create returned %s\n",
1686 : nt_errstr(status)));
1687 0 : reply_nterror(req, status);
1688 0 : return;
1689 : }
1690 : }
1691 :
1692 0 : if (change_notify_fsp_has_changes(fsp)) {
1693 :
1694 : /*
1695 : * We've got changes pending, respond immediately
1696 : */
1697 :
1698 : /*
1699 : * TODO: write a torture test to check the filtering behaviour
1700 : * here.
1701 : */
1702 :
1703 0 : change_notify_reply(req,
1704 0 : NT_STATUS_OK,
1705 : max_param_count,
1706 : fsp->notify,
1707 : smbd_smb1_notify_reply);
1708 :
1709 : /*
1710 : * change_notify_reply() above has independently sent its
1711 : * results
1712 : */
1713 0 : return;
1714 : }
1715 :
1716 : /*
1717 : * No changes pending, queue the request
1718 : */
1719 :
1720 0 : status = change_notify_add_request(req,
1721 : max_param_count,
1722 : filter,
1723 : recursive, fsp,
1724 : smbd_smb1_notify_reply);
1725 0 : if (!NT_STATUS_IS_OK(status)) {
1726 0 : reply_nterror(req, status);
1727 : }
1728 0 : return;
1729 : }
1730 :
1731 : /****************************************************************************
1732 : Reply to an NT transact rename command.
1733 : ****************************************************************************/
1734 :
1735 0 : static void call_nt_transact_rename(connection_struct *conn,
1736 : struct smb_request *req,
1737 : uint16_t **ppsetup, uint32_t setup_count,
1738 : char **ppparams, uint32_t parameter_count,
1739 : char **ppdata, uint32_t data_count,
1740 : uint32_t max_data_count)
1741 : {
1742 0 : char *params = *ppparams;
1743 0 : char *new_name = NULL;
1744 0 : files_struct *fsp = NULL;
1745 : NTSTATUS status;
1746 0 : TALLOC_CTX *ctx = talloc_tos();
1747 :
1748 0 : if(parameter_count < 5) {
1749 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1750 0 : return;
1751 : }
1752 :
1753 0 : fsp = file_fsp(req, SVAL(params, 0));
1754 0 : if (!check_fsp(conn, req, fsp)) {
1755 0 : return;
1756 : }
1757 0 : if (req->posix_pathnames) {
1758 0 : srvstr_get_path_posix(ctx,
1759 : params,
1760 0 : req->flags2,
1761 : &new_name,
1762 0 : params+4,
1763 0 : parameter_count - 4,
1764 : STR_TERMINATE,
1765 : &status);
1766 : } else {
1767 0 : srvstr_get_path(ctx,
1768 : params,
1769 0 : req->flags2,
1770 : &new_name,
1771 0 : params+4,
1772 0 : parameter_count - 4,
1773 : STR_TERMINATE,
1774 : &status);
1775 : }
1776 :
1777 0 : if (!NT_STATUS_IS_OK(status)) {
1778 0 : reply_nterror(req, status);
1779 0 : return;
1780 : }
1781 :
1782 : /*
1783 : * W2K3 ignores this request as the RAW-RENAME test
1784 : * demonstrates, so we do.
1785 : */
1786 0 : send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
1787 :
1788 0 : DEBUG(3,("nt transact rename from = %s, to = %s ignored!\n",
1789 : fsp_str_dbg(fsp), new_name));
1790 :
1791 0 : return;
1792 : }
1793 :
1794 : /****************************************************************************
1795 : SMB1 reply to query a security descriptor.
1796 : ****************************************************************************/
1797 :
1798 0 : static void call_nt_transact_query_security_desc(connection_struct *conn,
1799 : struct smb_request *req,
1800 : uint16_t **ppsetup,
1801 : uint32_t setup_count,
1802 : char **ppparams,
1803 : uint32_t parameter_count,
1804 : char **ppdata,
1805 : uint32_t data_count,
1806 : uint32_t max_data_count)
1807 : {
1808 0 : char *params = *ppparams;
1809 0 : char *data = *ppdata;
1810 0 : size_t sd_size = 0;
1811 : uint32_t security_info_wanted;
1812 0 : files_struct *fsp = NULL;
1813 : NTSTATUS status;
1814 0 : uint8_t *marshalled_sd = NULL;
1815 :
1816 0 : if(parameter_count < 8) {
1817 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1818 0 : return;
1819 : }
1820 :
1821 0 : fsp = file_fsp(req, SVAL(params,0));
1822 0 : if(!fsp) {
1823 0 : reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1824 0 : return;
1825 : }
1826 :
1827 0 : security_info_wanted = IVAL(params,4);
1828 :
1829 0 : DEBUG(3,("call_nt_transact_query_security_desc: file = %s, "
1830 : "info_wanted = 0x%x\n", fsp_str_dbg(fsp),
1831 : (unsigned int)security_info_wanted));
1832 :
1833 0 : params = nttrans_realloc(ppparams, 4);
1834 0 : if(params == NULL) {
1835 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1836 0 : return;
1837 : }
1838 :
1839 : /*
1840 : * Get the permissions to return.
1841 : */
1842 :
1843 0 : status = smbd_do_query_security_desc(conn,
1844 : talloc_tos(),
1845 : fsp,
1846 : security_info_wanted &
1847 : SMB_SUPPORTED_SECINFO_FLAGS,
1848 : max_data_count,
1849 : &marshalled_sd,
1850 : &sd_size);
1851 :
1852 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) {
1853 0 : SIVAL(params,0,(uint32_t)sd_size);
1854 0 : send_nt_replies(conn, req, NT_STATUS_BUFFER_TOO_SMALL,
1855 : params, 4, NULL, 0);
1856 0 : return;
1857 : }
1858 :
1859 0 : if (!NT_STATUS_IS_OK(status)) {
1860 0 : reply_nterror(req, status);
1861 0 : return;
1862 : }
1863 :
1864 0 : SMB_ASSERT(sd_size > 0);
1865 :
1866 0 : SIVAL(params,0,(uint32_t)sd_size);
1867 :
1868 0 : if (max_data_count < sd_size) {
1869 0 : send_nt_replies(conn, req, NT_STATUS_BUFFER_TOO_SMALL,
1870 : params, 4, NULL, 0);
1871 0 : return;
1872 : }
1873 :
1874 : /*
1875 : * Allocate the data we will return.
1876 : */
1877 :
1878 0 : data = nttrans_realloc(ppdata, sd_size);
1879 0 : if(data == NULL) {
1880 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1881 0 : return;
1882 : }
1883 :
1884 0 : memcpy(data, marshalled_sd, sd_size);
1885 :
1886 0 : send_nt_replies(conn, req, NT_STATUS_OK, params, 4, data, (int)sd_size);
1887 :
1888 0 : return;
1889 : }
1890 :
1891 : /****************************************************************************
1892 : Reply to set a security descriptor. Map to UNIX perms or POSIX ACLs.
1893 : ****************************************************************************/
1894 :
1895 0 : static void call_nt_transact_set_security_desc(connection_struct *conn,
1896 : struct smb_request *req,
1897 : uint16_t **ppsetup,
1898 : uint32_t setup_count,
1899 : char **ppparams,
1900 : uint32_t parameter_count,
1901 : char **ppdata,
1902 : uint32_t data_count,
1903 : uint32_t max_data_count)
1904 : {
1905 0 : char *params= *ppparams;
1906 0 : char *data = *ppdata;
1907 0 : files_struct *fsp = NULL;
1908 0 : uint32_t security_info_sent = 0;
1909 : NTSTATUS status;
1910 :
1911 0 : if(parameter_count < 8) {
1912 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1913 0 : return;
1914 : }
1915 :
1916 0 : if((fsp = file_fsp(req, SVAL(params,0))) == NULL) {
1917 0 : reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1918 0 : return;
1919 : }
1920 :
1921 0 : if (!CAN_WRITE(fsp->conn)) {
1922 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1923 0 : return;
1924 : }
1925 :
1926 0 : if(!lp_nt_acl_support(SNUM(conn))) {
1927 0 : goto done;
1928 : }
1929 :
1930 0 : security_info_sent = IVAL(params,4);
1931 :
1932 0 : DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n",
1933 : fsp_str_dbg(fsp), (unsigned int)security_info_sent));
1934 :
1935 0 : if (data_count == 0) {
1936 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1937 0 : return;
1938 : }
1939 :
1940 0 : status = set_sd_blob(fsp, (uint8_t *)data, data_count,
1941 : security_info_sent & SMB_SUPPORTED_SECINFO_FLAGS);
1942 0 : if (!NT_STATUS_IS_OK(status)) {
1943 0 : reply_nterror(req, status);
1944 0 : return;
1945 : }
1946 :
1947 0 : done:
1948 0 : send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
1949 0 : return;
1950 : }
1951 :
1952 : /****************************************************************************
1953 : Reply to NT IOCTL
1954 : ****************************************************************************/
1955 :
1956 0 : static void call_nt_transact_ioctl(connection_struct *conn,
1957 : struct smb_request *req,
1958 : uint16_t **ppsetup, uint32_t setup_count,
1959 : char **ppparams, uint32_t parameter_count,
1960 : char **ppdata, uint32_t data_count,
1961 : uint32_t max_data_count)
1962 : {
1963 : NTSTATUS status;
1964 : uint32_t function;
1965 : uint16_t fidnum;
1966 : files_struct *fsp;
1967 : uint8_t isFSctl;
1968 : uint8_t compfilter;
1969 0 : char *out_data = NULL;
1970 0 : uint32_t out_data_len = 0;
1971 0 : char *pdata = *ppdata;
1972 0 : TALLOC_CTX *ctx = talloc_tos();
1973 :
1974 0 : if (setup_count != 8) {
1975 0 : DEBUG(3,("call_nt_transact_ioctl: invalid setup count %d\n", setup_count));
1976 0 : reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
1977 0 : return;
1978 : }
1979 :
1980 0 : function = IVAL(*ppsetup, 0);
1981 0 : fidnum = SVAL(*ppsetup, 4);
1982 0 : isFSctl = CVAL(*ppsetup, 6);
1983 0 : compfilter = CVAL(*ppsetup, 7);
1984 :
1985 0 : DEBUG(10, ("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n",
1986 : function, fidnum, isFSctl, compfilter));
1987 :
1988 0 : fsp=file_fsp(req, fidnum);
1989 :
1990 : /*
1991 : * We don't really implement IOCTLs, especially on files.
1992 : */
1993 0 : if (!isFSctl) {
1994 0 : DEBUG(10, ("isFSctl: 0x%02X indicates IOCTL, not FSCTL!\n",
1995 : isFSctl));
1996 0 : reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
1997 0 : return;
1998 : }
1999 :
2000 : /* Has to be for an open file! */
2001 0 : if (!check_fsp_open(conn, req, fsp)) {
2002 0 : return;
2003 : }
2004 :
2005 0 : SMB_PERFCOUNT_SET_IOCTL(&req->pcd, function);
2006 :
2007 : /*
2008 : * out_data might be allocated by the VFS module, but talloc should be
2009 : * used, and should be cleaned up when the request ends.
2010 : */
2011 0 : status = SMB_VFS_FSCTL(fsp,
2012 : ctx,
2013 : function,
2014 : req->flags2,
2015 : (uint8_t *)pdata,
2016 : data_count,
2017 : (uint8_t **)&out_data,
2018 : max_data_count,
2019 : &out_data_len);
2020 0 : if (!NT_STATUS_IS_OK(status)) {
2021 0 : reply_nterror(req, status);
2022 : } else {
2023 0 : send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, out_data, out_data_len);
2024 : }
2025 : }
2026 :
2027 :
2028 : #ifdef HAVE_SYS_QUOTAS
2029 : /****************************************************************************
2030 : Reply to get user quota
2031 : ****************************************************************************/
2032 :
2033 0 : static void call_nt_transact_get_user_quota(connection_struct *conn,
2034 : struct smb_request *req,
2035 : uint16_t **ppsetup,
2036 : uint32_t setup_count,
2037 : char **ppparams,
2038 : uint32_t parameter_count,
2039 : char **ppdata,
2040 : uint32_t data_count,
2041 : uint32_t max_data_count)
2042 : {
2043 0 : const struct loadparm_substitution *lp_sub =
2044 0 : loadparm_s3_global_substitution();
2045 0 : NTSTATUS nt_status = NT_STATUS_OK;
2046 0 : char *params = *ppparams;
2047 0 : char *pdata = *ppdata;
2048 0 : int data_len = 0;
2049 0 : int param_len = 0;
2050 0 : files_struct *fsp = NULL;
2051 0 : DATA_BLOB blob = data_blob_null;
2052 0 : struct nttrans_query_quota_params info = {0};
2053 : enum ndr_err_code err;
2054 0 : TALLOC_CTX *tmp_ctx = NULL;
2055 0 : uint32_t resp_len = 0;
2056 0 : uint8_t *resp_data = 0;
2057 :
2058 0 : tmp_ctx = talloc_init("ntquota_list");
2059 0 : if (!tmp_ctx) {
2060 0 : nt_status = NT_STATUS_NO_MEMORY;
2061 0 : goto error;
2062 : }
2063 :
2064 : /* access check */
2065 0 : if (get_current_uid(conn) != sec_initial_uid()) {
2066 0 : DEBUG(1,("get_user_quota: access_denied service [%s] user "
2067 : "[%s]\n", lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2068 : conn->session_info->unix_info->unix_name));
2069 0 : nt_status = NT_STATUS_ACCESS_DENIED;
2070 0 : goto error;
2071 : }
2072 :
2073 0 : blob.data = (uint8_t*)params;
2074 0 : blob.length = parameter_count;
2075 :
2076 0 : err = ndr_pull_struct_blob(&blob, tmp_ctx, &info,
2077 : (ndr_pull_flags_fn_t)ndr_pull_nttrans_query_quota_params);
2078 :
2079 0 : if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
2080 0 : DEBUG(0,("TRANSACT_GET_USER_QUOTA: failed to pull "
2081 : "query_quota_params."));
2082 0 : nt_status = NT_STATUS_INVALID_PARAMETER;
2083 0 : goto error;
2084 : }
2085 0 : DBG_DEBUG("info.return_single_entry = %u, info.restart_scan = %u, "
2086 : "info.sid_list_length = %u, info.start_sid_length = %u, "
2087 : "info.start_sid_offset = %u\n",
2088 : (unsigned int)info.return_single_entry,
2089 : (unsigned int)info.restart_scan,
2090 : (unsigned int)info.sid_list_length,
2091 : (unsigned int)info.start_sid_length,
2092 : (unsigned int)info.start_sid_offset);
2093 :
2094 : /* set blob to point at data for further parsing */
2095 0 : blob.data = (uint8_t*)pdata;
2096 0 : blob.length = data_count;
2097 : /*
2098 : * Although MS-SMB ref is ambiguous here, a microsoft client will
2099 : * only ever send a start sid (as part of a list) with
2100 : * sid_list_length & start_sid_offset both set to the actual list
2101 : * length. Note: Only a single result is returned in this case
2102 : * In the case where either start_sid_offset or start_sid_length
2103 : * are set alone or if both set (but have different values) then
2104 : * it seems windows will return a number of entries from the start
2105 : * of the list of users with quotas set. This behaviour is undocumented
2106 : * and windows clients do not send messages of that type. As such we
2107 : * currently will reject these requests.
2108 : */
2109 0 : if (info.start_sid_length
2110 0 : || (info.sid_list_length != info.start_sid_offset)) {
2111 0 : DBG_ERR("TRANSACT_GET_USER_QUOTA: unsupported single or "
2112 : "compound sid format\n");
2113 0 : nt_status = NT_STATUS_INVALID_PARAMETER;
2114 0 : goto error;
2115 : }
2116 :
2117 : /* maybe we can check the quota_fnum */
2118 0 : fsp = file_fsp(req, info.fid);
2119 0 : if (!check_fsp_ntquota_handle(conn, req, fsp)) {
2120 0 : DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2121 0 : nt_status = NT_STATUS_INVALID_HANDLE;
2122 0 : goto error;
2123 : }
2124 0 : nt_status = smbd_do_query_getinfo_quota(tmp_ctx,
2125 : fsp,
2126 0 : info.restart_scan,
2127 0 : info.return_single_entry,
2128 : info.sid_list_length,
2129 : &blob,
2130 : max_data_count,
2131 : &resp_data,
2132 : &resp_len);
2133 0 : if (!NT_STATUS_IS_OK(nt_status)) {
2134 0 : if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
2135 0 : goto error;
2136 : }
2137 0 : nt_status = NT_STATUS_OK;
2138 : }
2139 :
2140 0 : param_len = 4;
2141 0 : params = nttrans_realloc(ppparams, param_len);
2142 0 : if(params == NULL) {
2143 0 : nt_status = NT_STATUS_NO_MEMORY;
2144 0 : goto error;
2145 : }
2146 :
2147 0 : data_len = resp_len;
2148 0 : SIVAL(params, 0, data_len);
2149 0 : pdata = nttrans_realloc(ppdata, data_len);
2150 0 : memcpy(pdata, resp_data, data_len);
2151 :
2152 0 : TALLOC_FREE(tmp_ctx);
2153 0 : send_nt_replies(conn, req, nt_status, params, param_len,
2154 : pdata, data_len);
2155 0 : return;
2156 0 : error:
2157 0 : TALLOC_FREE(tmp_ctx);
2158 0 : reply_nterror(req, nt_status);
2159 : }
2160 :
2161 : /****************************************************************************
2162 : Reply to set user quota
2163 : ****************************************************************************/
2164 :
2165 0 : static void call_nt_transact_set_user_quota(connection_struct *conn,
2166 : struct smb_request *req,
2167 : uint16_t **ppsetup,
2168 : uint32_t setup_count,
2169 : char **ppparams,
2170 : uint32_t parameter_count,
2171 : char **ppdata,
2172 : uint32_t data_count,
2173 : uint32_t max_data_count)
2174 : {
2175 0 : const struct loadparm_substitution *lp_sub =
2176 0 : loadparm_s3_global_substitution();
2177 0 : char *params = *ppparams;
2178 0 : char *pdata = *ppdata;
2179 0 : int data_len=0,param_len=0;
2180 : SMB_NTQUOTA_STRUCT qt;
2181 0 : struct file_quota_information info = {0};
2182 : enum ndr_err_code err;
2183 : struct dom_sid sid;
2184 : DATA_BLOB inblob;
2185 0 : files_struct *fsp = NULL;
2186 0 : TALLOC_CTX *ctx = NULL;
2187 0 : NTSTATUS status = NT_STATUS_OK;
2188 0 : ZERO_STRUCT(qt);
2189 :
2190 : /* access check */
2191 0 : if (get_current_uid(conn) != sec_initial_uid()) {
2192 0 : DEBUG(1,("set_user_quota: access_denied service [%s] user "
2193 : "[%s]\n", lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2194 : conn->session_info->unix_info->unix_name));
2195 0 : status = NT_STATUS_ACCESS_DENIED;
2196 0 : goto error;
2197 : }
2198 :
2199 : /*
2200 : * Ensure minimum number of parameters sent.
2201 : */
2202 :
2203 0 : if (parameter_count < 2) {
2204 0 : DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= 2 bytes parameters\n",parameter_count));
2205 0 : status = NT_STATUS_INVALID_PARAMETER;
2206 0 : goto error;
2207 : }
2208 :
2209 : /* maybe we can check the quota_fnum */
2210 0 : fsp = file_fsp(req, SVAL(params,0));
2211 0 : if (!check_fsp_ntquota_handle(conn, req, fsp)) {
2212 0 : DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2213 0 : status = NT_STATUS_INVALID_HANDLE;
2214 0 : goto error;
2215 : }
2216 :
2217 0 : ctx = talloc_init("set_user_quota");
2218 0 : if (!ctx) {
2219 0 : status = NT_STATUS_NO_MEMORY;
2220 0 : goto error;
2221 : }
2222 0 : inblob.data = (uint8_t*)pdata;
2223 0 : inblob.length = data_count;
2224 :
2225 0 : err = ndr_pull_struct_blob(
2226 : &inblob,
2227 : ctx,
2228 : &info,
2229 : (ndr_pull_flags_fn_t)ndr_pull_file_quota_information);
2230 :
2231 0 : if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
2232 0 : DEBUG(0,("TRANSACT_SET_USER_QUOTA: failed to pull "
2233 : "file_quota_information\n"));
2234 0 : status = NT_STATUS_INVALID_PARAMETER;
2235 0 : goto error;
2236 : }
2237 0 : qt.usedspace = info.quota_used;
2238 :
2239 0 : qt.softlim = info.quota_threshold;
2240 :
2241 0 : qt.hardlim = info.quota_limit;
2242 :
2243 0 : sid = info.sid;
2244 :
2245 0 : if (vfs_set_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) {
2246 0 : status = NT_STATUS_INTERNAL_ERROR;
2247 0 : goto error;
2248 : }
2249 :
2250 0 : send_nt_replies(conn, req, NT_STATUS_OK, params, param_len,
2251 : pdata, data_len);
2252 0 : TALLOC_FREE(ctx);
2253 0 : return;
2254 0 : error:
2255 0 : TALLOC_FREE(ctx);
2256 0 : reply_nterror(req, status);
2257 : }
2258 : #endif /* HAVE_SYS_QUOTAS */
2259 :
2260 0 : static void handle_nttrans(connection_struct *conn,
2261 : struct trans_state *state,
2262 : struct smb_request *req)
2263 : {
2264 0 : if (get_Protocol() >= PROTOCOL_NT1) {
2265 0 : req->flags2 |= 0x40; /* IS_LONG_NAME */
2266 0 : SSVAL(discard_const_p(uint8_t, req->inbuf),smb_flg2,req->flags2);
2267 : }
2268 :
2269 :
2270 0 : SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
2271 :
2272 : /* Now we must call the relevant NT_TRANS function */
2273 0 : switch(state->call) {
2274 0 : case NT_TRANSACT_CREATE:
2275 : {
2276 0 : START_PROFILE(NT_transact_create);
2277 0 : call_nt_transact_create(
2278 : conn, req,
2279 : &state->setup, state->setup_count,
2280 0 : &state->param, state->total_param,
2281 0 : &state->data, state->total_data,
2282 : state->max_data_return);
2283 0 : END_PROFILE(NT_transact_create);
2284 0 : break;
2285 : }
2286 :
2287 0 : case NT_TRANSACT_IOCTL:
2288 : {
2289 0 : START_PROFILE(NT_transact_ioctl);
2290 0 : call_nt_transact_ioctl(
2291 : conn, req,
2292 : &state->setup, state->setup_count,
2293 0 : &state->param, state->total_param,
2294 0 : &state->data, state->total_data,
2295 : state->max_data_return);
2296 0 : END_PROFILE(NT_transact_ioctl);
2297 0 : break;
2298 : }
2299 :
2300 0 : case NT_TRANSACT_SET_SECURITY_DESC:
2301 : {
2302 0 : START_PROFILE(NT_transact_set_security_desc);
2303 0 : call_nt_transact_set_security_desc(
2304 : conn, req,
2305 : &state->setup, state->setup_count,
2306 0 : &state->param, state->total_param,
2307 0 : &state->data, state->total_data,
2308 : state->max_data_return);
2309 0 : END_PROFILE(NT_transact_set_security_desc);
2310 0 : break;
2311 : }
2312 :
2313 0 : case NT_TRANSACT_NOTIFY_CHANGE:
2314 : {
2315 0 : START_PROFILE(NT_transact_notify_change);
2316 0 : call_nt_transact_notify_change(
2317 : conn, req,
2318 : &state->setup, state->setup_count,
2319 0 : &state->param, state->total_param,
2320 0 : &state->data, state->total_data,
2321 : state->max_data_return,
2322 : state->max_param_return);
2323 0 : END_PROFILE(NT_transact_notify_change);
2324 0 : break;
2325 : }
2326 :
2327 0 : case NT_TRANSACT_RENAME:
2328 : {
2329 0 : START_PROFILE(NT_transact_rename);
2330 0 : call_nt_transact_rename(
2331 : conn, req,
2332 : &state->setup, state->setup_count,
2333 0 : &state->param, state->total_param,
2334 0 : &state->data, state->total_data,
2335 : state->max_data_return);
2336 0 : END_PROFILE(NT_transact_rename);
2337 0 : break;
2338 : }
2339 :
2340 0 : case NT_TRANSACT_QUERY_SECURITY_DESC:
2341 : {
2342 0 : START_PROFILE(NT_transact_query_security_desc);
2343 0 : call_nt_transact_query_security_desc(
2344 : conn, req,
2345 : &state->setup, state->setup_count,
2346 0 : &state->param, state->total_param,
2347 0 : &state->data, state->total_data,
2348 : state->max_data_return);
2349 0 : END_PROFILE(NT_transact_query_security_desc);
2350 0 : break;
2351 : }
2352 :
2353 : #ifdef HAVE_SYS_QUOTAS
2354 0 : case NT_TRANSACT_GET_USER_QUOTA:
2355 : {
2356 0 : START_PROFILE(NT_transact_get_user_quota);
2357 0 : call_nt_transact_get_user_quota(
2358 : conn, req,
2359 : &state->setup, state->setup_count,
2360 0 : &state->param, state->total_param,
2361 0 : &state->data, state->total_data,
2362 : state->max_data_return);
2363 0 : END_PROFILE(NT_transact_get_user_quota);
2364 0 : break;
2365 : }
2366 :
2367 0 : case NT_TRANSACT_SET_USER_QUOTA:
2368 : {
2369 0 : START_PROFILE(NT_transact_set_user_quota);
2370 0 : call_nt_transact_set_user_quota(
2371 : conn, req,
2372 : &state->setup, state->setup_count,
2373 0 : &state->param, state->total_param,
2374 0 : &state->data, state->total_data,
2375 : state->max_data_return);
2376 0 : END_PROFILE(NT_transact_set_user_quota);
2377 0 : break;
2378 : }
2379 : #endif /* HAVE_SYS_QUOTAS */
2380 :
2381 0 : default:
2382 : /* Error in request */
2383 0 : DEBUG(0,("handle_nttrans: Unknown request %d in "
2384 : "nttrans call\n", state->call));
2385 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2386 0 : return;
2387 : }
2388 0 : return;
2389 : }
2390 :
2391 : /****************************************************************************
2392 : Reply to a SMBNTtrans.
2393 : ****************************************************************************/
2394 :
2395 0 : void reply_nttrans(struct smb_request *req)
2396 : {
2397 0 : connection_struct *conn = req->conn;
2398 : uint32_t pscnt;
2399 : uint32_t psoff;
2400 : uint32_t dscnt;
2401 : uint32_t dsoff;
2402 : uint16_t function_code;
2403 : NTSTATUS result;
2404 : struct trans_state *state;
2405 :
2406 0 : START_PROFILE(SMBnttrans);
2407 :
2408 0 : if (req->wct < 19) {
2409 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2410 0 : END_PROFILE(SMBnttrans);
2411 0 : return;
2412 : }
2413 :
2414 0 : pscnt = IVAL(req->vwv+9, 1);
2415 0 : psoff = IVAL(req->vwv+11, 1);
2416 0 : dscnt = IVAL(req->vwv+13, 1);
2417 0 : dsoff = IVAL(req->vwv+15, 1);
2418 0 : function_code = SVAL(req->vwv+18, 0);
2419 :
2420 0 : if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) {
2421 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2422 0 : END_PROFILE(SMBnttrans);
2423 0 : return;
2424 : }
2425 :
2426 0 : result = allow_new_trans(conn->pending_trans, req->mid);
2427 0 : if (!NT_STATUS_IS_OK(result)) {
2428 0 : DEBUG(2, ("Got invalid nttrans request: %s\n", nt_errstr(result)));
2429 0 : reply_nterror(req, result);
2430 0 : END_PROFILE(SMBnttrans);
2431 0 : return;
2432 : }
2433 :
2434 0 : if ((state = talloc(conn, struct trans_state)) == NULL) {
2435 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2436 0 : END_PROFILE(SMBnttrans);
2437 0 : return;
2438 : }
2439 :
2440 0 : state->cmd = SMBnttrans;
2441 :
2442 0 : state->mid = req->mid;
2443 0 : state->vuid = req->vuid;
2444 0 : state->total_data = IVAL(req->vwv+3, 1);
2445 0 : state->data = NULL;
2446 0 : state->total_param = IVAL(req->vwv+1, 1);
2447 0 : state->param = NULL;
2448 0 : state->max_data_return = IVAL(req->vwv+7, 1);
2449 0 : state->max_param_return = IVAL(req->vwv+5, 1);
2450 :
2451 : /* setup count is in *words* */
2452 0 : state->setup_count = 2*CVAL(req->vwv+17, 1);
2453 0 : state->setup = NULL;
2454 0 : state->call = function_code;
2455 :
2456 0 : DEBUG(10, ("num_setup=%u, "
2457 : "param_total=%u, this_param=%u, max_param=%u, "
2458 : "data_total=%u, this_data=%u, max_data=%u, "
2459 : "param_offset=%u, data_offset=%u\n",
2460 : (unsigned)state->setup_count,
2461 : (unsigned)state->total_param, (unsigned)pscnt,
2462 : (unsigned)state->max_param_return,
2463 : (unsigned)state->total_data, (unsigned)dscnt,
2464 : (unsigned)state->max_data_return,
2465 : (unsigned)psoff, (unsigned)dsoff));
2466 :
2467 : /*
2468 : * All nttrans messages we handle have smb_wct == 19 +
2469 : * state->setup_count. Ensure this is so as a sanity check.
2470 : */
2471 :
2472 0 : if(req->wct != 19 + (state->setup_count/2)) {
2473 0 : DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n",
2474 : req->wct, 19 + (state->setup_count/2)));
2475 0 : goto bad_param;
2476 : }
2477 :
2478 : /* Don't allow more than 128mb for each value. */
2479 0 : if ((state->total_data > (1024*1024*128)) ||
2480 0 : (state->total_param > (1024*1024*128))) {
2481 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2482 0 : END_PROFILE(SMBnttrans);
2483 0 : return;
2484 : }
2485 :
2486 0 : if ((dscnt > state->total_data) || (pscnt > state->total_param))
2487 0 : goto bad_param;
2488 :
2489 0 : if (state->total_data) {
2490 :
2491 0 : if (smb_buffer_oob(state->total_data, 0, dscnt)
2492 0 : || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
2493 0 : goto bad_param;
2494 : }
2495 :
2496 : /* Can't use talloc here, the core routines do realloc on the
2497 : * params and data. */
2498 0 : if ((state->data = (char *)SMB_MALLOC(state->total_data)) == NULL) {
2499 0 : DEBUG(0,("reply_nttrans: data malloc fail for %u "
2500 : "bytes !\n", (unsigned int)state->total_data));
2501 0 : TALLOC_FREE(state);
2502 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2503 0 : END_PROFILE(SMBnttrans);
2504 0 : return;
2505 : }
2506 :
2507 0 : memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
2508 : }
2509 :
2510 0 : if (state->total_param) {
2511 :
2512 0 : if (smb_buffer_oob(state->total_param, 0, pscnt)
2513 0 : || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
2514 0 : goto bad_param;
2515 : }
2516 :
2517 : /* Can't use talloc here, the core routines do realloc on the
2518 : * params and data. */
2519 0 : if ((state->param = (char *)SMB_MALLOC(state->total_param)) == NULL) {
2520 0 : DEBUG(0,("reply_nttrans: param malloc fail for %u "
2521 : "bytes !\n", (unsigned int)state->total_param));
2522 0 : SAFE_FREE(state->data);
2523 0 : TALLOC_FREE(state);
2524 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2525 0 : END_PROFILE(SMBnttrans);
2526 0 : return;
2527 : }
2528 :
2529 0 : memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
2530 : }
2531 :
2532 0 : state->received_data = dscnt;
2533 0 : state->received_param = pscnt;
2534 :
2535 0 : if(state->setup_count > 0) {
2536 0 : DEBUG(10,("reply_nttrans: state->setup_count = %d\n",
2537 : state->setup_count));
2538 :
2539 : /*
2540 : * No overflow possible here, state->setup_count is an
2541 : * unsigned int, being filled by a single byte from
2542 : * CVAL(req->vwv+13, 0) above. The cast in the comparison
2543 : * below is not necessary, it's here to clarify things. The
2544 : * validity of req->vwv and req->wct has been checked in
2545 : * init_smb1_request already.
2546 : */
2547 0 : if ((state->setup_count/2) + 19 > (unsigned int)req->wct) {
2548 0 : goto bad_param;
2549 : }
2550 :
2551 0 : state->setup = (uint16_t *)TALLOC(state, state->setup_count);
2552 0 : if (state->setup == NULL) {
2553 0 : DEBUG(0,("reply_nttrans : Out of memory\n"));
2554 0 : SAFE_FREE(state->data);
2555 0 : SAFE_FREE(state->param);
2556 0 : TALLOC_FREE(state);
2557 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2558 0 : END_PROFILE(SMBnttrans);
2559 0 : return;
2560 : }
2561 :
2562 0 : memcpy(state->setup, req->vwv+19, state->setup_count);
2563 0 : dump_data(10, (uint8_t *)state->setup, state->setup_count);
2564 : }
2565 :
2566 0 : if ((state->received_data == state->total_data) &&
2567 0 : (state->received_param == state->total_param)) {
2568 0 : handle_nttrans(conn, state, req);
2569 0 : SAFE_FREE(state->param);
2570 0 : SAFE_FREE(state->data);
2571 0 : TALLOC_FREE(state);
2572 0 : END_PROFILE(SMBnttrans);
2573 0 : return;
2574 : }
2575 :
2576 0 : DLIST_ADD(conn->pending_trans, state);
2577 :
2578 : /* We need to send an interim response then receive the rest
2579 : of the parameter/data bytes */
2580 0 : reply_smb1_outbuf(req, 0, 0);
2581 0 : show_msg((char *)req->outbuf);
2582 0 : END_PROFILE(SMBnttrans);
2583 0 : return;
2584 :
2585 0 : bad_param:
2586 :
2587 0 : DEBUG(0,("reply_nttrans: invalid trans parameters\n"));
2588 0 : SAFE_FREE(state->data);
2589 0 : SAFE_FREE(state->param);
2590 0 : TALLOC_FREE(state);
2591 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2592 0 : END_PROFILE(SMBnttrans);
2593 0 : return;
2594 : }
2595 :
2596 : /****************************************************************************
2597 : Reply to a SMBnttranss
2598 : ****************************************************************************/
2599 :
2600 0 : void reply_nttranss(struct smb_request *req)
2601 : {
2602 0 : connection_struct *conn = req->conn;
2603 : uint32_t pcnt,poff,dcnt,doff,pdisp,ddisp;
2604 : struct trans_state *state;
2605 :
2606 0 : START_PROFILE(SMBnttranss);
2607 :
2608 0 : show_msg((const char *)req->inbuf);
2609 :
2610 : /* Windows clients expect all replies to
2611 : an NT transact secondary (SMBnttranss 0xA1)
2612 : to have a command code of NT transact
2613 : (SMBnttrans 0xA0). See bug #8989 for details. */
2614 0 : req->cmd = SMBnttrans;
2615 :
2616 0 : if (req->wct < 18) {
2617 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2618 0 : END_PROFILE(SMBnttranss);
2619 0 : return;
2620 : }
2621 :
2622 0 : for (state = conn->pending_trans; state != NULL;
2623 0 : state = state->next) {
2624 0 : if (state->mid == req->mid) {
2625 0 : break;
2626 : }
2627 : }
2628 :
2629 0 : if ((state == NULL) || (state->cmd != SMBnttrans)) {
2630 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2631 0 : END_PROFILE(SMBnttranss);
2632 0 : return;
2633 : }
2634 :
2635 : /* Revise state->total_param and state->total_data in case they have
2636 : changed downwards */
2637 0 : if (IVAL(req->vwv+1, 1) < state->total_param) {
2638 0 : state->total_param = IVAL(req->vwv+1, 1);
2639 : }
2640 0 : if (IVAL(req->vwv+3, 1) < state->total_data) {
2641 0 : state->total_data = IVAL(req->vwv+3, 1);
2642 : }
2643 :
2644 0 : pcnt = IVAL(req->vwv+5, 1);
2645 0 : poff = IVAL(req->vwv+7, 1);
2646 0 : pdisp = IVAL(req->vwv+9, 1);
2647 :
2648 0 : dcnt = IVAL(req->vwv+11, 1);
2649 0 : doff = IVAL(req->vwv+13, 1);
2650 0 : ddisp = IVAL(req->vwv+15, 1);
2651 :
2652 0 : state->received_param += pcnt;
2653 0 : state->received_data += dcnt;
2654 :
2655 0 : if ((state->received_data > state->total_data) ||
2656 0 : (state->received_param > state->total_param))
2657 0 : goto bad_param;
2658 :
2659 0 : if (pcnt) {
2660 0 : if (smb_buffer_oob(state->total_param, pdisp, pcnt)
2661 0 : || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
2662 0 : goto bad_param;
2663 : }
2664 0 : memcpy(state->param+pdisp, smb_base(req->inbuf)+poff,pcnt);
2665 : }
2666 :
2667 0 : if (dcnt) {
2668 0 : if (smb_buffer_oob(state->total_data, ddisp, dcnt)
2669 0 : || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
2670 0 : goto bad_param;
2671 : }
2672 0 : memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
2673 : }
2674 :
2675 0 : if ((state->received_param < state->total_param) ||
2676 0 : (state->received_data < state->total_data)) {
2677 0 : END_PROFILE(SMBnttranss);
2678 0 : return;
2679 : }
2680 :
2681 0 : handle_nttrans(conn, state, req);
2682 :
2683 0 : DLIST_REMOVE(conn->pending_trans, state);
2684 0 : SAFE_FREE(state->data);
2685 0 : SAFE_FREE(state->param);
2686 0 : TALLOC_FREE(state);
2687 0 : END_PROFILE(SMBnttranss);
2688 0 : return;
2689 :
2690 0 : bad_param:
2691 :
2692 0 : DEBUG(0,("reply_nttranss: invalid trans parameters\n"));
2693 0 : DLIST_REMOVE(conn->pending_trans, state);
2694 0 : SAFE_FREE(state->data);
2695 0 : SAFE_FREE(state->param);
2696 0 : TALLOC_FREE(state);
2697 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2698 0 : END_PROFILE(SMBnttranss);
2699 0 : return;
2700 : }
|