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