Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB transaction2 handling
4 : Copyright (C) Jeremy Allison 1994-2007
5 : Copyright (C) Stefan (metze) Metzmacher 2003
6 : Copyright (C) Volker Lendecke 2005-2007
7 : Copyright (C) Steve French 2005
8 : Copyright (C) James Peach 2006-2007
9 :
10 : Extensively modified by Andrew Tridgell, 1995
11 :
12 : This program is free software; you can redistribute it and/or modify
13 : it under the terms of the GNU General Public License as published by
14 : the Free Software Foundation; either version 3 of the License, or
15 : (at your option) any later version.
16 :
17 : This program is distributed in the hope that it will be useful,
18 : but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : GNU General Public License for more details.
21 :
22 : You should have received a copy of the GNU General Public License
23 : along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : */
25 :
26 : #include "includes.h"
27 : #include "ntioctl.h"
28 : #include "system/filesys.h"
29 : #include "lib/util/time_basic.h"
30 : #include "version.h"
31 : #include "smbd/smbd.h"
32 : #include "smbd/globals.h"
33 : #include "../libcli/auth/libcli_auth.h"
34 : #include "../librpc/gen_ndr/xattr.h"
35 : #include "../librpc/gen_ndr/ndr_security.h"
36 : #include "libcli/security/security.h"
37 : #include "trans2.h"
38 : #include "auth.h"
39 : #include "smbprofile.h"
40 : #include "rpc_server/srv_pipe_hnd.h"
41 : #include "printing.h"
42 : #include "lib/util_ea.h"
43 : #include "lib/readdir_attr.h"
44 : #include "messages.h"
45 : #include "libcli/smb/smb2_posix.h"
46 : #include "lib/util/string_wrappers.h"
47 : #include "source3/lib/substitute.h"
48 : #include "source3/lib/adouble.h"
49 :
50 : #define DIR_ENTRY_SAFETY_MARGIN 4096
51 :
52 : /****************************************************************************
53 : Send the required number of replies back.
54 : We assume all fields other than the data fields are
55 : set correctly for the type of call.
56 : HACK ! Always assumes smb_setup field is zero.
57 : ****************************************************************************/
58 :
59 8 : static void send_trans2_replies(connection_struct *conn,
60 : struct smb_request *req,
61 : NTSTATUS status,
62 : const char *params,
63 : int paramsize,
64 : const char *pdata,
65 : int datasize,
66 : int max_data_bytes)
67 : {
68 : /* As we are using a protocol > LANMAN1 then the max_send
69 : variable must have been set in the sessetupX call.
70 : This takes precedence over the max_xmit field in the
71 : global struct. These different max_xmit variables should
72 : be merged as this is now too confusing */
73 :
74 8 : int data_to_send = datasize;
75 8 : int params_to_send = paramsize;
76 : int useable_space;
77 8 : const char *pp = params;
78 8 : const char *pd = pdata;
79 : int params_sent_thistime, data_sent_thistime, total_sent_thistime;
80 8 : int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
81 8 : int data_alignment_offset = 0;
82 8 : bool overflow = False;
83 8 : struct smbXsrv_connection *xconn = req->xconn;
84 8 : int max_send = xconn->smb1.sessions.max_send;
85 :
86 : /* Modify the data_to_send and datasize and set the error if
87 : we're trying to send more than max_data_bytes. We still send
88 : the part of the packet(s) that fit. Strange, but needed
89 : for OS/2. */
90 :
91 8 : if (max_data_bytes > 0 && datasize > max_data_bytes) {
92 0 : DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
93 : max_data_bytes, datasize ));
94 0 : datasize = data_to_send = max_data_bytes;
95 0 : overflow = True;
96 : }
97 :
98 : /* If there genuinely are no parameters or data to send just send the empty packet */
99 :
100 8 : if(params_to_send == 0 && data_to_send == 0) {
101 0 : reply_smb1_outbuf(req, 10, 0);
102 0 : if (NT_STATUS_V(status)) {
103 : uint8_t eclass;
104 : uint32_t ecode;
105 0 : ntstatus_to_dos(status, &eclass, &ecode);
106 0 : error_packet_set((char *)req->outbuf,
107 : eclass, ecode, status,
108 : __LINE__,__FILE__);
109 : }
110 0 : show_msg((char *)req->outbuf);
111 0 : if (!smb1_srv_send(xconn,
112 0 : (char *)req->outbuf,
113 0 : true, req->seqnum+1,
114 0 : IS_CONN_ENCRYPTED(conn),
115 : &req->pcd)) {
116 0 : exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
117 : }
118 0 : TALLOC_FREE(req->outbuf);
119 0 : return;
120 : }
121 :
122 : /* When sending params and data ensure that both are nicely aligned */
123 : /* Only do this alignment when there is also data to send - else
124 : can cause NT redirector problems. */
125 :
126 8 : if (((params_to_send % 4) != 0) && (data_to_send != 0))
127 0 : data_alignment_offset = 4 - (params_to_send % 4);
128 :
129 : /* Space is bufsize minus Netbios over TCP header minus SMB header */
130 : /* The alignment_offset is to align the param bytes on an even byte
131 : boundary. NT 4.0 Beta needs this to work correctly. */
132 :
133 8 : useable_space = max_send - (smb_size
134 : + 2 * 10 /* wct */
135 8 : + alignment_offset
136 8 : + data_alignment_offset);
137 :
138 8 : if (useable_space < 0) {
139 0 : DEBUG(0, ("send_trans2_replies failed sanity useable_space "
140 : "= %d!!!", useable_space));
141 0 : exit_server_cleanly("send_trans2_replies: Not enough space");
142 : }
143 :
144 16 : while (params_to_send || data_to_send) {
145 : /* Calculate whether we will totally or partially fill this packet */
146 :
147 8 : total_sent_thistime = params_to_send + data_to_send;
148 :
149 : /* We can never send more than useable_space */
150 : /*
151 : * Note that 'useable_space' does not include the alignment offsets,
152 : * but we must include the alignment offsets in the calculation of
153 : * the length of the data we send over the wire, as the alignment offsets
154 : * are sent here. Fix from Marc_Jacobsen@hp.com.
155 : */
156 :
157 8 : total_sent_thistime = MIN(total_sent_thistime, useable_space);
158 :
159 8 : reply_smb1_outbuf(req, 10, total_sent_thistime + alignment_offset
160 8 : + data_alignment_offset);
161 :
162 : /* Set total params and data to be sent */
163 8 : SSVAL(req->outbuf,smb_tprcnt,paramsize);
164 8 : SSVAL(req->outbuf,smb_tdrcnt,datasize);
165 :
166 : /* Calculate how many parameters and data we can fit into
167 : * this packet. Parameters get precedence
168 : */
169 :
170 8 : params_sent_thistime = MIN(params_to_send,useable_space);
171 8 : data_sent_thistime = useable_space - params_sent_thistime;
172 8 : data_sent_thistime = MIN(data_sent_thistime,data_to_send);
173 :
174 8 : SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
175 :
176 : /* smb_proff is the offset from the start of the SMB header to the
177 : parameter bytes, however the first 4 bytes of outbuf are
178 : the Netbios over TCP header. Thus use smb_base() to subtract
179 : them from the calculation */
180 :
181 8 : SSVAL(req->outbuf,smb_proff,
182 : ((smb_buf(req->outbuf)+alignment_offset)
183 : - smb_base(req->outbuf)));
184 :
185 8 : if(params_sent_thistime == 0)
186 8 : SSVAL(req->outbuf,smb_prdisp,0);
187 : else
188 : /* Absolute displacement of param bytes sent in this packet */
189 0 : SSVAL(req->outbuf,smb_prdisp,pp - params);
190 :
191 8 : SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
192 8 : if(data_sent_thistime == 0) {
193 0 : SSVAL(req->outbuf,smb_droff,0);
194 0 : SSVAL(req->outbuf,smb_drdisp, 0);
195 : } else {
196 : /* The offset of the data bytes is the offset of the
197 : parameter bytes plus the number of parameters being sent this time */
198 8 : SSVAL(req->outbuf, smb_droff,
199 : ((smb_buf(req->outbuf)+alignment_offset)
200 : - smb_base(req->outbuf))
201 : + params_sent_thistime + data_alignment_offset);
202 8 : SSVAL(req->outbuf,smb_drdisp, pd - pdata);
203 : }
204 :
205 : /* Initialize the padding for alignment */
206 :
207 8 : if (alignment_offset != 0) {
208 8 : memset(smb_buf(req->outbuf), 0, alignment_offset);
209 : }
210 :
211 : /* Copy the param bytes into the packet */
212 :
213 8 : if(params_sent_thistime) {
214 0 : memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
215 : params_sent_thistime);
216 : }
217 :
218 : /* Copy in the data bytes */
219 8 : if(data_sent_thistime) {
220 8 : if (data_alignment_offset != 0) {
221 0 : memset((smb_buf(req->outbuf)+alignment_offset+
222 : params_sent_thistime), 0,
223 : data_alignment_offset);
224 : }
225 8 : memcpy(smb_buf(req->outbuf)+alignment_offset
226 8 : +params_sent_thistime+data_alignment_offset,
227 : pd,data_sent_thistime);
228 : }
229 :
230 8 : DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
231 : params_sent_thistime, data_sent_thistime, useable_space));
232 8 : DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
233 : params_to_send, data_to_send, paramsize, datasize));
234 :
235 8 : if (overflow) {
236 0 : error_packet_set((char *)req->outbuf,
237 : ERRDOS,ERRbufferoverflow,
238 0 : STATUS_BUFFER_OVERFLOW,
239 : __LINE__,__FILE__);
240 8 : } else if (NT_STATUS_V(status)) {
241 : uint8_t eclass;
242 : uint32_t ecode;
243 0 : ntstatus_to_dos(status, &eclass, &ecode);
244 0 : error_packet_set((char *)req->outbuf,
245 : eclass, ecode, status,
246 : __LINE__,__FILE__);
247 : }
248 :
249 : /* Send the packet */
250 8 : show_msg((char *)req->outbuf);
251 8 : if (!smb1_srv_send(xconn,
252 8 : (char *)req->outbuf,
253 8 : true, req->seqnum+1,
254 8 : IS_CONN_ENCRYPTED(conn),
255 : &req->pcd))
256 0 : exit_server_cleanly("send_trans2_replies: smb1_srv_send failed.");
257 :
258 8 : TALLOC_FREE(req->outbuf);
259 :
260 8 : pp += params_sent_thistime;
261 8 : pd += data_sent_thistime;
262 :
263 8 : params_to_send -= params_sent_thistime;
264 8 : data_to_send -= data_sent_thistime;
265 :
266 : /* Sanity check */
267 8 : if(params_to_send < 0 || data_to_send < 0) {
268 0 : DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
269 : params_to_send, data_to_send));
270 0 : return;
271 : }
272 : }
273 :
274 8 : return;
275 : }
276 :
277 : /****************************************************************************
278 : Deal with SMB_SET_POSIX_LOCK.
279 : ****************************************************************************/
280 :
281 : static void smb_set_posix_lock_done(struct tevent_req *subreq);
282 :
283 0 : static NTSTATUS smb_set_posix_lock(connection_struct *conn,
284 : struct smb_request *req,
285 : const char *pdata,
286 : int total_data,
287 : files_struct *fsp)
288 : {
289 0 : struct tevent_req *subreq = NULL;
290 0 : struct smbd_lock_element *lck = NULL;
291 : uint64_t count;
292 : uint64_t offset;
293 : uint64_t smblctx;
294 0 : bool blocking_lock = False;
295 : enum brl_type lock_type;
296 :
297 0 : NTSTATUS status = NT_STATUS_OK;
298 :
299 0 : if (!CAN_WRITE(conn)) {
300 0 : return NT_STATUS_DOS(ERRSRV, ERRaccess);
301 : }
302 :
303 0 : if (fsp == NULL ||
304 0 : fsp->fsp_flags.is_pathref ||
305 0 : fsp_get_io_fd(fsp) == -1)
306 : {
307 0 : return NT_STATUS_INVALID_HANDLE;
308 : }
309 :
310 0 : if (total_data != POSIX_LOCK_DATA_SIZE) {
311 0 : return NT_STATUS_INVALID_PARAMETER;
312 : }
313 :
314 0 : switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
315 0 : case POSIX_LOCK_TYPE_READ:
316 0 : lock_type = READ_LOCK;
317 0 : break;
318 0 : case POSIX_LOCK_TYPE_WRITE:
319 : /* Return the right POSIX-mappable error code for files opened read-only. */
320 0 : if (!fsp->fsp_flags.can_write) {
321 0 : return NT_STATUS_INVALID_HANDLE;
322 : }
323 0 : lock_type = WRITE_LOCK;
324 0 : break;
325 0 : case POSIX_LOCK_TYPE_UNLOCK:
326 0 : lock_type = UNLOCK_LOCK;
327 0 : break;
328 0 : default:
329 0 : return NT_STATUS_INVALID_PARAMETER;
330 : }
331 :
332 0 : switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
333 0 : case POSIX_LOCK_FLAG_NOWAIT:
334 0 : blocking_lock = false;
335 0 : break;
336 0 : case POSIX_LOCK_FLAG_WAIT:
337 0 : blocking_lock = true;
338 0 : break;
339 0 : default:
340 0 : return NT_STATUS_INVALID_PARAMETER;
341 : }
342 :
343 0 : if (!lp_blocking_locks(SNUM(conn))) {
344 0 : blocking_lock = False;
345 : }
346 :
347 0 : smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
348 0 : offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
349 0 : ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
350 0 : count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
351 0 : ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
352 :
353 0 : DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
354 : "count = %"PRIu64", offset = %"PRIu64"\n",
355 : fsp_str_dbg(fsp),
356 : (unsigned int)lock_type,
357 : smblctx,
358 : count,
359 : offset);
360 :
361 0 : if (lock_type == UNLOCK_LOCK) {
362 0 : struct smbd_lock_element l = {
363 0 : .req_guid = smbd_request_guid(req, 0),
364 : .smblctx = smblctx,
365 : .brltype = UNLOCK_LOCK,
366 : .lock_flav = POSIX_LOCK,
367 : .offset = offset,
368 : .count = count,
369 : };
370 0 : status = smbd_do_unlocking(req, fsp, 1, &l);
371 0 : return status;
372 : }
373 :
374 0 : lck = talloc(req, struct smbd_lock_element);
375 0 : if (lck == NULL) {
376 0 : return NT_STATUS_NO_MEMORY;
377 : }
378 :
379 0 : *lck = (struct smbd_lock_element) {
380 0 : .req_guid = smbd_request_guid(req, 0),
381 : .smblctx = smblctx,
382 : .brltype = lock_type,
383 : .lock_flav = POSIX_LOCK,
384 : .count = count,
385 : .offset = offset,
386 : };
387 :
388 0 : subreq = smbd_smb1_do_locks_send(
389 : fsp,
390 0 : req->sconn->ev_ctx,
391 : &req,
392 : fsp,
393 : blocking_lock ? UINT32_MAX : 0,
394 : true, /* large_offset */
395 : 1,
396 : lck);
397 0 : if (subreq == NULL) {
398 0 : TALLOC_FREE(lck);
399 0 : return NT_STATUS_NO_MEMORY;
400 : }
401 0 : tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
402 0 : return NT_STATUS_EVENT_PENDING;
403 : }
404 :
405 0 : static void smb_set_posix_lock_done(struct tevent_req *subreq)
406 : {
407 0 : struct smb_request *req = NULL;
408 : NTSTATUS status;
409 : bool ok;
410 :
411 0 : ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
412 0 : SMB_ASSERT(ok);
413 :
414 0 : status = smbd_smb1_do_locks_recv(subreq);
415 0 : TALLOC_FREE(subreq);
416 :
417 0 : if (NT_STATUS_IS_OK(status)) {
418 0 : char params[2] = {0};
419 : /* Fake up max_data_bytes here - we know it fits. */
420 0 : send_trans2_replies(
421 0 : req->conn,
422 : req,
423 0 : NT_STATUS_OK,
424 : params,
425 : 2,
426 : NULL,
427 : 0,
428 : 0xffff);
429 : } else {
430 0 : reply_nterror(req, status);
431 0 : ok = smb1_srv_send(
432 0 : req->xconn,
433 0 : (char *)req->outbuf,
434 : true,
435 0 : req->seqnum+1,
436 0 : IS_CONN_ENCRYPTED(req->conn),
437 : NULL);
438 0 : if (!ok) {
439 0 : exit_server_cleanly("smb_set_posix_lock_done: "
440 : "smb1_srv_send failed.");
441 : }
442 : }
443 :
444 0 : TALLOC_FREE(req);
445 0 : return;
446 : }
447 :
448 : /****************************************************************************
449 : Read a list of EA names from an incoming data buffer. Create an ea_list with them.
450 : ****************************************************************************/
451 :
452 0 : static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
453 : {
454 0 : struct ea_list *ea_list_head = NULL;
455 0 : size_t converted_size, offset = 0;
456 :
457 0 : while (offset + 2 < data_size) {
458 0 : struct ea_list *eal = talloc_zero(ctx, struct ea_list);
459 0 : unsigned int namelen = CVAL(pdata,offset);
460 :
461 0 : offset++; /* Go past the namelen byte. */
462 :
463 : /* integer wrap paranioa. */
464 0 : if ((offset + namelen < offset) || (offset + namelen < namelen) ||
465 0 : (offset > data_size) || (namelen > data_size) ||
466 0 : (offset + namelen >= data_size)) {
467 : break;
468 : }
469 : /* Ensure the name is null terminated. */
470 0 : if (pdata[offset + namelen] != '\0') {
471 0 : return NULL;
472 : }
473 0 : if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
474 : &converted_size)) {
475 0 : DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
476 : "failed: %s", strerror(errno)));
477 : }
478 0 : if (!eal->ea.name) {
479 0 : return NULL;
480 : }
481 :
482 0 : offset += (namelen + 1); /* Go past the name + terminating zero. */
483 0 : DLIST_ADD_END(ea_list_head, eal);
484 0 : DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
485 : }
486 :
487 0 : return ea_list_head;
488 : }
489 :
490 : /****************************************************************************
491 : Reply to a TRANSACT2_OPEN.
492 : ****************************************************************************/
493 :
494 0 : static void call_trans2open(connection_struct *conn,
495 : struct smb_request *req,
496 : char **pparams, int total_params,
497 : char **ppdata, int total_data,
498 : unsigned int max_data_bytes)
499 : {
500 0 : struct smb_filename *smb_fname = NULL;
501 0 : char *params = *pparams;
502 0 : char *pdata = *ppdata;
503 : int deny_mode;
504 : int32_t open_attr;
505 : bool oplock_request;
506 : #if 0
507 : bool return_additional_info;
508 : int16 open_sattr;
509 : time_t open_time;
510 : #endif
511 : int open_ofun;
512 : uint32_t open_size;
513 : char *pname;
514 0 : char *fname = NULL;
515 0 : off_t size=0;
516 0 : int fattr=0,mtime=0;
517 0 : SMB_INO_T inode = 0;
518 0 : int smb_action = 0;
519 0 : struct files_struct *dirfsp = NULL;
520 : files_struct *fsp;
521 0 : struct ea_list *ea_list = NULL;
522 0 : uint16_t flags = 0;
523 : NTSTATUS status;
524 : uint32_t access_mask;
525 : uint32_t share_mode;
526 : uint32_t create_disposition;
527 0 : uint32_t create_options = 0;
528 0 : uint32_t private_flags = 0;
529 0 : NTTIME twrp = 0;
530 0 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
531 0 : TALLOC_CTX *ctx = talloc_tos();
532 :
533 : /*
534 : * Ensure we have enough parameters to perform the operation.
535 : */
536 :
537 0 : if (total_params < 29) {
538 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
539 0 : goto out;
540 : }
541 :
542 0 : flags = SVAL(params, 0);
543 0 : deny_mode = SVAL(params, 2);
544 0 : open_attr = SVAL(params,6);
545 0 : oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
546 0 : if (oplock_request) {
547 0 : oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
548 : }
549 :
550 : #if 0
551 : return_additional_info = BITSETW(params,0);
552 : open_sattr = SVAL(params, 4);
553 : open_time = make_unix_date3(params+8);
554 : #endif
555 0 : open_ofun = SVAL(params,12);
556 0 : open_size = IVAL(params,14);
557 0 : pname = ¶ms[28];
558 :
559 0 : if (IS_IPC(conn)) {
560 0 : reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
561 0 : goto out;
562 : }
563 :
564 0 : if (req->posix_pathnames) {
565 0 : srvstr_get_path_posix(ctx,
566 : params,
567 0 : req->flags2,
568 : &fname,
569 : pname,
570 0 : total_params - 28,
571 : STR_TERMINATE,
572 : &status);
573 : } else {
574 0 : srvstr_get_path(ctx,
575 : params,
576 0 : req->flags2,
577 : &fname,
578 : pname,
579 0 : total_params - 28,
580 : STR_TERMINATE,
581 : &status);
582 : }
583 0 : if (!NT_STATUS_IS_OK(status)) {
584 0 : reply_nterror(req, status);
585 0 : goto out;
586 : }
587 :
588 0 : DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
589 : fname, (unsigned int)deny_mode, (unsigned int)open_attr,
590 : (unsigned int)open_ofun, open_size));
591 :
592 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
593 0 : extract_snapshot_token(fname, &twrp);
594 : }
595 0 : status = filename_convert_dirfsp(ctx,
596 : conn,
597 : fname,
598 : ucf_flags,
599 : twrp,
600 : &dirfsp,
601 : &smb_fname);
602 0 : if (!NT_STATUS_IS_OK(status)) {
603 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
604 0 : reply_botherror(req,
605 : NT_STATUS_PATH_NOT_COVERED,
606 : ERRSRV, ERRbadpath);
607 0 : goto out;
608 : }
609 0 : reply_nterror(req, status);
610 0 : goto out;
611 : }
612 :
613 0 : if (open_ofun == 0) {
614 0 : reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
615 0 : goto out;
616 : }
617 :
618 0 : if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
619 : open_ofun,
620 : &access_mask, &share_mode,
621 : &create_disposition,
622 : &create_options,
623 : &private_flags)) {
624 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
625 0 : goto out;
626 : }
627 :
628 : /* Any data in this call is an EA list. */
629 0 : if (total_data && (total_data != 4)) {
630 0 : if (total_data < 10) {
631 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
632 0 : goto out;
633 : }
634 :
635 0 : if (IVAL(pdata,0) > total_data) {
636 0 : DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
637 : IVAL(pdata,0), (unsigned int)total_data));
638 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
639 0 : goto out;
640 : }
641 :
642 0 : ea_list = read_ea_list(talloc_tos(), pdata + 4,
643 0 : total_data - 4);
644 0 : if (!ea_list) {
645 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
646 0 : goto out;
647 : }
648 :
649 0 : if (!lp_ea_support(SNUM(conn))) {
650 0 : reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
651 0 : goto out;
652 : }
653 :
654 0 : if (!req->posix_pathnames &&
655 0 : ea_list_has_invalid_name(ea_list)) {
656 0 : int param_len = 30;
657 0 : *pparams = (char *)SMB_REALLOC(*pparams, param_len);
658 0 : if(*pparams == NULL ) {
659 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
660 0 : goto out;
661 : }
662 0 : params = *pparams;
663 0 : memset(params, '\0', param_len);
664 0 : send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
665 : params, param_len, NULL, 0, max_data_bytes);
666 0 : goto out;
667 : }
668 : }
669 :
670 0 : status = SMB_VFS_CREATE_FILE(
671 : conn, /* conn */
672 : req, /* req */
673 : dirfsp, /* dirfsp */
674 : smb_fname, /* fname */
675 : access_mask, /* access_mask */
676 : share_mode, /* share_access */
677 : create_disposition, /* create_disposition*/
678 : create_options, /* create_options */
679 : open_attr, /* file_attributes */
680 : oplock_request, /* oplock_request */
681 : NULL, /* lease */
682 : open_size, /* allocation_size */
683 : private_flags,
684 : NULL, /* sd */
685 : ea_list, /* ea_list */
686 : &fsp, /* result */
687 : &smb_action, /* psbuf */
688 : NULL, NULL); /* create context */
689 :
690 0 : if (!NT_STATUS_IS_OK(status)) {
691 0 : if (open_was_deferred(req->xconn, req->mid)) {
692 : /* We have re-scheduled this call. */
693 0 : goto out;
694 : }
695 :
696 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
697 0 : reply_openerror(req, status);
698 0 : goto out;
699 : }
700 :
701 0 : fsp = fcb_or_dos_open(
702 : req,
703 : smb_fname,
704 : access_mask,
705 : create_options,
706 : private_flags);
707 0 : if (fsp == NULL) {
708 0 : bool ok = defer_smb1_sharing_violation(req);
709 0 : if (ok) {
710 0 : goto out;
711 : }
712 0 : reply_openerror(req, status);
713 0 : goto out;
714 : }
715 :
716 0 : smb_action = FILE_WAS_OPENED;
717 : }
718 :
719 0 : size = get_file_size_stat(&smb_fname->st);
720 0 : fattr = fdos_mode(fsp);
721 0 : mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
722 0 : inode = smb_fname->st.st_ex_ino;
723 0 : if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
724 0 : close_file_free(req, &fsp, ERROR_CLOSE);
725 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
726 0 : goto out;
727 : }
728 :
729 : /* Realloc the size of parameters and data we will return */
730 0 : *pparams = (char *)SMB_REALLOC(*pparams, 30);
731 0 : if(*pparams == NULL ) {
732 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
733 0 : goto out;
734 : }
735 0 : params = *pparams;
736 :
737 0 : SSVAL(params,0,fsp->fnum);
738 0 : SSVAL(params,2,fattr);
739 0 : srv_put_dos_date2(params,4, mtime);
740 0 : SIVAL(params,8, (uint32_t)size);
741 0 : SSVAL(params,12,deny_mode);
742 0 : SSVAL(params,14,0); /* open_type - file or directory. */
743 0 : SSVAL(params,16,0); /* open_state - only valid for IPC device. */
744 :
745 0 : if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
746 0 : smb_action |= EXTENDED_OPLOCK_GRANTED;
747 : }
748 :
749 0 : SSVAL(params,18,smb_action);
750 :
751 : /*
752 : * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
753 : */
754 0 : SIVAL(params,20,inode);
755 0 : SSVAL(params,24,0); /* Padding. */
756 0 : if (flags & 8) {
757 0 : uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
758 0 : SIVAL(params, 26, ea_size);
759 : } else {
760 0 : SIVAL(params, 26, 0);
761 : }
762 :
763 : /* Send the required number of replies */
764 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
765 0 : out:
766 0 : TALLOC_FREE(smb_fname);
767 0 : }
768 :
769 0 : static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
770 : connection_struct *conn,
771 : struct dptr_struct *dirptr,
772 : uint16_t flags2,
773 : const char *path_mask,
774 : uint32_t dirtype,
775 : int info_level,
776 : bool requires_resume_key,
777 : bool dont_descend,
778 : bool ask_sharemode,
779 : char **ppdata,
780 : char *base_data,
781 : char *end_data,
782 : int space_remaining,
783 : bool *got_exact_match,
784 : int *last_entry_off,
785 : struct ea_list *name_list)
786 : {
787 0 : uint8_t align = 4;
788 0 : const bool do_pad = true;
789 :
790 0 : if (info_level >= 1 && info_level <= 3) {
791 : /* No alignment on earlier info levels. */
792 0 : align = 1;
793 : }
794 :
795 0 : return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
796 : path_mask, dirtype, info_level,
797 : requires_resume_key, dont_descend, ask_sharemode,
798 : true, align, do_pad,
799 : ppdata, base_data, end_data,
800 : space_remaining,
801 : NULL,
802 : got_exact_match,
803 : last_entry_off, name_list, NULL);
804 : }
805 :
806 : /****************************************************************************
807 : Reply to a TRANS2_FINDFIRST.
808 : ****************************************************************************/
809 :
810 0 : static void call_trans2findfirst(connection_struct *conn,
811 : struct smb_request *req,
812 : char **pparams, int total_params,
813 : char **ppdata, int total_data,
814 : unsigned int max_data_bytes)
815 : {
816 : /* We must be careful here that we don't return more than the
817 : allowed number of data bytes. If this means returning fewer than
818 : maxentries then so be it. We assume that the redirector has
819 : enough room for the fixed number of parameter bytes it has
820 : requested. */
821 0 : struct smb_filename *smb_dname = NULL;
822 0 : char *params = *pparams;
823 0 : char *pdata = *ppdata;
824 : char *data_end;
825 : uint32_t dirtype;
826 : int maxentries;
827 : uint16_t findfirst_flags;
828 : bool close_after_first;
829 : bool close_if_end;
830 : bool requires_resume_key;
831 : int info_level;
832 0 : char *directory = NULL;
833 0 : char *mask = NULL;
834 : char *p;
835 0 : int last_entry_off=0;
836 0 : int dptr_num = -1;
837 0 : int numentries = 0;
838 : int i;
839 0 : bool finished = False;
840 0 : bool dont_descend = False;
841 0 : bool out_of_space = False;
842 : int space_remaining;
843 0 : struct ea_list *ea_list = NULL;
844 0 : NTSTATUS ntstatus = NT_STATUS_OK;
845 : bool ask_sharemode;
846 0 : struct smbd_server_connection *sconn = req->sconn;
847 0 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
848 0 : bool backup_priv = false;
849 0 : bool as_root = false;
850 0 : files_struct *fsp = NULL;
851 0 : struct files_struct *dirfsp = NULL;
852 : const struct loadparm_substitution *lp_sub =
853 0 : loadparm_s3_global_substitution();
854 :
855 0 : if (total_params < 13) {
856 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
857 0 : goto out;
858 : }
859 :
860 0 : dirtype = SVAL(params,0);
861 0 : maxentries = SVAL(params,2);
862 0 : findfirst_flags = SVAL(params,4);
863 0 : close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
864 0 : close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
865 0 : requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
866 0 : backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
867 0 : security_token_has_privilege(get_current_nttok(conn),
868 : SEC_PRIV_BACKUP));
869 :
870 0 : info_level = SVAL(params,6);
871 :
872 0 : DBG_NOTICE("dirtype = %"PRIx32", maxentries = %d, "
873 : "close_after_first=%d, close_if_end = %d "
874 : "requires_resume_key = %d backup_priv = %d level = 0x%x, "
875 : "max_data_bytes = %d\n",
876 : dirtype,
877 : maxentries,
878 : close_after_first,
879 : close_if_end,
880 : requires_resume_key,
881 : backup_priv,
882 : info_level,
883 : max_data_bytes);
884 :
885 0 : if (!maxentries) {
886 : /* W2K3 seems to treat zero as 1. */
887 0 : maxentries = 1;
888 : }
889 :
890 0 : switch (info_level) {
891 0 : case SMB_FIND_INFO_STANDARD:
892 : case SMB_FIND_EA_SIZE:
893 : case SMB_FIND_EA_LIST:
894 : case SMB_FIND_FILE_DIRECTORY_INFO:
895 : case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
896 : case SMB_FIND_FILE_NAMES_INFO:
897 : case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
898 : case SMB_FIND_ID_FULL_DIRECTORY_INFO:
899 : case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
900 0 : break;
901 0 : case SMB_FIND_FILE_UNIX:
902 : case SMB_FIND_FILE_UNIX_INFO2:
903 0 : if (!lp_smb1_unix_extensions()) {
904 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
905 0 : goto out;
906 : }
907 0 : if (!req->posix_pathnames) {
908 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
909 0 : goto out;
910 : }
911 0 : break;
912 0 : default:
913 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
914 0 : goto out;
915 : }
916 :
917 0 : if (req->posix_pathnames) {
918 0 : srvstr_get_path_posix(talloc_tos(),
919 : params,
920 0 : req->flags2,
921 : &directory,
922 0 : params+12,
923 0 : total_params - 12,
924 : STR_TERMINATE,
925 : &ntstatus);
926 : } else {
927 0 : srvstr_get_path(talloc_tos(),
928 : params,
929 0 : req->flags2,
930 : &directory,
931 0 : params+12,
932 0 : total_params - 12,
933 : STR_TERMINATE,
934 : &ntstatus);
935 : }
936 0 : if (!NT_STATUS_IS_OK(ntstatus)) {
937 0 : reply_nterror(req, ntstatus);
938 0 : goto out;
939 : }
940 :
941 0 : if (backup_priv) {
942 0 : become_root();
943 0 : as_root = true;
944 : }
945 0 : ntstatus = filename_convert_smb1_search_path(talloc_tos(),
946 : conn,
947 : directory,
948 : ucf_flags,
949 : &dirfsp,
950 : &smb_dname,
951 : &mask);
952 :
953 0 : if (!NT_STATUS_IS_OK(ntstatus)) {
954 0 : if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
955 0 : reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
956 : ERRSRV, ERRbadpath);
957 0 : goto out;
958 : }
959 0 : reply_nterror(req, ntstatus);
960 0 : goto out;
961 : }
962 :
963 0 : TALLOC_FREE(directory);
964 0 : directory = smb_dname->base_name;
965 :
966 0 : DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
967 :
968 0 : if (info_level == SMB_FIND_EA_LIST) {
969 : uint32_t ea_size;
970 :
971 0 : if (total_data < 4) {
972 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
973 0 : goto out;
974 : }
975 :
976 0 : ea_size = IVAL(pdata,0);
977 0 : if (ea_size != total_data) {
978 0 : DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
979 : total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
980 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
981 0 : goto out;
982 : }
983 :
984 0 : if (!lp_ea_support(SNUM(conn))) {
985 0 : reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
986 0 : goto out;
987 : }
988 :
989 : /* Pull out the list of names. */
990 0 : ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
991 0 : if (!ea_list) {
992 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
993 0 : goto out;
994 : }
995 : }
996 :
997 0 : if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
998 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
999 0 : goto out;
1000 : }
1001 :
1002 0 : *ppdata = (char *)SMB_REALLOC(
1003 : *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1004 0 : if(*ppdata == NULL ) {
1005 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1006 0 : goto out;
1007 : }
1008 0 : pdata = *ppdata;
1009 0 : data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1010 : /*
1011 : * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1012 : * error.
1013 : */
1014 0 : memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
1015 : /* Realloc the params space */
1016 0 : *pparams = (char *)SMB_REALLOC(*pparams, 10);
1017 0 : if (*pparams == NULL) {
1018 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1019 0 : goto out;
1020 : }
1021 0 : params = *pparams;
1022 :
1023 : /*
1024 : * Open an fsp on this directory for the dptr.
1025 : */
1026 0 : ntstatus = SMB_VFS_CREATE_FILE(
1027 : conn, /* conn */
1028 : req, /* req */
1029 : dirfsp, /* dirfsp */
1030 : smb_dname, /* dname */
1031 : FILE_LIST_DIRECTORY, /* access_mask */
1032 : FILE_SHARE_READ|
1033 : FILE_SHARE_WRITE, /* share_access */
1034 : FILE_OPEN, /* create_disposition*/
1035 : FILE_DIRECTORY_FILE, /* create_options */
1036 : FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1037 : NO_OPLOCK, /* oplock_request */
1038 : NULL, /* lease */
1039 : 0, /* allocation_size */
1040 : 0, /* private_flags */
1041 : NULL, /* sd */
1042 : NULL, /* ea_list */
1043 : &fsp, /* result */
1044 : NULL, /* pinfo */
1045 : NULL, /* in_context */
1046 : NULL);/* out_context */
1047 :
1048 0 : if (!NT_STATUS_IS_OK(ntstatus)) {
1049 0 : DBG_ERR("failed to open directory %s\n",
1050 : smb_fname_str_dbg(smb_dname));
1051 0 : reply_nterror(req, ntstatus);
1052 0 : goto out;
1053 : }
1054 :
1055 : /* Save the wildcard match and attribs we are using on this directory -
1056 : needed as lanman2 assumes these are being saved between calls */
1057 :
1058 0 : ntstatus = dptr_create(conn,
1059 : req,
1060 : fsp, /* fsp */
1061 : False,
1062 : True,
1063 0 : req->smbpid,
1064 : mask,
1065 : dirtype,
1066 0 : &fsp->dptr);
1067 :
1068 0 : if (!NT_STATUS_IS_OK(ntstatus)) {
1069 : /*
1070 : * Use NULL here for the first parameter (req)
1071 : * as this is not a client visible handle so
1072 : * can'tbe part of an SMB1 chain.
1073 : */
1074 0 : close_file_free(NULL, &fsp, NORMAL_CLOSE);
1075 0 : reply_nterror(req, ntstatus);
1076 0 : goto out;
1077 : }
1078 :
1079 0 : if (backup_priv) {
1080 : /* Remember this in case we have
1081 : to do a findnext. */
1082 0 : dptr_set_priv(fsp->dptr);
1083 : }
1084 :
1085 0 : dptr_num = dptr_dnum(fsp->dptr);
1086 0 : DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1087 :
1088 : /* We don't need to check for VOL here as this is returned by
1089 : a different TRANS2 call. */
1090 :
1091 0 : DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1092 : directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
1093 0 : if (in_list(directory,
1094 0 : lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
1095 0 : dptr_case_sensitive(fsp->dptr))) {
1096 0 : dont_descend = True;
1097 : }
1098 :
1099 0 : p = pdata;
1100 0 : space_remaining = max_data_bytes;
1101 0 : out_of_space = False;
1102 :
1103 0 : ask_sharemode = fsp_search_ask_sharemode(fsp);
1104 :
1105 0 : for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1106 0 : bool got_exact_match = False;
1107 :
1108 : /* this is a heuristic to avoid seeking the dirptr except when
1109 : absolutely necessary. It allows for a filename of about 40 chars */
1110 0 : if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1111 0 : out_of_space = True;
1112 0 : finished = False;
1113 : } else {
1114 0 : ntstatus = get_lanman2_dir_entry(talloc_tos(),
1115 : conn,
1116 0 : fsp->dptr,
1117 0 : req->flags2,
1118 : mask,dirtype,info_level,
1119 : requires_resume_key,dont_descend,
1120 : ask_sharemode,
1121 : &p,pdata,data_end,
1122 : space_remaining,
1123 : &got_exact_match,
1124 : &last_entry_off, ea_list);
1125 0 : if (NT_STATUS_EQUAL(ntstatus,
1126 : NT_STATUS_ILLEGAL_CHARACTER)) {
1127 : /*
1128 : * Bad character conversion on name. Ignore this
1129 : * entry.
1130 : */
1131 0 : continue;
1132 : }
1133 0 : if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1134 0 : out_of_space = true;
1135 : } else {
1136 0 : finished = !NT_STATUS_IS_OK(ntstatus);
1137 : }
1138 : }
1139 :
1140 0 : if (!finished && !out_of_space)
1141 0 : numentries++;
1142 :
1143 : /*
1144 : * As an optimisation if we know we aren't looking
1145 : * for a wildcard name (ie. the name matches the wildcard exactly)
1146 : * then we can finish on any (first) match.
1147 : * This speeds up large directory searches. JRA.
1148 : */
1149 :
1150 0 : if(got_exact_match)
1151 0 : finished = True;
1152 :
1153 : /* Ensure space_remaining never goes -ve. */
1154 0 : if (PTR_DIFF(p,pdata) > max_data_bytes) {
1155 0 : space_remaining = 0;
1156 0 : out_of_space = true;
1157 : } else {
1158 0 : space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1159 : }
1160 : }
1161 :
1162 : /* Check if we can close the dirptr */
1163 0 : if(close_after_first || (finished && close_if_end)) {
1164 0 : DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1165 0 : dptr_num = -1;
1166 0 : close_file_free(NULL, &fsp, NORMAL_CLOSE);
1167 : }
1168 :
1169 : /*
1170 : * If there are no matching entries we must return ERRDOS/ERRbadfile -
1171 : * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1172 : * the protocol level is less than NT1. Tested with smbclient. JRA.
1173 : * This should fix the OS/2 client bug #2335.
1174 : */
1175 :
1176 0 : if(numentries == 0) {
1177 0 : dptr_num = -1;
1178 : /*
1179 : * We may have already closed the file in the
1180 : * close_after_first or finished case above.
1181 : */
1182 0 : if (fsp != NULL) {
1183 0 : close_file_free(NULL, &fsp, NORMAL_CLOSE);
1184 : }
1185 0 : if (get_Protocol() < PROTOCOL_NT1) {
1186 0 : reply_force_doserror(req, ERRDOS, ERRnofiles);
1187 0 : goto out;
1188 : } else {
1189 0 : reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
1190 : ERRDOS, ERRbadfile);
1191 0 : goto out;
1192 : }
1193 : }
1194 :
1195 : /* At this point pdata points to numentries directory entries. */
1196 :
1197 : /* Set up the return parameter block */
1198 0 : SSVAL(params,0,dptr_num);
1199 0 : SSVAL(params,2,numentries);
1200 0 : SSVAL(params,4,finished);
1201 0 : SSVAL(params,6,0); /* Never an EA error */
1202 0 : SSVAL(params,8,last_entry_off);
1203 :
1204 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
1205 : max_data_bytes);
1206 :
1207 0 : if ((! *directory) && dptr_path(sconn, dptr_num)) {
1208 0 : directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
1209 0 : if (!directory) {
1210 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1211 : }
1212 : }
1213 :
1214 0 : DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1215 : smb_fn_name(req->cmd),
1216 : mask, directory, dirtype, numentries ) );
1217 :
1218 : /*
1219 : * Force a name mangle here to ensure that the
1220 : * mask as an 8.3 name is top of the mangled cache.
1221 : * The reasons for this are subtle. Don't remove
1222 : * this code unless you know what you are doing
1223 : * (see PR#13758). JRA.
1224 : */
1225 :
1226 0 : if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
1227 : char mangled_name[13];
1228 0 : name_to_8_3(mask, mangled_name, True, conn->params);
1229 : }
1230 0 : out:
1231 :
1232 0 : if (as_root) {
1233 0 : unbecome_root();
1234 : }
1235 :
1236 0 : TALLOC_FREE(smb_dname);
1237 0 : return;
1238 : }
1239 :
1240 : /****************************************************************************
1241 : Reply to a TRANS2_FINDNEXT.
1242 : ****************************************************************************/
1243 :
1244 0 : static void call_trans2findnext(connection_struct *conn,
1245 : struct smb_request *req,
1246 : char **pparams, int total_params,
1247 : char **ppdata, int total_data,
1248 : unsigned int max_data_bytes)
1249 : {
1250 : /* We must be careful here that we don't return more than the
1251 : allowed number of data bytes. If this means returning fewer than
1252 : maxentries then so be it. We assume that the redirector has
1253 : enough room for the fixed number of parameter bytes it has
1254 : requested. */
1255 0 : char *params = *pparams;
1256 0 : char *pdata = *ppdata;
1257 : char *data_end;
1258 : int dptr_num;
1259 : int maxentries;
1260 : uint16_t info_level;
1261 : uint32_t resume_key;
1262 : uint16_t findnext_flags;
1263 : bool close_after_request;
1264 : bool close_if_end;
1265 : bool requires_resume_key;
1266 : bool continue_bit;
1267 0 : char *resume_name = NULL;
1268 0 : const char *mask = NULL;
1269 0 : const char *directory = NULL;
1270 0 : char *p = NULL;
1271 : uint16_t dirtype;
1272 0 : int numentries = 0;
1273 0 : int i, last_entry_off=0;
1274 0 : bool finished = False;
1275 0 : bool dont_descend = False;
1276 0 : bool out_of_space = False;
1277 : int space_remaining;
1278 0 : struct ea_list *ea_list = NULL;
1279 0 : NTSTATUS ntstatus = NT_STATUS_OK;
1280 : bool ask_sharemode;
1281 0 : TALLOC_CTX *ctx = talloc_tos();
1282 0 : struct smbd_server_connection *sconn = req->sconn;
1283 0 : bool backup_priv = false;
1284 0 : bool as_root = false;
1285 0 : files_struct *fsp = NULL;
1286 : const struct loadparm_substitution *lp_sub =
1287 0 : loadparm_s3_global_substitution();
1288 :
1289 0 : if (total_params < 13) {
1290 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1291 0 : return;
1292 : }
1293 :
1294 0 : dptr_num = SVAL(params,0);
1295 0 : maxentries = SVAL(params,2);
1296 0 : info_level = SVAL(params,4);
1297 0 : resume_key = IVAL(params,6);
1298 0 : findnext_flags = SVAL(params,10);
1299 0 : close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1300 0 : close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1301 0 : requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1302 0 : continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1303 :
1304 0 : if (!continue_bit) {
1305 : /* We only need resume_name if continue_bit is zero. */
1306 0 : if (req->posix_pathnames) {
1307 0 : srvstr_get_path_posix(ctx,
1308 : params,
1309 0 : req->flags2,
1310 : &resume_name,
1311 0 : params+12,
1312 0 : total_params - 12,
1313 : STR_TERMINATE,
1314 : &ntstatus);
1315 : } else {
1316 0 : srvstr_get_path(ctx,
1317 : params,
1318 0 : req->flags2,
1319 : &resume_name,
1320 0 : params+12,
1321 0 : total_params - 12,
1322 : STR_TERMINATE,
1323 : &ntstatus);
1324 : }
1325 0 : if (!NT_STATUS_IS_OK(ntstatus)) {
1326 : /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1327 : complain (it thinks we're asking for the directory above the shared
1328 : path or an invalid name). Catch this as the resume name is only compared, never used in
1329 : a file access. JRA. */
1330 0 : srvstr_pull_talloc(ctx, params, req->flags2,
1331 : &resume_name, params+12,
1332 : total_params - 12,
1333 : STR_TERMINATE);
1334 :
1335 0 : if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
1336 0 : reply_nterror(req, ntstatus);
1337 0 : return;
1338 : }
1339 : }
1340 : }
1341 :
1342 0 : DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1343 : close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1344 : resume_key = %d resume name = %s continue=%d level = %d\n",
1345 : dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1346 : requires_resume_key, resume_key,
1347 : resume_name ? resume_name : "(NULL)", continue_bit, info_level));
1348 :
1349 0 : if (!maxentries) {
1350 : /* W2K3 seems to treat zero as 1. */
1351 0 : maxentries = 1;
1352 : }
1353 :
1354 0 : switch (info_level) {
1355 0 : case SMB_FIND_INFO_STANDARD:
1356 : case SMB_FIND_EA_SIZE:
1357 : case SMB_FIND_EA_LIST:
1358 : case SMB_FIND_FILE_DIRECTORY_INFO:
1359 : case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1360 : case SMB_FIND_FILE_NAMES_INFO:
1361 : case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1362 : case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1363 : case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1364 0 : break;
1365 0 : case SMB_FIND_FILE_UNIX:
1366 : case SMB_FIND_FILE_UNIX_INFO2:
1367 0 : if (!lp_smb1_unix_extensions()) {
1368 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1369 0 : return;
1370 : }
1371 0 : if (!req->posix_pathnames) {
1372 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1373 0 : return;
1374 : }
1375 0 : break;
1376 0 : default:
1377 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1378 0 : return;
1379 : }
1380 :
1381 0 : if (info_level == SMB_FIND_EA_LIST) {
1382 : uint32_t ea_size;
1383 :
1384 0 : if (total_data < 4) {
1385 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1386 0 : return;
1387 : }
1388 :
1389 0 : ea_size = IVAL(pdata,0);
1390 0 : if (ea_size != total_data) {
1391 0 : DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1392 : total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1393 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1394 0 : return;
1395 : }
1396 :
1397 0 : if (!lp_ea_support(SNUM(conn))) {
1398 0 : reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1399 0 : return;
1400 : }
1401 :
1402 : /* Pull out the list of names. */
1403 0 : ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1404 0 : if (!ea_list) {
1405 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1406 0 : return;
1407 : }
1408 : }
1409 :
1410 0 : if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1411 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1412 0 : return;
1413 : }
1414 :
1415 0 : *ppdata = (char *)SMB_REALLOC(
1416 : *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1417 0 : if(*ppdata == NULL) {
1418 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1419 0 : return;
1420 : }
1421 :
1422 0 : pdata = *ppdata;
1423 0 : data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1424 :
1425 : /*
1426 : * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1427 : * error.
1428 : */
1429 0 : memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
1430 : /* Realloc the params space */
1431 0 : *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1432 0 : if(*pparams == NULL ) {
1433 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1434 0 : return;
1435 : }
1436 :
1437 0 : params = *pparams;
1438 :
1439 : /* Check that the dptr is valid */
1440 0 : fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1441 0 : if (fsp == NULL) {
1442 0 : reply_nterror(req, STATUS_NO_MORE_FILES);
1443 0 : return;
1444 : }
1445 :
1446 0 : directory = dptr_path(sconn, dptr_num);
1447 :
1448 : /* Get the wildcard mask from the dptr */
1449 0 : if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
1450 0 : DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1451 0 : reply_nterror(req, STATUS_NO_MORE_FILES);
1452 0 : return;
1453 : }
1454 :
1455 : /* Get the attr mask from the dptr */
1456 0 : dirtype = dptr_attr(sconn, dptr_num);
1457 :
1458 0 : backup_priv = dptr_get_priv(fsp->dptr);
1459 :
1460 0 : DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
1461 : "backup_priv = %d\n",
1462 : dptr_num, mask, dirtype,
1463 : (long)fsp->dptr,
1464 : dptr_TellDir(fsp->dptr),
1465 : (int)backup_priv));
1466 :
1467 : /* We don't need to check for VOL here as this is returned by
1468 : a different TRANS2 call. */
1469 :
1470 0 : DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1471 : directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1472 0 : if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),
1473 0 : dptr_case_sensitive(fsp->dptr)))
1474 0 : dont_descend = True;
1475 :
1476 0 : p = pdata;
1477 0 : space_remaining = max_data_bytes;
1478 0 : out_of_space = False;
1479 :
1480 0 : if (backup_priv) {
1481 0 : become_root();
1482 0 : as_root = true;
1483 : }
1484 :
1485 : /*
1486 : * Seek to the correct position. We no longer use the resume key but
1487 : * depend on the last file name instead.
1488 : */
1489 :
1490 0 : if(!continue_bit && resume_name && *resume_name) {
1491 : SMB_STRUCT_STAT st;
1492 0 : bool posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
1493 :
1494 0 : long current_pos = 0;
1495 : /*
1496 : * Remember, name_to_8_3 is called by
1497 : * get_lanman2_dir_entry(), so the resume name
1498 : * could be mangled. Ensure we check the unmangled name.
1499 : */
1500 :
1501 0 : if (!posix_open &&
1502 0 : mangle_is_mangled(resume_name, conn->params)) {
1503 0 : char *new_resume_name = NULL;
1504 0 : mangle_lookup_name_from_8_3(ctx,
1505 : resume_name,
1506 : &new_resume_name,
1507 0 : conn->params);
1508 0 : if (new_resume_name) {
1509 0 : resume_name = new_resume_name;
1510 : }
1511 : }
1512 :
1513 : /*
1514 : * Fix for NT redirector problem triggered by resume key indexes
1515 : * changing between directory scans. We now return a resume key of 0
1516 : * and instead look for the filename to continue from (also given
1517 : * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1518 : * findfirst/findnext (as is usual) then the directory pointer
1519 : * should already be at the correct place.
1520 : */
1521 :
1522 0 : finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
1523 : } /* end if resume_name && !continue_bit */
1524 :
1525 0 : ask_sharemode = fsp_search_ask_sharemode(fsp);
1526 :
1527 0 : for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1528 0 : bool got_exact_match = False;
1529 :
1530 : /* this is a heuristic to avoid seeking the fsp->dptr except when
1531 : absolutely necessary. It allows for a filename of about 40 chars */
1532 0 : if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1533 0 : out_of_space = True;
1534 0 : finished = False;
1535 : } else {
1536 0 : ntstatus = get_lanman2_dir_entry(ctx,
1537 : conn,
1538 0 : fsp->dptr,
1539 0 : req->flags2,
1540 : mask,dirtype,info_level,
1541 : requires_resume_key,dont_descend,
1542 : ask_sharemode,
1543 : &p,pdata,data_end,
1544 : space_remaining,
1545 : &got_exact_match,
1546 : &last_entry_off, ea_list);
1547 0 : if (NT_STATUS_EQUAL(ntstatus,
1548 : NT_STATUS_ILLEGAL_CHARACTER)) {
1549 : /*
1550 : * Bad character conversion on name. Ignore this
1551 : * entry.
1552 : */
1553 0 : continue;
1554 : }
1555 0 : if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1556 0 : out_of_space = true;
1557 : } else {
1558 0 : finished = !NT_STATUS_IS_OK(ntstatus);
1559 : }
1560 : }
1561 :
1562 0 : if (!finished && !out_of_space)
1563 0 : numentries++;
1564 :
1565 : /*
1566 : * As an optimisation if we know we aren't looking
1567 : * for a wildcard name (ie. the name matches the wildcard exactly)
1568 : * then we can finish on any (first) match.
1569 : * This speeds up large directory searches. JRA.
1570 : */
1571 :
1572 0 : if(got_exact_match)
1573 0 : finished = True;
1574 :
1575 0 : space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1576 : }
1577 :
1578 0 : DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1579 : smb_fn_name(req->cmd),
1580 : mask, directory, dirtype, numentries ) );
1581 :
1582 : /* Check if we can close the fsp->dptr */
1583 0 : if(close_after_request || (finished && close_if_end)) {
1584 0 : DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1585 0 : dptr_num = -1;
1586 0 : close_file_free(NULL, &fsp, NORMAL_CLOSE);
1587 : }
1588 :
1589 0 : if (as_root) {
1590 0 : unbecome_root();
1591 : }
1592 :
1593 : /* Set up the return parameter block */
1594 0 : SSVAL(params,0,numentries);
1595 0 : SSVAL(params,2,finished);
1596 0 : SSVAL(params,4,0); /* Never an EA error */
1597 0 : SSVAL(params,6,last_entry_off);
1598 :
1599 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
1600 : max_data_bytes);
1601 :
1602 0 : return;
1603 : }
1604 :
1605 : /****************************************************************************
1606 : Reply to a TRANS2_QFSINFO (query filesystem info).
1607 : ****************************************************************************/
1608 :
1609 8 : static void call_trans2qfsinfo(connection_struct *conn,
1610 : struct smb_request *req,
1611 : char **pparams, int total_params,
1612 : char **ppdata, int total_data,
1613 : unsigned int max_data_bytes)
1614 : {
1615 8 : char *params = *pparams;
1616 : uint16_t info_level;
1617 8 : int data_len = 0;
1618 : size_t fixed_portion;
1619 : NTSTATUS status;
1620 :
1621 8 : if (total_params < 2) {
1622 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1623 0 : return;
1624 : }
1625 :
1626 8 : info_level = SVAL(params,0);
1627 :
1628 8 : if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1629 0 : if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
1630 0 : DEBUG(0,("call_trans2qfsinfo: encryption required "
1631 : "and info level 0x%x sent.\n",
1632 : (unsigned int)info_level));
1633 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1634 0 : return;
1635 : }
1636 : }
1637 :
1638 8 : DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1639 :
1640 8 : status = smbd_do_qfsinfo(req->xconn, conn, req,
1641 : info_level,
1642 8 : req->flags2,
1643 : max_data_bytes,
1644 : &fixed_portion,
1645 : NULL,
1646 : ppdata, &data_len);
1647 8 : if (!NT_STATUS_IS_OK(status)) {
1648 0 : reply_nterror(req, status);
1649 0 : return;
1650 : }
1651 :
1652 8 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
1653 : max_data_bytes);
1654 :
1655 8 : DEBUG( 4, ( "%s info_level = %d\n",
1656 : smb_fn_name(req->cmd), info_level) );
1657 :
1658 8 : return;
1659 : }
1660 :
1661 : /****************************************************************************
1662 : Reply to a TRANS2_SETFSINFO (set filesystem info).
1663 : ****************************************************************************/
1664 :
1665 0 : static void call_trans2setfsinfo(connection_struct *conn,
1666 : struct smb_request *req,
1667 : char **pparams, int total_params,
1668 : char **ppdata, int total_data,
1669 : unsigned int max_data_bytes)
1670 : {
1671 : const struct loadparm_substitution *lp_sub =
1672 0 : loadparm_s3_global_substitution();
1673 0 : struct smbXsrv_connection *xconn = req->xconn;
1674 0 : char *pdata = *ppdata;
1675 0 : char *params = *pparams;
1676 : uint16_t info_level;
1677 :
1678 0 : DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
1679 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
1680 :
1681 : /* */
1682 0 : if (total_params < 4) {
1683 0 : DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1684 : total_params));
1685 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1686 0 : return;
1687 : }
1688 :
1689 0 : info_level = SVAL(params,2);
1690 :
1691 0 : if (IS_IPC(conn)) {
1692 0 : if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
1693 : info_level != SMB_SET_CIFS_UNIX_INFO) {
1694 0 : DEBUG(0,("call_trans2setfsinfo: not an allowed "
1695 : "info level (0x%x) on IPC$.\n",
1696 : (unsigned int)info_level));
1697 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1698 0 : return;
1699 : }
1700 : }
1701 :
1702 0 : if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1703 0 : if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
1704 0 : DEBUG(0,("call_trans2setfsinfo: encryption required "
1705 : "and info level 0x%x sent.\n",
1706 : (unsigned int)info_level));
1707 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1708 0 : return;
1709 : }
1710 : }
1711 :
1712 0 : switch(info_level) {
1713 0 : case SMB_SET_CIFS_UNIX_INFO:
1714 0 : if (!lp_smb1_unix_extensions()) {
1715 0 : DEBUG(2,("call_trans2setfsinfo: "
1716 : "SMB_SET_CIFS_UNIX_INFO is invalid with "
1717 : "unix extensions off\n"));
1718 0 : reply_nterror(req,
1719 : NT_STATUS_INVALID_LEVEL);
1720 0 : return;
1721 : }
1722 :
1723 : /* There should be 12 bytes of capabilities set. */
1724 0 : if (total_data < 12) {
1725 0 : reply_nterror(
1726 : req,
1727 : NT_STATUS_INVALID_PARAMETER);
1728 0 : return;
1729 : }
1730 0 : xconn->smb1.unix_info.client_major = SVAL(pdata,0);
1731 0 : xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
1732 0 : xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
1733 0 : xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
1734 :
1735 : /* Just print these values for now. */
1736 0 : DBG_DEBUG("set unix_info info. "
1737 : "major = %"PRIu16", minor = %"PRIu16
1738 : "cap_low = 0x%"PRIx32", "
1739 : "cap_high = 0x%"PRIx32"\n",
1740 : xconn->smb1.unix_info.client_major,
1741 : xconn->smb1.unix_info.client_minor,
1742 : xconn->smb1.unix_info.client_cap_low,
1743 : xconn->smb1.unix_info.client_cap_high);
1744 :
1745 : /*
1746 : * Here is where we must switch to posix
1747 : * pathname processing...
1748 : */
1749 0 : if (xconn->smb1.unix_info.client_cap_low &
1750 : CIFS_UNIX_POSIX_PATHNAMES_CAP)
1751 : {
1752 0 : lp_set_posix_pathnames();
1753 0 : mangle_change_to_posix();
1754 : }
1755 :
1756 0 : if ((xconn->smb1.unix_info.client_cap_low &
1757 0 : CIFS_UNIX_FCNTL_LOCKS_CAP) &&
1758 0 : !(xconn->smb1.unix_info.client_cap_low &
1759 : CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP))
1760 : {
1761 : /* Client that knows how to do posix locks,
1762 : * but not posix open/mkdir operations. Set a
1763 : * default type for read/write checks. */
1764 :
1765 0 : lp_set_posix_default_cifsx_readwrite_locktype(
1766 : POSIX_LOCK);
1767 :
1768 : }
1769 0 : break;
1770 :
1771 0 : case SMB_REQUEST_TRANSPORT_ENCRYPTION:
1772 : {
1773 : NTSTATUS status;
1774 0 : size_t param_len = 0;
1775 0 : size_t data_len = total_data;
1776 :
1777 0 : if (!lp_smb1_unix_extensions()) {
1778 0 : reply_nterror(
1779 : req,
1780 : NT_STATUS_INVALID_LEVEL);
1781 0 : return;
1782 : }
1783 :
1784 0 : if (lp_server_smb_encrypt(SNUM(conn)) ==
1785 : SMB_ENCRYPTION_OFF) {
1786 0 : reply_nterror(
1787 : req,
1788 : NT_STATUS_NOT_SUPPORTED);
1789 0 : return;
1790 : }
1791 :
1792 0 : if (xconn->smb1.echo_handler.trusted_fde) {
1793 0 : DEBUG( 2,("call_trans2setfsinfo: "
1794 : "request transport encryption disabled"
1795 : "with 'fork echo handler = yes'\n"));
1796 0 : reply_nterror(
1797 : req,
1798 : NT_STATUS_NOT_SUPPORTED);
1799 0 : return;
1800 : }
1801 :
1802 0 : DEBUG( 4,("call_trans2setfsinfo: "
1803 : "request transport encryption.\n"));
1804 :
1805 0 : status = srv_request_encryption_setup(conn,
1806 : (unsigned char **)ppdata,
1807 : &data_len,
1808 : (unsigned char **)pparams,
1809 : ¶m_len);
1810 :
1811 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
1812 0 : !NT_STATUS_IS_OK(status)) {
1813 0 : reply_nterror(req, status);
1814 0 : return;
1815 : }
1816 :
1817 0 : send_trans2_replies(conn, req,
1818 0 : NT_STATUS_OK,
1819 : *pparams,
1820 : param_len,
1821 : *ppdata,
1822 : data_len,
1823 : max_data_bytes);
1824 :
1825 0 : if (NT_STATUS_IS_OK(status)) {
1826 : /* Server-side transport
1827 : * encryption is now *on*. */
1828 0 : status = srv_encryption_start(conn);
1829 0 : if (!NT_STATUS_IS_OK(status)) {
1830 0 : char *reason = talloc_asprintf(talloc_tos(),
1831 : "Failure in setting "
1832 : "up encrypted transport: %s",
1833 : nt_errstr(status));
1834 0 : exit_server_cleanly(reason);
1835 : }
1836 : }
1837 0 : return;
1838 : }
1839 :
1840 0 : case SMB_FS_QUOTA_INFORMATION:
1841 : {
1842 : NTSTATUS status;
1843 0 : DATA_BLOB qdata = {
1844 : .data = (uint8_t *)pdata,
1845 : .length = total_data
1846 : };
1847 0 : files_struct *fsp = NULL;
1848 0 : fsp = file_fsp(req, SVAL(params,0));
1849 :
1850 0 : status = smb_set_fsquota(conn,
1851 : req,
1852 : fsp,
1853 : &qdata);
1854 0 : if (!NT_STATUS_IS_OK(status)) {
1855 0 : reply_nterror(req, status);
1856 0 : return;
1857 : }
1858 0 : break;
1859 : }
1860 0 : default:
1861 0 : DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1862 : info_level));
1863 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1864 0 : return;
1865 : break;
1866 : }
1867 :
1868 : /*
1869 : * sending this reply works fine,
1870 : * but I'm not sure it's the same
1871 : * like windows do...
1872 : * --metze
1873 : */
1874 0 : reply_smb1_outbuf(req, 10, 0);
1875 : }
1876 :
1877 : /****************************************************************************
1878 : Reply to a TRANSACT2_QFILEINFO on a PIPE !
1879 : ****************************************************************************/
1880 :
1881 0 : static void call_trans2qpipeinfo(connection_struct *conn,
1882 : struct smb_request *req,
1883 : files_struct *fsp,
1884 : uint16_t info_level,
1885 : unsigned int tran_call,
1886 : char **pparams, int total_params,
1887 : char **ppdata, int total_data,
1888 : unsigned int max_data_bytes)
1889 : {
1890 0 : char *params = *pparams;
1891 0 : char *pdata = *ppdata;
1892 0 : unsigned int data_size = 0;
1893 0 : unsigned int param_size = 2;
1894 :
1895 0 : if (!fsp_is_np(fsp)) {
1896 0 : reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1897 0 : return;
1898 : }
1899 :
1900 0 : *pparams = (char *)SMB_REALLOC(*pparams,2);
1901 0 : if (*pparams == NULL) {
1902 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1903 0 : return;
1904 : }
1905 0 : params = *pparams;
1906 0 : SSVAL(params,0,0);
1907 0 : if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1908 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1909 0 : return;
1910 : }
1911 0 : data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
1912 0 : *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
1913 0 : if (*ppdata == NULL ) {
1914 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1915 0 : return;
1916 : }
1917 0 : pdata = *ppdata;
1918 :
1919 0 : switch (info_level) {
1920 0 : case SMB_FILE_STANDARD_INFORMATION:
1921 0 : memset(pdata,0,24);
1922 0 : SOFF_T(pdata,0,4096LL);
1923 0 : SIVAL(pdata,16,1);
1924 0 : SIVAL(pdata,20,1);
1925 0 : data_size = 24;
1926 0 : break;
1927 :
1928 0 : default:
1929 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1930 0 : return;
1931 : }
1932 :
1933 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
1934 : max_data_bytes);
1935 :
1936 0 : return;
1937 : }
1938 :
1939 0 : static void handle_trans2qfilepathinfo_result(
1940 : connection_struct *conn,
1941 : struct smb_request *req,
1942 : uint16_t info_level,
1943 : NTSTATUS status,
1944 : char *pdata,
1945 : int data_return_size,
1946 : size_t fixed_portion,
1947 : unsigned int max_data_bytes)
1948 : {
1949 0 : char params[2] = { 0, 0, };
1950 0 : int param_size = 2;
1951 :
1952 : /*
1953 : * draft-leach-cifs-v1-spec-02.txt
1954 : * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
1955 : * says:
1956 : *
1957 : * The requested information is placed in the Data portion of the
1958 : * transaction response. For the information levels greater than 0x100,
1959 : * the transaction response has 1 parameter word which should be
1960 : * ignored by the client.
1961 : *
1962 : * However Windows only follows this rule for the IS_NAME_VALID call.
1963 : */
1964 0 : switch (info_level) {
1965 0 : case SMB_INFO_IS_NAME_VALID:
1966 0 : param_size = 0;
1967 0 : break;
1968 : }
1969 :
1970 0 : if (!NT_STATUS_IS_OK(status)) {
1971 0 : if (open_was_deferred(req->xconn, req->mid)) {
1972 : /* We have re-scheduled this call. */
1973 0 : return;
1974 : }
1975 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1976 0 : bool ok = defer_smb1_sharing_violation(req);
1977 0 : if (ok) {
1978 0 : return;
1979 : }
1980 : }
1981 0 : reply_nterror(req, status);
1982 0 : return;
1983 : }
1984 :
1985 0 : if (fixed_portion > max_data_bytes) {
1986 0 : reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
1987 0 : return;
1988 : }
1989 :
1990 0 : send_trans2_replies(
1991 : conn,
1992 : req,
1993 0 : NT_STATUS_OK,
1994 : params,
1995 : param_size,
1996 : pdata,
1997 : data_return_size,
1998 : max_data_bytes);
1999 : }
2000 :
2001 : /****************************************************************************
2002 : Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2003 : file name or file id).
2004 : ****************************************************************************/
2005 :
2006 0 : static void call_trans2qfilepathinfo(connection_struct *conn,
2007 : struct smb_request *req,
2008 : unsigned int tran_call,
2009 : uint16_t info_level,
2010 : struct smb_filename *smb_fname,
2011 : struct files_struct *fsp,
2012 : bool delete_pending,
2013 : struct timespec write_time_ts,
2014 : char **pparams, int total_params,
2015 : char **ppdata, int total_data,
2016 : unsigned int max_data_bytes)
2017 : {
2018 0 : char *params = *pparams;
2019 0 : char *pdata = *ppdata;
2020 0 : unsigned int data_size = 0;
2021 0 : struct ea_list *ea_list = NULL;
2022 : size_t fixed_portion;
2023 0 : NTSTATUS status = NT_STATUS_OK;
2024 :
2025 0 : DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
2026 : "total_data=%d\n", smb_fname_str_dbg(smb_fname),
2027 : fsp_fnum_dbg(fsp),
2028 : info_level,tran_call,total_data));
2029 :
2030 : /* Pull out any data sent here before we realloc. */
2031 0 : switch (info_level) {
2032 0 : case SMB_INFO_QUERY_EAS_FROM_LIST:
2033 : {
2034 : /* Pull any EA list from the data portion. */
2035 : uint32_t ea_size;
2036 :
2037 0 : if (total_data < 4) {
2038 0 : reply_nterror(
2039 : req, NT_STATUS_INVALID_PARAMETER);
2040 0 : return;
2041 : }
2042 0 : ea_size = IVAL(pdata,0);
2043 :
2044 0 : if (total_data > 0 && ea_size != total_data) {
2045 0 : DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2046 : total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2047 0 : reply_nterror(
2048 : req, NT_STATUS_INVALID_PARAMETER);
2049 0 : return;
2050 : }
2051 :
2052 0 : if (!lp_ea_support(SNUM(conn))) {
2053 0 : reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2054 0 : return;
2055 : }
2056 :
2057 : /* Pull out the list of names. */
2058 0 : ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
2059 0 : if (!ea_list) {
2060 0 : reply_nterror(
2061 : req, NT_STATUS_INVALID_PARAMETER);
2062 0 : return;
2063 : }
2064 0 : break;
2065 : }
2066 :
2067 0 : default:
2068 0 : break;
2069 : }
2070 :
2071 0 : *pparams = (char *)SMB_REALLOC(*pparams,2);
2072 0 : if (*pparams == NULL) {
2073 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2074 0 : return;
2075 : }
2076 0 : params = *pparams;
2077 0 : SSVAL(params,0,0);
2078 :
2079 0 : if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
2080 : /*
2081 : * We use levels that start with 0xFF00
2082 : * internally to represent SMB2 specific levels
2083 : */
2084 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2085 0 : return;
2086 : }
2087 :
2088 0 : status = smbd_do_qfilepathinfo(conn, req, req, info_level,
2089 : fsp, smb_fname,
2090 : delete_pending, write_time_ts,
2091 : ea_list,
2092 0 : req->flags2, max_data_bytes,
2093 : &fixed_portion,
2094 : ppdata, &data_size);
2095 :
2096 0 : handle_trans2qfilepathinfo_result(
2097 : conn,
2098 : req,
2099 : info_level,
2100 : status,
2101 : *ppdata,
2102 : data_size,
2103 : fixed_portion,
2104 : max_data_bytes);
2105 : }
2106 :
2107 0 : static NTSTATUS smb_q_unix_basic(
2108 : struct connection_struct *conn,
2109 : struct smb_request *req,
2110 : struct smb_filename *smb_fname,
2111 : struct files_struct *fsp,
2112 : char **ppdata,
2113 : int *ptotal_data)
2114 : {
2115 0 : const int total_data = 100;
2116 :
2117 0 : *ppdata = SMB_REALLOC(*ppdata, total_data);
2118 0 : if (*ppdata == NULL) {
2119 0 : return NT_STATUS_NO_MEMORY;
2120 : }
2121 0 : store_file_unix_basic(conn, *ppdata, fsp, &smb_fname->st);
2122 :
2123 0 : *ptotal_data = total_data;
2124 :
2125 0 : return NT_STATUS_OK;
2126 : }
2127 :
2128 0 : static NTSTATUS smb_q_unix_info2(
2129 : struct connection_struct *conn,
2130 : struct smb_request *req,
2131 : struct smb_filename *smb_fname,
2132 : struct files_struct *fsp,
2133 : char **ppdata,
2134 : int *ptotal_data)
2135 : {
2136 0 : const int total_data = 116;
2137 :
2138 0 : *ppdata = SMB_REALLOC(*ppdata, total_data);
2139 0 : if (*ppdata == NULL) {
2140 0 : return NT_STATUS_NO_MEMORY;
2141 : }
2142 0 : store_file_unix_basic_info2(conn, *ppdata, fsp, &smb_fname->st);
2143 :
2144 0 : *ptotal_data = total_data;
2145 :
2146 0 : return NT_STATUS_OK;
2147 : }
2148 :
2149 : #if defined(HAVE_POSIX_ACLS)
2150 : /****************************************************************************
2151 : Utility function to open a fsp for a POSIX handle operation.
2152 : ****************************************************************************/
2153 :
2154 0 : static NTSTATUS get_posix_fsp(connection_struct *conn,
2155 : struct smb_request *req,
2156 : struct smb_filename *smb_fname,
2157 : uint32_t access_mask,
2158 : files_struct **ret_fsp)
2159 : {
2160 : NTSTATUS status;
2161 0 : uint32_t create_disposition = FILE_OPEN;
2162 0 : uint32_t share_access = FILE_SHARE_READ|
2163 : FILE_SHARE_WRITE|
2164 : FILE_SHARE_DELETE;
2165 0 : struct smb2_create_blobs *posx = NULL;
2166 :
2167 : /*
2168 : * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
2169 : * but set reasonable defaults.
2170 : */
2171 0 : uint32_t file_attributes = 0664;
2172 0 : uint32_t oplock = NO_OPLOCK;
2173 0 : uint32_t create_options = FILE_NON_DIRECTORY_FILE;
2174 :
2175 : /* File or directory must exist. */
2176 0 : if (!VALID_STAT(smb_fname->st)) {
2177 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2178 : }
2179 : /* Cannot be a symlink. */
2180 0 : if (S_ISLNK(smb_fname->st.st_ex_mode)) {
2181 0 : return NT_STATUS_ACCESS_DENIED;
2182 : }
2183 : /* Set options correctly for directory open. */
2184 0 : if (S_ISDIR(smb_fname->st.st_ex_mode)) {
2185 : /*
2186 : * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
2187 : * directories, but set reasonable defaults.
2188 : */
2189 0 : file_attributes = 0775;
2190 0 : create_options = FILE_DIRECTORY_FILE;
2191 : }
2192 :
2193 0 : status = make_smb2_posix_create_ctx(
2194 : talloc_tos(), &posx, file_attributes);
2195 0 : if (!NT_STATUS_IS_OK(status)) {
2196 0 : DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
2197 : nt_errstr(status));
2198 0 : goto done;
2199 : }
2200 :
2201 0 : status = SMB_VFS_CREATE_FILE(
2202 : conn, /* conn */
2203 : req, /* req */
2204 : NULL, /* dirfsp */
2205 : smb_fname, /* fname */
2206 : access_mask, /* access_mask */
2207 : share_access, /* share_access */
2208 : create_disposition,/* create_disposition*/
2209 : create_options, /* create_options */
2210 : file_attributes,/* file_attributes */
2211 : oplock, /* oplock_request */
2212 : NULL, /* lease */
2213 : 0, /* allocation_size */
2214 : 0, /* private_flags */
2215 : NULL, /* sd */
2216 : NULL, /* ea_list */
2217 : ret_fsp, /* result */
2218 : NULL, /* pinfo */
2219 : posx, /* in_context */
2220 : NULL); /* out_context */
2221 :
2222 0 : done:
2223 0 : TALLOC_FREE(posx);
2224 0 : return status;
2225 : }
2226 :
2227 : /****************************************************************************
2228 : Utility function to count the number of entries in a POSIX acl.
2229 : ****************************************************************************/
2230 :
2231 0 : static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2232 : {
2233 0 : unsigned int ace_count = 0;
2234 0 : int entry_id = SMB_ACL_FIRST_ENTRY;
2235 : SMB_ACL_ENTRY_T entry;
2236 :
2237 0 : while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2238 0 : entry_id = SMB_ACL_NEXT_ENTRY;
2239 0 : ace_count++;
2240 : }
2241 0 : return ace_count;
2242 : }
2243 :
2244 : /****************************************************************************
2245 : Utility function to marshall a POSIX acl into wire format.
2246 : ****************************************************************************/
2247 :
2248 0 : static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2249 : {
2250 0 : int entry_id = SMB_ACL_FIRST_ENTRY;
2251 : SMB_ACL_ENTRY_T entry;
2252 :
2253 0 : while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2254 : SMB_ACL_TAG_T tagtype;
2255 : SMB_ACL_PERMSET_T permset;
2256 0 : unsigned char perms = 0;
2257 : unsigned int own_grp;
2258 :
2259 0 : entry_id = SMB_ACL_NEXT_ENTRY;
2260 :
2261 0 : if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
2262 0 : DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2263 0 : return False;
2264 : }
2265 :
2266 0 : if (sys_acl_get_permset(entry, &permset) == -1) {
2267 0 : DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2268 0 : return False;
2269 : }
2270 :
2271 0 : perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2272 0 : perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2273 0 : perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2274 :
2275 0 : SCVAL(pdata,1,perms);
2276 :
2277 0 : switch (tagtype) {
2278 0 : case SMB_ACL_USER_OBJ:
2279 0 : SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2280 0 : own_grp = (unsigned int)pst->st_ex_uid;
2281 0 : SIVAL(pdata,2,own_grp);
2282 0 : SIVAL(pdata,6,0);
2283 0 : break;
2284 0 : case SMB_ACL_USER:
2285 : {
2286 0 : uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
2287 0 : if (!puid) {
2288 0 : DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2289 0 : return False;
2290 : }
2291 0 : own_grp = (unsigned int)*puid;
2292 0 : SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2293 0 : SIVAL(pdata,2,own_grp);
2294 0 : SIVAL(pdata,6,0);
2295 0 : break;
2296 : }
2297 0 : case SMB_ACL_GROUP_OBJ:
2298 0 : SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2299 0 : own_grp = (unsigned int)pst->st_ex_gid;
2300 0 : SIVAL(pdata,2,own_grp);
2301 0 : SIVAL(pdata,6,0);
2302 0 : break;
2303 0 : case SMB_ACL_GROUP:
2304 : {
2305 0 : gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
2306 0 : if (!pgid) {
2307 0 : DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2308 0 : return False;
2309 : }
2310 0 : own_grp = (unsigned int)*pgid;
2311 0 : SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2312 0 : SIVAL(pdata,2,own_grp);
2313 0 : SIVAL(pdata,6,0);
2314 0 : break;
2315 : }
2316 0 : case SMB_ACL_MASK:
2317 0 : SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2318 0 : SIVAL(pdata,2,0xFFFFFFFF);
2319 0 : SIVAL(pdata,6,0xFFFFFFFF);
2320 0 : break;
2321 0 : case SMB_ACL_OTHER:
2322 0 : SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2323 0 : SIVAL(pdata,2,0xFFFFFFFF);
2324 0 : SIVAL(pdata,6,0xFFFFFFFF);
2325 0 : break;
2326 0 : default:
2327 0 : DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2328 0 : return False;
2329 : }
2330 0 : pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2331 : }
2332 :
2333 0 : return True;
2334 : }
2335 : #endif
2336 :
2337 0 : static NTSTATUS smb_q_posix_acl(
2338 : struct connection_struct *conn,
2339 : struct smb_request *req,
2340 : struct smb_filename *smb_fname,
2341 : struct files_struct *fsp,
2342 : char **ppdata,
2343 : int *ptotal_data)
2344 : {
2345 : #if !defined(HAVE_POSIX_ACLS)
2346 : return NT_STATUS_INVALID_LEVEL;
2347 : #else
2348 0 : char *pdata = NULL;
2349 0 : SMB_ACL_T file_acl = NULL;
2350 0 : SMB_ACL_T def_acl = NULL;
2351 0 : uint16_t num_file_acls = 0;
2352 0 : uint16_t num_def_acls = 0;
2353 0 : unsigned int size_needed = 0;
2354 : NTSTATUS status;
2355 : bool ok;
2356 0 : bool close_fsp = false;
2357 :
2358 : /*
2359 : * Ensure we always operate on a file descriptor, not just
2360 : * the filename.
2361 : */
2362 0 : if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
2363 0 : uint32_t access_mask = SEC_STD_READ_CONTROL|
2364 : FILE_READ_ATTRIBUTES|
2365 : FILE_WRITE_ATTRIBUTES;
2366 :
2367 0 : status = get_posix_fsp(conn,
2368 : req,
2369 : smb_fname,
2370 : access_mask,
2371 : &fsp);
2372 :
2373 0 : if (!NT_STATUS_IS_OK(status)) {
2374 0 : goto out;
2375 : }
2376 0 : close_fsp = true;
2377 : }
2378 :
2379 0 : SMB_ASSERT(fsp != NULL);
2380 :
2381 0 : status = refuse_symlink_fsp(fsp);
2382 0 : if (!NT_STATUS_IS_OK(status)) {
2383 0 : goto out;
2384 : }
2385 :
2386 0 : file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, SMB_ACL_TYPE_ACCESS,
2387 : talloc_tos());
2388 :
2389 0 : if (file_acl == NULL && no_acl_syscall_error(errno)) {
2390 0 : DBG_INFO("ACLs not implemented on "
2391 : "filesystem containing %s\n",
2392 : fsp_str_dbg(fsp));
2393 0 : status = NT_STATUS_NOT_IMPLEMENTED;
2394 0 : goto out;
2395 : }
2396 :
2397 0 : if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2398 : /*
2399 : * We can only have default POSIX ACLs on
2400 : * directories.
2401 : */
2402 0 : if (!fsp->fsp_flags.is_directory) {
2403 0 : DBG_INFO("Non-directory open %s\n",
2404 : fsp_str_dbg(fsp));
2405 0 : status = NT_STATUS_INVALID_HANDLE;
2406 0 : goto out;
2407 : }
2408 0 : def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
2409 : SMB_ACL_TYPE_DEFAULT,
2410 : talloc_tos());
2411 0 : def_acl = free_empty_sys_acl(conn, def_acl);
2412 : }
2413 :
2414 0 : num_file_acls = count_acl_entries(conn, file_acl);
2415 0 : num_def_acls = count_acl_entries(conn, def_acl);
2416 :
2417 : /* Wrap checks. */
2418 : if (num_file_acls + num_def_acls < num_file_acls) {
2419 : status = NT_STATUS_INVALID_PARAMETER;
2420 : goto out;
2421 : }
2422 :
2423 0 : size_needed = num_file_acls + num_def_acls;
2424 :
2425 : /*
2426 : * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
2427 : * than UINT_MAX, so check by division.
2428 : */
2429 0 : if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
2430 0 : status = NT_STATUS_INVALID_PARAMETER;
2431 0 : goto out;
2432 : }
2433 :
2434 0 : size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
2435 0 : if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
2436 0 : status = NT_STATUS_INVALID_PARAMETER;
2437 0 : goto out;
2438 : }
2439 0 : size_needed += SMB_POSIX_ACL_HEADER_SIZE;
2440 :
2441 0 : *ppdata = SMB_REALLOC(*ppdata, size_needed);
2442 0 : if (*ppdata == NULL) {
2443 0 : status = NT_STATUS_NO_MEMORY;
2444 0 : goto out;
2445 : }
2446 0 : pdata = *ppdata;
2447 :
2448 0 : SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2449 0 : SSVAL(pdata,2,num_file_acls);
2450 0 : SSVAL(pdata,4,num_def_acls);
2451 0 : pdata += SMB_POSIX_ACL_HEADER_SIZE;
2452 :
2453 0 : ok = marshall_posix_acl(conn,
2454 : pdata,
2455 0 : &fsp->fsp_name->st,
2456 : file_acl);
2457 0 : if (!ok) {
2458 0 : status = NT_STATUS_INTERNAL_ERROR;
2459 0 : goto out;
2460 : }
2461 0 : pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
2462 :
2463 0 : ok = marshall_posix_acl(conn,
2464 : pdata,
2465 0 : &fsp->fsp_name->st,
2466 : def_acl);
2467 0 : if (!ok) {
2468 0 : status = NT_STATUS_INTERNAL_ERROR;
2469 0 : goto out;
2470 : }
2471 :
2472 0 : *ptotal_data = size_needed;
2473 0 : status = NT_STATUS_OK;
2474 :
2475 0 : out:
2476 :
2477 0 : if (close_fsp) {
2478 : /*
2479 : * Ensure the stat struct in smb_fname is up to
2480 : * date. Structure copy.
2481 : */
2482 0 : smb_fname->st = fsp->fsp_name->st;
2483 0 : (void)close_file_free(req, &fsp, NORMAL_CLOSE);
2484 : }
2485 :
2486 0 : TALLOC_FREE(file_acl);
2487 0 : TALLOC_FREE(def_acl);
2488 0 : return status;
2489 : #endif
2490 : }
2491 :
2492 0 : static NTSTATUS smb_q_posix_symlink(
2493 : struct connection_struct *conn,
2494 : struct smb_request *req,
2495 : struct smb_filename *smb_fname,
2496 : char **ppdata,
2497 : int *ptotal_data)
2498 : {
2499 : char buffer[PATH_MAX+1];
2500 : size_t needed, len;
2501 : int link_len;
2502 0 : char *pdata = NULL;
2503 0 : struct smb_filename *parent_fname = NULL;
2504 0 : struct smb_filename *base_name = NULL;
2505 : NTSTATUS status;
2506 :
2507 0 : DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
2508 : smb_fname_str_dbg(smb_fname));
2509 :
2510 0 : if (!S_ISLNK(smb_fname->st.st_ex_mode)) {
2511 0 : return NT_STATUS_DOS(ERRSRV, ERRbadlink);
2512 : }
2513 :
2514 0 : status = parent_pathref(
2515 : talloc_tos(),
2516 : conn->cwd_fsp,
2517 : smb_fname,
2518 : &parent_fname,
2519 : &base_name);
2520 :
2521 0 : if (!NT_STATUS_IS_OK(status)) {
2522 0 : DBG_DEBUG("parent_pathref failed: %s\n", nt_errstr(status));
2523 0 : return status;
2524 : }
2525 :
2526 0 : link_len = SMB_VFS_READLINKAT(
2527 : conn,
2528 : parent_fname->fsp,
2529 : base_name,
2530 : buffer,
2531 : sizeof(buffer)-1);
2532 0 : TALLOC_FREE(parent_fname);
2533 :
2534 0 : if (link_len == -1) {
2535 0 : status = map_nt_error_from_unix(errno);
2536 0 : DBG_DEBUG("READLINKAT failed: %s\n", nt_errstr(status));
2537 0 : return status;
2538 : }
2539 0 : if (link_len >= sizeof(buffer)) {
2540 0 : return NT_STATUS_INTERNAL_ERROR;
2541 : }
2542 0 : buffer[link_len] = 0;
2543 :
2544 0 : needed = (link_len+1)*2;
2545 :
2546 0 : *ppdata = SMB_REALLOC(*ppdata, needed);
2547 0 : if (*ppdata == NULL) {
2548 0 : return NT_STATUS_NO_MEMORY;
2549 : }
2550 0 : pdata = *ppdata;
2551 :
2552 0 : status = srvstr_push(
2553 : pdata,
2554 : req->flags2,
2555 : pdata,
2556 : buffer,
2557 : needed,
2558 : STR_TERMINATE,
2559 : &len);
2560 0 : if (!NT_STATUS_IS_OK(status)) {
2561 0 : return status;
2562 : }
2563 0 : *ptotal_data = len;
2564 :
2565 0 : return NT_STATUS_OK;
2566 : }
2567 :
2568 0 : static void call_trans2qpathinfo(
2569 : connection_struct *conn,
2570 : struct smb_request *req,
2571 : char **pparams,
2572 : int total_params,
2573 : char **ppdata,
2574 : int total_data,
2575 : unsigned int max_data_bytes)
2576 : {
2577 0 : char *params = *pparams;
2578 : uint16_t info_level;
2579 0 : struct smb_filename *smb_fname = NULL;
2580 0 : bool delete_pending = False;
2581 0 : struct timespec write_time_ts = { .tv_sec = 0, };
2582 0 : struct files_struct *dirfsp = NULL;
2583 0 : files_struct *fsp = NULL;
2584 : struct file_id fileid;
2585 : uint32_t name_hash;
2586 0 : char *fname = NULL;
2587 0 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2588 0 : NTTIME twrp = 0;
2589 : bool info_level_handled;
2590 0 : NTSTATUS status = NT_STATUS_OK;
2591 : int ret;
2592 :
2593 0 : if (!params) {
2594 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2595 0 : return;
2596 : }
2597 :
2598 :
2599 : /* qpathinfo */
2600 0 : if (total_params < 7) {
2601 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2602 0 : return;
2603 : }
2604 :
2605 0 : info_level = SVAL(params,0);
2606 :
2607 0 : DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level);
2608 :
2609 0 : if (INFO_LEVEL_IS_UNIX(info_level)) {
2610 0 : if (!lp_smb1_unix_extensions()) {
2611 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2612 0 : return;
2613 : }
2614 0 : if (!req->posix_pathnames) {
2615 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2616 0 : return;
2617 : }
2618 : }
2619 :
2620 0 : if (req->posix_pathnames) {
2621 0 : srvstr_get_path_posix(req,
2622 : params,
2623 0 : req->flags2,
2624 : &fname,
2625 0 : ¶ms[6],
2626 0 : total_params - 6,
2627 : STR_TERMINATE,
2628 : &status);
2629 : } else {
2630 0 : srvstr_get_path(req,
2631 : params,
2632 0 : req->flags2,
2633 : &fname,
2634 0 : ¶ms[6],
2635 0 : total_params - 6,
2636 : STR_TERMINATE,
2637 : &status);
2638 : }
2639 0 : if (!NT_STATUS_IS_OK(status)) {
2640 0 : reply_nterror(req, status);
2641 0 : return;
2642 : }
2643 :
2644 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
2645 0 : extract_snapshot_token(fname, &twrp);
2646 : }
2647 0 : status = filename_convert_dirfsp(req,
2648 : conn,
2649 : fname,
2650 : ucf_flags,
2651 : twrp,
2652 : &dirfsp,
2653 : &smb_fname);
2654 0 : if (!NT_STATUS_IS_OK(status)) {
2655 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2656 0 : reply_botherror(req,
2657 : NT_STATUS_PATH_NOT_COVERED,
2658 : ERRSRV, ERRbadpath);
2659 0 : return;
2660 : }
2661 0 : reply_nterror(req, status);
2662 0 : return;
2663 : }
2664 :
2665 : /*
2666 : * qpathinfo must operate on an existing file, so we
2667 : * can exit early if filename_convert_dirfsp() returned the
2668 : * "new file" NT_STATUS_OK, !VALID_STAT case.
2669 : */
2670 :
2671 0 : if (!VALID_STAT(smb_fname->st)) {
2672 0 : reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2673 0 : return;
2674 : }
2675 :
2676 : /*
2677 : * smb_fname->fsp may be NULL if smb_fname points at a symlink
2678 : * and we're in POSIX context, so be careful when using fsp
2679 : * below, it can still be NULL.
2680 : */
2681 0 : fsp = smb_fname->fsp;
2682 :
2683 : /* If this is a stream, check if there is a delete_pending. */
2684 0 : if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
2685 0 : && is_ntfs_stream_smb_fname(smb_fname)) {
2686 : struct smb_filename *smb_fname_base;
2687 :
2688 : /* Create an smb_filename with stream_name == NULL. */
2689 0 : smb_fname_base = synthetic_smb_fname(
2690 : talloc_tos(),
2691 0 : smb_fname->base_name,
2692 : NULL,
2693 : NULL,
2694 0 : smb_fname->twrp,
2695 0 : smb_fname->flags);
2696 0 : if (smb_fname_base == NULL) {
2697 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2698 0 : return;
2699 : }
2700 :
2701 0 : ret = vfs_stat(conn, smb_fname_base);
2702 0 : if (ret != 0) {
2703 0 : DBG_NOTICE("vfs_stat of %s failed "
2704 : "(%s)\n",
2705 : smb_fname_str_dbg(smb_fname_base),
2706 : strerror(errno));
2707 0 : TALLOC_FREE(smb_fname_base);
2708 0 : reply_nterror(req,
2709 : map_nt_error_from_unix(errno));
2710 0 : return;
2711 : }
2712 :
2713 0 : status = file_name_hash(conn,
2714 : smb_fname_str_dbg(smb_fname_base),
2715 : &name_hash);
2716 0 : if (!NT_STATUS_IS_OK(status)) {
2717 0 : TALLOC_FREE(smb_fname_base);
2718 0 : reply_nterror(req, status);
2719 0 : return;
2720 : }
2721 :
2722 0 : fileid = vfs_file_id_from_sbuf(conn,
2723 0 : &smb_fname_base->st);
2724 0 : TALLOC_FREE(smb_fname_base);
2725 0 : get_file_infos(fileid, name_hash, &delete_pending, NULL);
2726 0 : if (delete_pending) {
2727 0 : reply_nterror(req, NT_STATUS_DELETE_PENDING);
2728 0 : return;
2729 : }
2730 : }
2731 :
2732 0 : status = file_name_hash(conn,
2733 : smb_fname_str_dbg(smb_fname),
2734 : &name_hash);
2735 0 : if (!NT_STATUS_IS_OK(status)) {
2736 0 : reply_nterror(req, status);
2737 0 : return;
2738 : }
2739 :
2740 0 : if (fsp_getinfo_ask_sharemode(fsp)) {
2741 0 : fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2742 0 : get_file_infos(fileid, name_hash, &delete_pending,
2743 : &write_time_ts);
2744 : }
2745 :
2746 0 : if (delete_pending) {
2747 0 : reply_nterror(req, NT_STATUS_DELETE_PENDING);
2748 0 : return;
2749 : }
2750 :
2751 0 : info_level_handled = true; /* Untouched in switch cases below */
2752 :
2753 0 : switch (info_level) {
2754 :
2755 0 : default:
2756 0 : info_level_handled = false;
2757 0 : break;
2758 :
2759 0 : case SMB_QUERY_FILE_UNIX_BASIC:
2760 0 : status = smb_q_unix_basic(
2761 : conn,
2762 : req,
2763 : smb_fname,
2764 0 : smb_fname->fsp,
2765 : ppdata,
2766 : &total_data);
2767 0 : break;
2768 :
2769 0 : case SMB_QUERY_FILE_UNIX_INFO2:
2770 0 : status = smb_q_unix_info2(
2771 : conn,
2772 : req,
2773 : smb_fname,
2774 0 : smb_fname->fsp,
2775 : ppdata,
2776 : &total_data);
2777 0 : break;
2778 :
2779 0 : case SMB_QUERY_POSIX_ACL:
2780 0 : status = smb_q_posix_acl(
2781 : conn,
2782 : req,
2783 : smb_fname,
2784 0 : smb_fname->fsp,
2785 : ppdata,
2786 : &total_data);
2787 0 : break;
2788 :
2789 0 : case SMB_QUERY_FILE_UNIX_LINK:
2790 0 : status = smb_q_posix_symlink(
2791 : conn,
2792 : req,
2793 : smb_fname,
2794 : ppdata,
2795 : &total_data);
2796 0 : break;
2797 : }
2798 :
2799 0 : if (info_level_handled) {
2800 0 : handle_trans2qfilepathinfo_result(
2801 : conn,
2802 : req,
2803 : info_level,
2804 : status,
2805 : *ppdata,
2806 : total_data,
2807 : total_data,
2808 : max_data_bytes);
2809 0 : return;
2810 : }
2811 :
2812 0 : call_trans2qfilepathinfo(
2813 : conn,
2814 : req,
2815 : TRANSACT2_QPATHINFO,
2816 : info_level,
2817 : smb_fname,
2818 : fsp,
2819 : false,
2820 : write_time_ts,
2821 : pparams,
2822 : total_params,
2823 : ppdata,
2824 : total_data,
2825 : max_data_bytes);
2826 : }
2827 :
2828 0 : static NTSTATUS smb_q_posix_lock(
2829 : struct connection_struct *conn,
2830 : struct smb_request *req,
2831 : struct files_struct *fsp,
2832 : char **ppdata,
2833 : int *ptotal_data)
2834 : {
2835 0 : char *pdata = *ppdata;
2836 0 : int total_data = *ptotal_data;
2837 : uint64_t count;
2838 : uint64_t offset;
2839 : uint64_t smblctx;
2840 : enum brl_type lock_type;
2841 : NTSTATUS status;
2842 :
2843 0 : if (fsp->fsp_flags.is_pathref || (fsp_get_io_fd(fsp) == -1)) {
2844 0 : return NT_STATUS_INVALID_HANDLE;
2845 : }
2846 :
2847 0 : if (total_data != POSIX_LOCK_DATA_SIZE) {
2848 0 : return NT_STATUS_INVALID_PARAMETER;
2849 : }
2850 :
2851 0 : switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
2852 0 : case POSIX_LOCK_TYPE_READ:
2853 0 : lock_type = READ_LOCK;
2854 0 : break;
2855 0 : case POSIX_LOCK_TYPE_WRITE:
2856 0 : lock_type = WRITE_LOCK;
2857 0 : break;
2858 0 : case POSIX_LOCK_TYPE_UNLOCK:
2859 : default:
2860 : /* There's no point in asking for an unlock... */
2861 0 : return NT_STATUS_INVALID_PARAMETER;
2862 : }
2863 :
2864 0 : smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
2865 0 : offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
2866 0 : count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
2867 :
2868 0 : status = query_lock(
2869 : fsp,
2870 : &smblctx,
2871 : &count,
2872 : &offset,
2873 : &lock_type,
2874 : POSIX_LOCK);
2875 :
2876 0 : if (NT_STATUS_IS_OK(status)) {
2877 : /*
2878 : * For success we just return a copy of what we sent
2879 : * with the lock type set to POSIX_LOCK_TYPE_UNLOCK.
2880 : */
2881 0 : SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
2882 0 : return NT_STATUS_OK;
2883 : }
2884 :
2885 0 : if (!ERROR_WAS_LOCK_DENIED(status)) {
2886 0 : DBG_DEBUG("query_lock() failed: %s\n", nt_errstr(status));
2887 0 : return status;
2888 : }
2889 :
2890 : /*
2891 : * Here we need to report who has it locked.
2892 : */
2893 :
2894 0 : SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
2895 0 : SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
2896 0 : SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
2897 0 : SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
2898 0 : SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
2899 :
2900 0 : return NT_STATUS_OK;
2901 : }
2902 :
2903 0 : static void call_trans2qfileinfo(
2904 : connection_struct *conn,
2905 : struct smb_request *req,
2906 : char **pparams,
2907 : int total_params,
2908 : char **ppdata,
2909 : int total_data,
2910 : unsigned int max_data_bytes)
2911 : {
2912 0 : char *params = *pparams;
2913 : uint16_t info_level;
2914 0 : struct smb_filename *smb_fname = NULL;
2915 0 : bool delete_pending = False;
2916 0 : struct timespec write_time_ts = { .tv_sec = 0, };
2917 0 : files_struct *fsp = NULL;
2918 : struct file_id fileid;
2919 : bool info_level_handled;
2920 0 : NTSTATUS status = NT_STATUS_OK;
2921 : int ret;
2922 :
2923 0 : if (params == NULL) {
2924 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2925 0 : return;
2926 : }
2927 :
2928 0 : if (total_params < 4) {
2929 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2930 0 : return;
2931 : }
2932 :
2933 0 : fsp = file_fsp(req, SVAL(params,0));
2934 0 : info_level = SVAL(params,2);
2935 :
2936 0 : if (IS_IPC(conn)) {
2937 0 : call_trans2qpipeinfo(
2938 : conn,
2939 : req,
2940 : fsp,
2941 : info_level,
2942 : TRANSACT2_QFILEINFO,
2943 : pparams,
2944 : total_params,
2945 : ppdata,
2946 : total_data,
2947 : max_data_bytes);
2948 0 : return;
2949 : }
2950 :
2951 0 : DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level);
2952 :
2953 0 : if (INFO_LEVEL_IS_UNIX(info_level)) {
2954 0 : if (!lp_smb1_unix_extensions()) {
2955 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2956 0 : return;
2957 : }
2958 0 : if (!req->posix_pathnames) {
2959 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2960 0 : return;
2961 : }
2962 : }
2963 :
2964 : /* Initial check for valid fsp ptr. */
2965 0 : if (!check_fsp_open(conn, req, fsp)) {
2966 0 : return;
2967 : }
2968 :
2969 0 : smb_fname = fsp->fsp_name;
2970 :
2971 0 : if(fsp->fake_file_handle) {
2972 : /*
2973 : * This is actually for the QUOTA_FAKE_FILE --metze
2974 : */
2975 :
2976 : /* We know this name is ok, it's already passed the checks. */
2977 :
2978 0 : } else if(fsp_get_pathref_fd(fsp) == -1) {
2979 : /*
2980 : * This is actually a QFILEINFO on a directory
2981 : * handle (returned from an NT SMB). NT5.0 seems
2982 : * to do this call. JRA.
2983 : */
2984 0 : ret = vfs_stat(conn, smb_fname);
2985 0 : if (ret != 0) {
2986 0 : DBG_NOTICE("vfs_stat of %s failed (%s)\n",
2987 : smb_fname_str_dbg(smb_fname),
2988 : strerror(errno));
2989 0 : reply_nterror(req,
2990 : map_nt_error_from_unix(errno));
2991 0 : return;
2992 : }
2993 :
2994 0 : if (fsp_getinfo_ask_sharemode(fsp)) {
2995 0 : fileid = vfs_file_id_from_sbuf(
2996 0 : conn, &smb_fname->st);
2997 0 : get_file_infos(fileid, fsp->name_hash,
2998 : &delete_pending,
2999 : &write_time_ts);
3000 : }
3001 : } else {
3002 : /*
3003 : * Original code - this is an open file.
3004 : */
3005 0 : status = vfs_stat_fsp(fsp);
3006 0 : if (!NT_STATUS_IS_OK(status)) {
3007 0 : DEBUG(3, ("fstat of %s failed (%s)\n",
3008 : fsp_fnum_dbg(fsp), nt_errstr(status)));
3009 0 : reply_nterror(req, status);
3010 0 : return;
3011 : }
3012 0 : if (fsp_getinfo_ask_sharemode(fsp)) {
3013 0 : fileid = vfs_file_id_from_sbuf(
3014 0 : conn, &smb_fname->st);
3015 0 : get_file_infos(fileid, fsp->name_hash,
3016 : &delete_pending,
3017 : &write_time_ts);
3018 : }
3019 : }
3020 :
3021 0 : info_level_handled = true; /* Untouched in switch cases below */
3022 :
3023 0 : switch (info_level) {
3024 :
3025 0 : default:
3026 0 : info_level_handled = false;
3027 0 : break;
3028 :
3029 0 : case SMB_QUERY_POSIX_LOCK:
3030 0 : status = smb_q_posix_lock(conn, req, fsp, ppdata, &total_data);
3031 0 : break;
3032 :
3033 0 : case SMB_QUERY_FILE_UNIX_BASIC:
3034 0 : status = smb_q_unix_basic(
3035 : conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3036 0 : break;
3037 :
3038 0 : case SMB_QUERY_FILE_UNIX_INFO2:
3039 0 : status = smb_q_unix_info2(
3040 : conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3041 0 : break;
3042 :
3043 0 : case SMB_QUERY_POSIX_ACL:
3044 0 : status = smb_q_posix_acl(
3045 : conn, req, fsp->fsp_name, fsp, ppdata, &total_data);
3046 0 : break;
3047 : }
3048 :
3049 0 : if (info_level_handled) {
3050 0 : handle_trans2qfilepathinfo_result(
3051 : conn,
3052 : req,
3053 : info_level,
3054 : status,
3055 : *ppdata,
3056 : total_data,
3057 : total_data,
3058 : max_data_bytes);
3059 0 : return;
3060 : }
3061 :
3062 0 : call_trans2qfilepathinfo(
3063 : conn,
3064 : req,
3065 : TRANSACT2_QFILEINFO,
3066 : info_level,
3067 : smb_fname,
3068 : fsp,
3069 : delete_pending,
3070 : write_time_ts,
3071 : pparams,
3072 : total_params,
3073 : ppdata,
3074 : total_data,
3075 : max_data_bytes);
3076 : }
3077 :
3078 0 : static void handle_trans2setfilepathinfo_result(
3079 : connection_struct *conn,
3080 : struct smb_request *req,
3081 : uint16_t info_level,
3082 : NTSTATUS status,
3083 : char *pdata,
3084 : int data_return_size,
3085 : unsigned int max_data_bytes)
3086 : {
3087 0 : char params[2] = { 0, 0, };
3088 :
3089 0 : if (NT_STATUS_IS_OK(status)) {
3090 0 : send_trans2_replies(
3091 : conn,
3092 : req,
3093 0 : NT_STATUS_OK,
3094 : params,
3095 : 2,
3096 : pdata,
3097 : data_return_size,
3098 : max_data_bytes);
3099 0 : return;
3100 : }
3101 :
3102 0 : if (open_was_deferred(req->xconn, req->mid)) {
3103 : /* We have re-scheduled this call. */
3104 0 : return;
3105 : }
3106 :
3107 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3108 0 : bool ok = defer_smb1_sharing_violation(req);
3109 0 : if (ok) {
3110 0 : return;
3111 : }
3112 : }
3113 :
3114 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
3115 : /* We have re-scheduled this call. */
3116 0 : return;
3117 : }
3118 :
3119 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3120 0 : reply_botherror(
3121 : req,
3122 : NT_STATUS_PATH_NOT_COVERED,
3123 : ERRSRV,
3124 : ERRbadpath);
3125 0 : return;
3126 : }
3127 :
3128 0 : if (info_level == SMB_POSIX_PATH_OPEN) {
3129 0 : reply_openerror(req, status);
3130 0 : return;
3131 : }
3132 :
3133 0 : if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
3134 : /*
3135 : * Invalid EA name needs to return 2 param bytes,
3136 : * not a zero-length error packet.
3137 : */
3138 :
3139 0 : send_trans2_replies(
3140 : conn,
3141 : req,
3142 : status,
3143 : params,
3144 : 2,
3145 : NULL,
3146 : 0,
3147 : max_data_bytes);
3148 0 : return;
3149 : }
3150 :
3151 0 : reply_nterror(req, status);
3152 : }
3153 :
3154 : /****************************************************************************
3155 : Create a directory with POSIX semantics.
3156 : ****************************************************************************/
3157 :
3158 0 : static NTSTATUS smb_posix_mkdir(connection_struct *conn,
3159 : struct smb_request *req,
3160 : char **ppdata,
3161 : int total_data,
3162 : struct smb_filename *smb_fname,
3163 : int *pdata_return_size)
3164 : {
3165 0 : NTSTATUS status = NT_STATUS_OK;
3166 0 : uint32_t raw_unixmode = 0;
3167 0 : mode_t unixmode = (mode_t)0;
3168 0 : files_struct *fsp = NULL;
3169 0 : uint16_t info_level_return = 0;
3170 : int info;
3171 0 : char *pdata = *ppdata;
3172 0 : struct smb2_create_blobs *posx = NULL;
3173 :
3174 0 : if (total_data < 18) {
3175 0 : return NT_STATUS_INVALID_PARAMETER;
3176 : }
3177 :
3178 0 : raw_unixmode = IVAL(pdata,8);
3179 : /* Next 4 bytes are not yet defined. */
3180 :
3181 0 : status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3182 : PERM_NEW_DIR, &unixmode);
3183 0 : if (!NT_STATUS_IS_OK(status)) {
3184 0 : return status;
3185 : }
3186 :
3187 0 : status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3188 0 : if (!NT_STATUS_IS_OK(status)) {
3189 0 : DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3190 : nt_errstr(status));
3191 0 : return status;
3192 : }
3193 :
3194 0 : DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
3195 : smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
3196 :
3197 0 : status = SMB_VFS_CREATE_FILE(
3198 : conn, /* conn */
3199 : req, /* req */
3200 : NULL, /* dirfsp */
3201 : smb_fname, /* fname */
3202 : FILE_READ_ATTRIBUTES, /* access_mask */
3203 : FILE_SHARE_NONE, /* share_access */
3204 : FILE_CREATE, /* create_disposition*/
3205 : FILE_DIRECTORY_FILE, /* create_options */
3206 : 0, /* file_attributes */
3207 : 0, /* oplock_request */
3208 : NULL, /* lease */
3209 : 0, /* allocation_size */
3210 : 0, /* private_flags */
3211 : NULL, /* sd */
3212 : NULL, /* ea_list */
3213 : &fsp, /* result */
3214 : &info, /* pinfo */
3215 : posx, /* in_context_blobs */
3216 : NULL); /* out_context_blobs */
3217 :
3218 0 : TALLOC_FREE(posx);
3219 :
3220 0 : if (NT_STATUS_IS_OK(status)) {
3221 0 : close_file_free(req, &fsp, NORMAL_CLOSE);
3222 : }
3223 :
3224 0 : info_level_return = SVAL(pdata,16);
3225 :
3226 0 : if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3227 0 : *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3228 0 : } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3229 0 : *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3230 : } else {
3231 0 : *pdata_return_size = 12;
3232 : }
3233 :
3234 : /* Realloc the data size */
3235 0 : *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3236 0 : if (*ppdata == NULL) {
3237 0 : *pdata_return_size = 0;
3238 0 : return NT_STATUS_NO_MEMORY;
3239 : }
3240 0 : pdata = *ppdata;
3241 :
3242 0 : SSVAL(pdata,0,NO_OPLOCK_RETURN);
3243 0 : SSVAL(pdata,2,0); /* No fnum. */
3244 0 : SIVAL(pdata,4,info); /* Was directory created. */
3245 :
3246 0 : switch (info_level_return) {
3247 0 : case SMB_QUERY_FILE_UNIX_BASIC:
3248 0 : SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3249 0 : SSVAL(pdata,10,0); /* Padding. */
3250 0 : store_file_unix_basic(conn, pdata + 12, fsp,
3251 0 : &smb_fname->st);
3252 0 : break;
3253 0 : case SMB_QUERY_FILE_UNIX_INFO2:
3254 0 : SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3255 0 : SSVAL(pdata,10,0); /* Padding. */
3256 0 : store_file_unix_basic_info2(conn, pdata + 12, fsp,
3257 0 : &smb_fname->st);
3258 0 : break;
3259 0 : default:
3260 0 : SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3261 0 : SSVAL(pdata,10,0); /* Padding. */
3262 0 : break;
3263 : }
3264 :
3265 0 : return status;
3266 : }
3267 :
3268 : /****************************************************************************
3269 : Open/Create a file with POSIX semantics.
3270 : ****************************************************************************/
3271 :
3272 : #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
3273 : #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
3274 :
3275 0 : static NTSTATUS smb_posix_open(connection_struct *conn,
3276 : struct smb_request *req,
3277 : char **ppdata,
3278 : int total_data,
3279 : struct smb_filename *smb_fname,
3280 : int *pdata_return_size)
3281 : {
3282 0 : bool extended_oplock_granted = False;
3283 0 : char *pdata = *ppdata;
3284 0 : uint32_t flags = 0;
3285 0 : uint32_t wire_open_mode = 0;
3286 0 : uint32_t raw_unixmode = 0;
3287 0 : uint32_t attributes = 0;
3288 0 : uint32_t create_disp = 0;
3289 0 : uint32_t access_mask = 0;
3290 0 : uint32_t create_options = FILE_NON_DIRECTORY_FILE;
3291 0 : NTSTATUS status = NT_STATUS_OK;
3292 0 : mode_t unixmode = (mode_t)0;
3293 0 : files_struct *fsp = NULL;
3294 0 : int oplock_request = 0;
3295 0 : int info = 0;
3296 0 : uint16_t info_level_return = 0;
3297 0 : struct smb2_create_blobs *posx = NULL;
3298 :
3299 0 : if (total_data < 18) {
3300 0 : return NT_STATUS_INVALID_PARAMETER;
3301 : }
3302 :
3303 0 : flags = IVAL(pdata,0);
3304 0 : oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
3305 0 : if (oplock_request) {
3306 0 : oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
3307 : }
3308 :
3309 0 : wire_open_mode = IVAL(pdata,4);
3310 :
3311 0 : if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
3312 0 : return smb_posix_mkdir(conn, req,
3313 : ppdata,
3314 : total_data,
3315 : smb_fname,
3316 : pdata_return_size);
3317 : }
3318 :
3319 0 : switch (wire_open_mode & SMB_ACCMODE) {
3320 0 : case SMB_O_RDONLY:
3321 0 : access_mask = SMB_O_RDONLY_MAPPING;
3322 0 : break;
3323 0 : case SMB_O_WRONLY:
3324 0 : access_mask = SMB_O_WRONLY_MAPPING;
3325 0 : break;
3326 0 : case SMB_O_RDWR:
3327 0 : access_mask = (SMB_O_RDONLY_MAPPING|
3328 : SMB_O_WRONLY_MAPPING);
3329 0 : break;
3330 0 : default:
3331 0 : DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
3332 : (unsigned int)wire_open_mode ));
3333 0 : return NT_STATUS_INVALID_PARAMETER;
3334 : }
3335 :
3336 0 : wire_open_mode &= ~SMB_ACCMODE;
3337 :
3338 : /* First take care of O_CREAT|O_EXCL interactions. */
3339 0 : switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
3340 0 : case (SMB_O_CREAT | SMB_O_EXCL):
3341 : /* File exists fail. File not exist create. */
3342 0 : create_disp = FILE_CREATE;
3343 0 : break;
3344 0 : case SMB_O_CREAT:
3345 : /* File exists open. File not exist create. */
3346 0 : create_disp = FILE_OPEN_IF;
3347 0 : break;
3348 0 : case SMB_O_EXCL:
3349 : /* O_EXCL on its own without O_CREAT is undefined.
3350 : We deliberately ignore it as some versions of
3351 : Linux CIFSFS can send a bare O_EXCL on the
3352 : wire which other filesystems in the kernel
3353 : ignore. See bug 9519 for details. */
3354 :
3355 : /* Fallthrough. */
3356 :
3357 : case 0:
3358 : /* File exists open. File not exist fail. */
3359 0 : create_disp = FILE_OPEN;
3360 0 : break;
3361 0 : default:
3362 0 : DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
3363 : (unsigned int)wire_open_mode ));
3364 0 : return NT_STATUS_INVALID_PARAMETER;
3365 : }
3366 :
3367 : /* Next factor in the effects of O_TRUNC. */
3368 0 : wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
3369 :
3370 0 : if (wire_open_mode & SMB_O_TRUNC) {
3371 0 : switch (create_disp) {
3372 0 : case FILE_CREATE:
3373 : /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
3374 : /* Leave create_disp alone as
3375 : (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
3376 : */
3377 : /* File exists fail. File not exist create. */
3378 0 : break;
3379 0 : case FILE_OPEN_IF:
3380 : /* SMB_O_CREAT | SMB_O_TRUNC */
3381 : /* File exists overwrite. File not exist create. */
3382 0 : create_disp = FILE_OVERWRITE_IF;
3383 0 : break;
3384 0 : case FILE_OPEN:
3385 : /* SMB_O_TRUNC */
3386 : /* File exists overwrite. File not exist fail. */
3387 0 : create_disp = FILE_OVERWRITE;
3388 0 : break;
3389 0 : default:
3390 : /* Cannot get here. */
3391 0 : smb_panic("smb_posix_open: logic error");
3392 : return NT_STATUS_INVALID_PARAMETER;
3393 : }
3394 : }
3395 :
3396 0 : raw_unixmode = IVAL(pdata,8);
3397 : /* Next 4 bytes are not yet defined. */
3398 :
3399 0 : status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3400 0 : (VALID_STAT(smb_fname->st) ?
3401 : PERM_EXISTING_FILE : PERM_NEW_FILE),
3402 : &unixmode);
3403 :
3404 0 : if (!NT_STATUS_IS_OK(status)) {
3405 0 : return status;
3406 : }
3407 :
3408 0 : status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
3409 0 : if (!NT_STATUS_IS_OK(status)) {
3410 0 : DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3411 : nt_errstr(status));
3412 0 : return status;
3413 : }
3414 :
3415 0 : if (wire_open_mode & SMB_O_SYNC) {
3416 0 : create_options |= FILE_WRITE_THROUGH;
3417 : }
3418 0 : if (wire_open_mode & SMB_O_APPEND) {
3419 0 : access_mask |= FILE_APPEND_DATA;
3420 : }
3421 0 : if (wire_open_mode & SMB_O_DIRECT) {
3422 0 : attributes |= FILE_FLAG_NO_BUFFERING;
3423 : }
3424 :
3425 0 : if ((wire_open_mode & SMB_O_DIRECTORY) ||
3426 0 : VALID_STAT_OF_DIR(smb_fname->st)) {
3427 0 : if (access_mask != SMB_O_RDONLY_MAPPING) {
3428 0 : return NT_STATUS_FILE_IS_A_DIRECTORY;
3429 : }
3430 0 : create_options &= ~FILE_NON_DIRECTORY_FILE;
3431 0 : create_options |= FILE_DIRECTORY_FILE;
3432 : }
3433 :
3434 0 : DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
3435 : smb_fname_str_dbg(smb_fname),
3436 : (unsigned int)wire_open_mode,
3437 : (unsigned int)unixmode ));
3438 :
3439 0 : status = SMB_VFS_CREATE_FILE(
3440 : conn, /* conn */
3441 : req, /* req */
3442 : NULL, /* dirfsp */
3443 : smb_fname, /* fname */
3444 : access_mask, /* access_mask */
3445 : (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3446 : FILE_SHARE_DELETE),
3447 : create_disp, /* create_disposition*/
3448 : create_options, /* create_options */
3449 : attributes, /* file_attributes */
3450 : oplock_request, /* oplock_request */
3451 : NULL, /* lease */
3452 : 0, /* allocation_size */
3453 : 0, /* private_flags */
3454 : NULL, /* sd */
3455 : NULL, /* ea_list */
3456 : &fsp, /* result */
3457 : &info, /* pinfo */
3458 : posx, /* in_context_blobs */
3459 : NULL); /* out_context_blobs */
3460 :
3461 0 : TALLOC_FREE(posx);
3462 :
3463 0 : if (!NT_STATUS_IS_OK(status)) {
3464 0 : return status;
3465 : }
3466 :
3467 0 : if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3468 0 : extended_oplock_granted = True;
3469 : }
3470 :
3471 0 : if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3472 0 : extended_oplock_granted = True;
3473 : }
3474 :
3475 0 : info_level_return = SVAL(pdata,16);
3476 :
3477 : /* Allocate the correct return size. */
3478 :
3479 0 : if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
3480 0 : *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
3481 0 : } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
3482 0 : *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
3483 : } else {
3484 0 : *pdata_return_size = 12;
3485 : }
3486 :
3487 : /* Realloc the data size */
3488 0 : *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
3489 0 : if (*ppdata == NULL) {
3490 0 : close_file_free(req, &fsp, ERROR_CLOSE);
3491 0 : *pdata_return_size = 0;
3492 0 : return NT_STATUS_NO_MEMORY;
3493 : }
3494 0 : pdata = *ppdata;
3495 :
3496 0 : if (extended_oplock_granted) {
3497 0 : if (flags & REQUEST_BATCH_OPLOCK) {
3498 0 : SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
3499 : } else {
3500 0 : SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
3501 : }
3502 0 : } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
3503 0 : SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
3504 : } else {
3505 0 : SSVAL(pdata,0,NO_OPLOCK_RETURN);
3506 : }
3507 :
3508 0 : SSVAL(pdata,2,fsp->fnum);
3509 0 : SIVAL(pdata,4,info); /* Was file created etc. */
3510 :
3511 0 : switch (info_level_return) {
3512 0 : case SMB_QUERY_FILE_UNIX_BASIC:
3513 0 : SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
3514 0 : SSVAL(pdata,10,0); /* padding. */
3515 0 : store_file_unix_basic(conn, pdata + 12, fsp,
3516 0 : &smb_fname->st);
3517 0 : break;
3518 0 : case SMB_QUERY_FILE_UNIX_INFO2:
3519 0 : SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
3520 0 : SSVAL(pdata,10,0); /* padding. */
3521 0 : store_file_unix_basic_info2(conn, pdata + 12, fsp,
3522 0 : &smb_fname->st);
3523 0 : break;
3524 0 : default:
3525 0 : SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
3526 0 : SSVAL(pdata,10,0); /* padding. */
3527 0 : break;
3528 : }
3529 0 : return NT_STATUS_OK;
3530 : }
3531 :
3532 : /****************************************************************************
3533 : Delete a file with POSIX semantics.
3534 : ****************************************************************************/
3535 :
3536 : struct smb_posix_unlink_state {
3537 : struct smb_filename *smb_fname;
3538 : struct files_struct *fsp;
3539 : NTSTATUS status;
3540 : };
3541 :
3542 0 : static void smb_posix_unlink_locked(struct share_mode_lock *lck,
3543 : void *private_data)
3544 : {
3545 0 : struct smb_posix_unlink_state *state = private_data;
3546 0 : char del = 1;
3547 : bool other_nonposix_opens;
3548 :
3549 0 : other_nonposix_opens = has_other_nonposix_opens(lck, state->fsp);
3550 0 : if (other_nonposix_opens) {
3551 : /* Fail with sharing violation. */
3552 0 : state->status = NT_STATUS_SHARING_VIOLATION;
3553 0 : return;
3554 : }
3555 :
3556 : /*
3557 : * Set the delete on close.
3558 : */
3559 0 : state->status = smb_set_file_disposition_info(state->fsp->conn,
3560 : &del,
3561 : 1,
3562 0 : state->fsp,
3563 : state->smb_fname);
3564 : }
3565 :
3566 0 : static NTSTATUS smb_posix_unlink(connection_struct *conn,
3567 : struct smb_request *req,
3568 : const char *pdata,
3569 : int total_data,
3570 : struct smb_filename *smb_fname)
3571 : {
3572 0 : struct smb_posix_unlink_state state = {};
3573 0 : NTSTATUS status = NT_STATUS_OK;
3574 0 : files_struct *fsp = NULL;
3575 0 : uint16_t flags = 0;
3576 0 : int info = 0;
3577 0 : int create_options = 0;
3578 0 : struct smb2_create_blobs *posx = NULL;
3579 :
3580 0 : if (!CAN_WRITE(conn)) {
3581 0 : return NT_STATUS_DOS(ERRSRV, ERRaccess);
3582 : }
3583 :
3584 0 : if (total_data < 2) {
3585 0 : return NT_STATUS_INVALID_PARAMETER;
3586 : }
3587 :
3588 0 : flags = SVAL(pdata,0);
3589 :
3590 0 : if (!VALID_STAT(smb_fname->st)) {
3591 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3592 : }
3593 :
3594 0 : if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
3595 0 : !VALID_STAT_OF_DIR(smb_fname->st)) {
3596 0 : return NT_STATUS_NOT_A_DIRECTORY;
3597 : }
3598 :
3599 0 : DEBUG(10,("smb_posix_unlink: %s %s\n",
3600 : (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
3601 : smb_fname_str_dbg(smb_fname)));
3602 :
3603 0 : if (S_ISDIR(smb_fname->st.st_ex_mode)) {
3604 0 : create_options |= FILE_DIRECTORY_FILE;
3605 : }
3606 :
3607 0 : status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
3608 0 : if (!NT_STATUS_IS_OK(status)) {
3609 0 : DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3610 : nt_errstr(status));
3611 0 : return status;
3612 : }
3613 :
3614 0 : status = SMB_VFS_CREATE_FILE(
3615 : conn, /* conn */
3616 : req, /* req */
3617 : NULL, /* dirfsp */
3618 : smb_fname, /* fname */
3619 : DELETE_ACCESS, /* access_mask */
3620 : (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
3621 : FILE_SHARE_DELETE),
3622 : FILE_OPEN, /* create_disposition*/
3623 : create_options, /* create_options */
3624 : 0, /* file_attributes */
3625 : 0, /* oplock_request */
3626 : NULL, /* lease */
3627 : 0, /* allocation_size */
3628 : 0, /* private_flags */
3629 : NULL, /* sd */
3630 : NULL, /* ea_list */
3631 : &fsp, /* result */
3632 : &info, /* pinfo */
3633 : posx, /* in_context_blobs */
3634 : NULL); /* out_context_blobs */
3635 :
3636 0 : TALLOC_FREE(posx);
3637 :
3638 0 : if (!NT_STATUS_IS_OK(status)) {
3639 0 : return status;
3640 : }
3641 :
3642 : /*
3643 : * Don't lie to client. If we can't really delete due to
3644 : * non-POSIX opens return SHARING_VIOLATION.
3645 : */
3646 :
3647 0 : state = (struct smb_posix_unlink_state) {
3648 : .smb_fname = smb_fname,
3649 : .fsp = fsp,
3650 : };
3651 :
3652 0 : status = share_mode_do_locked_vfs_allowed(fsp->file_id,
3653 : smb_posix_unlink_locked,
3654 : &state);
3655 0 : if (!NT_STATUS_IS_OK(status)) {
3656 0 : DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
3657 : fsp_str_dbg(fsp), nt_errstr(status));
3658 0 : close_file_free(req, &fsp, NORMAL_CLOSE);
3659 0 : return NT_STATUS_INVALID_PARAMETER;
3660 : }
3661 :
3662 0 : status = state.status;
3663 0 : if (!NT_STATUS_IS_OK(status)) {
3664 0 : close_file_free(req, &fsp, NORMAL_CLOSE);
3665 0 : return status;
3666 : }
3667 0 : return close_file_free(req, &fsp, NORMAL_CLOSE);
3668 : }
3669 :
3670 : /****************************************************************************
3671 : Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3672 : ****************************************************************************/
3673 :
3674 0 : static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
3675 : struct smb_request *req,
3676 : const char *pdata,
3677 : int total_data,
3678 : struct smb_filename *new_smb_fname)
3679 : {
3680 0 : char *link_target = NULL;
3681 : struct smb_filename target_fname;
3682 0 : TALLOC_CTX *ctx = talloc_tos();
3683 : NTSTATUS status;
3684 : int ret;
3685 0 : struct smb_filename *parent_fname = NULL;
3686 0 : struct smb_filename *base_name = NULL;
3687 :
3688 0 : if (!CAN_WRITE(conn)) {
3689 0 : return NT_STATUS_DOS(ERRSRV, ERRaccess);
3690 : }
3691 :
3692 : /* Set a symbolic link. */
3693 : /* Don't allow this if follow links is false. */
3694 :
3695 0 : if (total_data == 0) {
3696 0 : return NT_STATUS_INVALID_PARAMETER;
3697 : }
3698 :
3699 0 : if (!lp_follow_symlinks(SNUM(conn))) {
3700 0 : return NT_STATUS_ACCESS_DENIED;
3701 : }
3702 :
3703 0 : srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
3704 : total_data, STR_TERMINATE);
3705 :
3706 0 : if (!link_target) {
3707 0 : return NT_STATUS_INVALID_PARAMETER;
3708 : }
3709 :
3710 0 : target_fname = (struct smb_filename) {
3711 : .base_name = link_target,
3712 : };
3713 :
3714 : /* Removes @GMT tokens if any */
3715 0 : status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
3716 0 : if (!NT_STATUS_IS_OK(status)) {
3717 0 : return status;
3718 : }
3719 :
3720 0 : DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3721 : new_smb_fname->base_name, link_target ));
3722 :
3723 0 : status = parent_pathref(talloc_tos(),
3724 : conn->cwd_fsp,
3725 : new_smb_fname,
3726 : &parent_fname,
3727 : &base_name);
3728 0 : if (!NT_STATUS_IS_OK(status)) {
3729 0 : return status;
3730 : }
3731 :
3732 0 : ret = SMB_VFS_SYMLINKAT(conn,
3733 : &target_fname,
3734 : parent_fname->fsp,
3735 : base_name);
3736 0 : if (ret != 0) {
3737 0 : TALLOC_FREE(parent_fname);
3738 0 : return map_nt_error_from_unix(errno);
3739 : }
3740 :
3741 0 : TALLOC_FREE(parent_fname);
3742 0 : return NT_STATUS_OK;
3743 : }
3744 :
3745 : /****************************************************************************
3746 : Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3747 : ****************************************************************************/
3748 :
3749 0 : static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
3750 : struct smb_request *req,
3751 : const char *pdata, int total_data,
3752 : struct smb_filename *smb_fname_new)
3753 : {
3754 0 : char *oldname = NULL;
3755 0 : struct files_struct *src_dirfsp = NULL;
3756 0 : struct smb_filename *smb_fname_old = NULL;
3757 0 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
3758 0 : NTTIME old_twrp = 0;
3759 0 : TALLOC_CTX *ctx = talloc_tos();
3760 0 : NTSTATUS status = NT_STATUS_OK;
3761 :
3762 0 : if (!CAN_WRITE(conn)) {
3763 0 : return NT_STATUS_DOS(ERRSRV, ERRaccess);
3764 : }
3765 :
3766 : /* Set a hard link. */
3767 0 : if (total_data == 0) {
3768 0 : return NT_STATUS_INVALID_PARAMETER;
3769 : }
3770 :
3771 0 : if (req->posix_pathnames) {
3772 0 : srvstr_get_path_posix(ctx,
3773 : pdata,
3774 0 : req->flags2,
3775 : &oldname,
3776 : pdata,
3777 : total_data,
3778 : STR_TERMINATE,
3779 : &status);
3780 : } else {
3781 0 : srvstr_get_path(ctx,
3782 : pdata,
3783 0 : req->flags2,
3784 : &oldname,
3785 : pdata,
3786 : total_data,
3787 : STR_TERMINATE,
3788 : &status);
3789 : }
3790 0 : if (!NT_STATUS_IS_OK(status)) {
3791 0 : return status;
3792 : }
3793 :
3794 0 : DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3795 : smb_fname_str_dbg(smb_fname_new), oldname));
3796 :
3797 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
3798 0 : extract_snapshot_token(oldname, &old_twrp);
3799 : }
3800 0 : status = filename_convert_dirfsp(ctx,
3801 : conn,
3802 : oldname,
3803 : ucf_flags,
3804 : old_twrp,
3805 : &src_dirfsp,
3806 : &smb_fname_old);
3807 0 : if (!NT_STATUS_IS_OK(status)) {
3808 0 : return status;
3809 : }
3810 :
3811 0 : return hardlink_internals(ctx,
3812 : conn,
3813 : req,
3814 : false,
3815 : src_dirfsp,
3816 : smb_fname_old,
3817 : NULL, /* new_dirfsp */
3818 : smb_fname_new);
3819 : }
3820 :
3821 : /****************************************************************************
3822 : Allow a UNIX info mknod.
3823 : ****************************************************************************/
3824 :
3825 0 : static NTSTATUS smb_unix_mknod(connection_struct *conn,
3826 : const char *pdata,
3827 : int total_data,
3828 : const struct smb_filename *smb_fname)
3829 : {
3830 0 : uint32_t file_type = IVAL(pdata,56);
3831 : #if defined(HAVE_MAKEDEV)
3832 0 : uint32_t dev_major = IVAL(pdata,60);
3833 0 : uint32_t dev_minor = IVAL(pdata,68);
3834 : #endif
3835 0 : SMB_DEV_T dev = (SMB_DEV_T)0;
3836 0 : uint32_t raw_unixmode = IVAL(pdata,84);
3837 : NTSTATUS status;
3838 : mode_t unixmode;
3839 : int ret;
3840 0 : struct smb_filename *parent_fname = NULL;
3841 0 : struct smb_filename *base_name = NULL;
3842 :
3843 0 : if (total_data < 100) {
3844 0 : return NT_STATUS_INVALID_PARAMETER;
3845 : }
3846 :
3847 0 : status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3848 : PERM_NEW_FILE, &unixmode);
3849 0 : if (!NT_STATUS_IS_OK(status)) {
3850 0 : return status;
3851 : }
3852 :
3853 : #if defined(HAVE_MAKEDEV)
3854 0 : dev = makedev(dev_major, dev_minor);
3855 : #endif
3856 :
3857 0 : switch (file_type) {
3858 : /* We can't create other objects here. */
3859 0 : case UNIX_TYPE_FILE:
3860 : case UNIX_TYPE_DIR:
3861 : case UNIX_TYPE_SYMLINK:
3862 0 : return NT_STATUS_ACCESS_DENIED;
3863 : #if defined(S_IFIFO)
3864 0 : case UNIX_TYPE_FIFO:
3865 0 : unixmode |= S_IFIFO;
3866 0 : break;
3867 : #endif
3868 : #if defined(S_IFSOCK)
3869 0 : case UNIX_TYPE_SOCKET:
3870 0 : unixmode |= S_IFSOCK;
3871 0 : break;
3872 : #endif
3873 : #if defined(S_IFCHR)
3874 0 : case UNIX_TYPE_CHARDEV:
3875 : /* This is only allowed for root. */
3876 0 : if (get_current_uid(conn) != sec_initial_uid()) {
3877 0 : return NT_STATUS_ACCESS_DENIED;
3878 : }
3879 0 : unixmode |= S_IFCHR;
3880 0 : break;
3881 : #endif
3882 : #if defined(S_IFBLK)
3883 0 : case UNIX_TYPE_BLKDEV:
3884 0 : if (get_current_uid(conn) != sec_initial_uid()) {
3885 0 : return NT_STATUS_ACCESS_DENIED;
3886 : }
3887 0 : unixmode |= S_IFBLK;
3888 0 : break;
3889 : #endif
3890 0 : default:
3891 0 : return NT_STATUS_INVALID_PARAMETER;
3892 : }
3893 :
3894 0 : DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
3895 : "%.0f mode 0%o for file %s\n", (double)dev,
3896 : (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
3897 :
3898 0 : status = parent_pathref(talloc_tos(),
3899 : conn->cwd_fsp,
3900 : smb_fname,
3901 : &parent_fname,
3902 : &base_name);
3903 0 : if (!NT_STATUS_IS_OK(status)) {
3904 0 : return status;
3905 : }
3906 :
3907 : /* Ok - do the mknod. */
3908 0 : ret = SMB_VFS_MKNODAT(conn,
3909 : parent_fname->fsp,
3910 : base_name,
3911 : unixmode,
3912 : dev);
3913 :
3914 0 : if (ret != 0) {
3915 0 : TALLOC_FREE(parent_fname);
3916 0 : return map_nt_error_from_unix(errno);
3917 : }
3918 :
3919 : /* If any of the other "set" calls fail we
3920 : * don't want to end up with a half-constructed mknod.
3921 : */
3922 :
3923 0 : if (lp_inherit_permissions(SNUM(conn))) {
3924 0 : inherit_access_posix_acl(conn,
3925 0 : parent_fname->fsp,
3926 : smb_fname,
3927 : unixmode);
3928 : }
3929 0 : TALLOC_FREE(parent_fname);
3930 :
3931 0 : return NT_STATUS_OK;
3932 : }
3933 :
3934 : /****************************************************************************
3935 : Deal with SMB_SET_FILE_UNIX_BASIC.
3936 : ****************************************************************************/
3937 :
3938 0 : static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
3939 : struct smb_request *req,
3940 : const char *pdata,
3941 : int total_data,
3942 : files_struct *fsp,
3943 : struct smb_filename *smb_fname)
3944 : {
3945 : struct smb_file_time ft;
3946 : uint32_t raw_unixmode;
3947 : mode_t unixmode;
3948 0 : off_t size = 0;
3949 0 : uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3950 0 : gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3951 0 : NTSTATUS status = NT_STATUS_OK;
3952 : enum perm_type ptype;
3953 0 : files_struct *all_fsps = NULL;
3954 0 : bool modify_mtime = true;
3955 : struct file_id id;
3956 : SMB_STRUCT_STAT sbuf;
3957 :
3958 0 : if (!CAN_WRITE(conn)) {
3959 0 : return NT_STATUS_DOS(ERRSRV, ERRaccess);
3960 : }
3961 :
3962 0 : init_smb_file_time(&ft);
3963 :
3964 0 : if (total_data < 100) {
3965 0 : return NT_STATUS_INVALID_PARAMETER;
3966 : }
3967 :
3968 0 : if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3969 0 : IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3970 0 : size=IVAL(pdata,0); /* first 8 Bytes are size */
3971 0 : size |= (((off_t)IVAL(pdata,4)) << 32);
3972 : }
3973 :
3974 0 : ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
3975 0 : ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
3976 0 : set_owner = (uid_t)IVAL(pdata,40);
3977 0 : set_grp = (gid_t)IVAL(pdata,48);
3978 0 : raw_unixmode = IVAL(pdata,84);
3979 :
3980 0 : if (VALID_STAT(smb_fname->st)) {
3981 0 : if (S_ISDIR(smb_fname->st.st_ex_mode)) {
3982 0 : ptype = PERM_EXISTING_DIR;
3983 : } else {
3984 0 : ptype = PERM_EXISTING_FILE;
3985 : }
3986 : } else {
3987 0 : ptype = PERM_NEW_FILE;
3988 : }
3989 :
3990 0 : status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
3991 : ptype, &unixmode);
3992 0 : if (!NT_STATUS_IS_OK(status)) {
3993 0 : return status;
3994 : }
3995 :
3996 0 : DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
3997 : "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3998 : smb_fname_str_dbg(smb_fname), (double)size,
3999 : (unsigned int)set_owner, (unsigned int)set_grp,
4000 : (int)raw_unixmode));
4001 :
4002 0 : sbuf = smb_fname->st;
4003 :
4004 0 : if (!VALID_STAT(sbuf)) {
4005 : /*
4006 : * The only valid use of this is to create character and block
4007 : * devices, and named pipes. This is deprecated (IMHO) and
4008 : * a new info level should be used for mknod. JRA.
4009 : */
4010 :
4011 0 : return smb_unix_mknod(conn,
4012 : pdata,
4013 : total_data,
4014 : smb_fname);
4015 : }
4016 :
4017 : #if 1
4018 : /* Horrible backwards compatibility hack as an old server bug
4019 : * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4020 : * */
4021 :
4022 0 : if (!size) {
4023 0 : size = get_file_size_stat(&sbuf);
4024 : }
4025 : #endif
4026 :
4027 : /*
4028 : * Deal with the UNIX specific mode set.
4029 : */
4030 :
4031 0 : if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4032 : int ret;
4033 :
4034 0 : if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4035 0 : DBG_WARNING("Can't set mode on symlink %s\n",
4036 : smb_fname_str_dbg(smb_fname));
4037 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4038 : }
4039 :
4040 0 : DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4041 : "setting mode 0%o for file %s\n",
4042 : (unsigned int)unixmode,
4043 : smb_fname_str_dbg(smb_fname)));
4044 0 : ret = SMB_VFS_FCHMOD(fsp, unixmode);
4045 0 : if (ret != 0) {
4046 0 : return map_nt_error_from_unix(errno);
4047 : }
4048 : }
4049 :
4050 : /*
4051 : * Deal with the UNIX specific uid set.
4052 : */
4053 :
4054 0 : if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
4055 0 : (sbuf.st_ex_uid != set_owner)) {
4056 : int ret;
4057 :
4058 0 : DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4059 : "changing owner %u for path %s\n",
4060 : (unsigned int)set_owner,
4061 : smb_fname_str_dbg(smb_fname)));
4062 :
4063 0 : if (fsp &&
4064 0 : !fsp->fsp_flags.is_pathref &&
4065 0 : fsp_get_io_fd(fsp) != -1)
4066 : {
4067 0 : ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
4068 : } else {
4069 : /*
4070 : * UNIX extensions calls must always operate
4071 : * on symlinks.
4072 : */
4073 0 : ret = SMB_VFS_LCHOWN(conn, smb_fname,
4074 : set_owner, (gid_t)-1);
4075 : }
4076 :
4077 0 : if (ret != 0) {
4078 0 : status = map_nt_error_from_unix(errno);
4079 0 : return status;
4080 : }
4081 : }
4082 :
4083 : /*
4084 : * Deal with the UNIX specific gid set.
4085 : */
4086 :
4087 0 : if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
4088 0 : (sbuf.st_ex_gid != set_grp)) {
4089 : int ret;
4090 :
4091 0 : DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
4092 : "changing group %u for file %s\n",
4093 : (unsigned int)set_grp,
4094 : smb_fname_str_dbg(smb_fname)));
4095 0 : if (fsp &&
4096 0 : !fsp->fsp_flags.is_pathref &&
4097 0 : fsp_get_io_fd(fsp) != -1)
4098 : {
4099 0 : ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
4100 : } else {
4101 : /*
4102 : * UNIX extensions calls must always operate
4103 : * on symlinks.
4104 : */
4105 0 : ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
4106 : set_grp);
4107 : }
4108 0 : if (ret != 0) {
4109 0 : status = map_nt_error_from_unix(errno);
4110 0 : return status;
4111 : }
4112 : }
4113 :
4114 : /* Deal with any size changes. */
4115 :
4116 0 : if (S_ISREG(sbuf.st_ex_mode)) {
4117 0 : status = smb_set_file_size(conn, req,
4118 : fsp,
4119 : smb_fname,
4120 : &sbuf,
4121 : size,
4122 : false);
4123 0 : if (!NT_STATUS_IS_OK(status)) {
4124 0 : return status;
4125 : }
4126 : }
4127 :
4128 : /* Deal with any time changes. */
4129 0 : if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
4130 : /* No change, don't cancel anything. */
4131 0 : return status;
4132 : }
4133 :
4134 0 : id = vfs_file_id_from_sbuf(conn, &sbuf);
4135 0 : for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
4136 0 : all_fsps = file_find_di_next(all_fsps, true)) {
4137 : /*
4138 : * We're setting the time explicitly for UNIX.
4139 : * Cancel any pending changes over all handles.
4140 : */
4141 0 : all_fsps->fsp_flags.update_write_time_on_close = false;
4142 0 : TALLOC_FREE(all_fsps->update_write_time_event);
4143 : }
4144 :
4145 : /*
4146 : * Override the "setting_write_time"
4147 : * parameter here as it almost does what
4148 : * we need. Just remember if we modified
4149 : * mtime and send the notify ourselves.
4150 : */
4151 0 : if (is_omit_timespec(&ft.mtime)) {
4152 0 : modify_mtime = false;
4153 : }
4154 :
4155 0 : status = smb_set_file_time(conn,
4156 : fsp,
4157 : smb_fname,
4158 : &ft,
4159 : false);
4160 0 : if (modify_mtime) {
4161 0 : notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4162 0 : FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
4163 : }
4164 0 : return status;
4165 : }
4166 :
4167 : /****************************************************************************
4168 : Deal with SMB_SET_FILE_UNIX_INFO2.
4169 : ****************************************************************************/
4170 :
4171 0 : static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
4172 : struct smb_request *req,
4173 : const char *pdata,
4174 : int total_data,
4175 : files_struct *fsp,
4176 : struct smb_filename *smb_fname)
4177 : {
4178 : NTSTATUS status;
4179 : uint32_t smb_fflags;
4180 : uint32_t smb_fmask;
4181 :
4182 0 : if (!CAN_WRITE(conn)) {
4183 0 : return NT_STATUS_DOS(ERRSRV, ERRaccess);
4184 : }
4185 :
4186 0 : if (total_data < 116) {
4187 0 : return NT_STATUS_INVALID_PARAMETER;
4188 : }
4189 :
4190 : /* Start by setting all the fields that are common between UNIX_BASIC
4191 : * and UNIX_INFO2.
4192 : */
4193 0 : status = smb_set_file_unix_basic(conn, req, pdata, total_data,
4194 : fsp, smb_fname);
4195 0 : if (!NT_STATUS_IS_OK(status)) {
4196 0 : return status;
4197 : }
4198 :
4199 0 : smb_fflags = IVAL(pdata, 108);
4200 0 : smb_fmask = IVAL(pdata, 112);
4201 :
4202 : /* NB: We should only attempt to alter the file flags if the client
4203 : * sends a non-zero mask.
4204 : */
4205 0 : if (smb_fmask != 0) {
4206 0 : int stat_fflags = 0;
4207 :
4208 0 : if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
4209 : smb_fmask, &stat_fflags)) {
4210 : /* Client asked to alter a flag we don't understand. */
4211 0 : return NT_STATUS_INVALID_PARAMETER;
4212 : }
4213 :
4214 0 : if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
4215 0 : DBG_WARNING("Can't change flags on symlink %s\n",
4216 : smb_fname_str_dbg(smb_fname));
4217 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4218 : }
4219 0 : if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
4220 0 : return map_nt_error_from_unix(errno);
4221 : }
4222 : }
4223 :
4224 : /* XXX: need to add support for changing the create_time here. You
4225 : * can do this for paths on Darwin with setattrlist(2). The right way
4226 : * to hook this up is probably by extending the VFS utimes interface.
4227 : */
4228 :
4229 0 : return NT_STATUS_OK;
4230 : }
4231 :
4232 : /****************************************************************************
4233 : Deal with SMB_SET_POSIX_ACL.
4234 : ****************************************************************************/
4235 :
4236 0 : static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4237 : struct smb_request *req,
4238 : const char *pdata,
4239 : int total_data_in,
4240 : files_struct *fsp,
4241 : struct smb_filename *smb_fname)
4242 : {
4243 : #if !defined(HAVE_POSIX_ACLS)
4244 : return NT_STATUS_INVALID_LEVEL;
4245 : #else
4246 : uint16_t posix_acl_version;
4247 : uint16_t num_file_acls;
4248 : uint16_t num_def_acls;
4249 0 : bool valid_file_acls = true;
4250 0 : bool valid_def_acls = true;
4251 : NTSTATUS status;
4252 : unsigned int size_needed;
4253 : unsigned int total_data;
4254 0 : bool close_fsp = false;
4255 :
4256 0 : if (total_data_in < 0) {
4257 0 : status = NT_STATUS_INVALID_PARAMETER;
4258 0 : goto out;
4259 : }
4260 :
4261 0 : total_data = total_data_in;
4262 :
4263 0 : if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4264 0 : status = NT_STATUS_INVALID_PARAMETER;
4265 0 : goto out;
4266 : }
4267 0 : posix_acl_version = SVAL(pdata,0);
4268 0 : num_file_acls = SVAL(pdata,2);
4269 0 : num_def_acls = SVAL(pdata,4);
4270 :
4271 0 : if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4272 0 : valid_file_acls = false;
4273 0 : num_file_acls = 0;
4274 : }
4275 :
4276 0 : if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4277 0 : valid_def_acls = false;
4278 0 : num_def_acls = 0;
4279 : }
4280 :
4281 0 : if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4282 0 : status = NT_STATUS_INVALID_PARAMETER;
4283 0 : goto out;
4284 : }
4285 :
4286 : /* Wrap checks. */
4287 : if (num_file_acls + num_def_acls < num_file_acls) {
4288 : status = NT_STATUS_INVALID_PARAMETER;
4289 : goto out;
4290 : }
4291 :
4292 0 : size_needed = num_file_acls + num_def_acls;
4293 :
4294 : /*
4295 : * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4296 : * than UINT_MAX, so check by division.
4297 : */
4298 0 : if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4299 0 : status = NT_STATUS_INVALID_PARAMETER;
4300 0 : goto out;
4301 : }
4302 :
4303 0 : size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
4304 0 : if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
4305 0 : status = NT_STATUS_INVALID_PARAMETER;
4306 0 : goto out;
4307 : }
4308 0 : size_needed += SMB_POSIX_ACL_HEADER_SIZE;
4309 :
4310 0 : if (total_data < size_needed) {
4311 0 : status = NT_STATUS_INVALID_PARAMETER;
4312 0 : goto out;
4313 : }
4314 :
4315 : /*
4316 : * Ensure we always operate on a file descriptor, not just
4317 : * the filename.
4318 : */
4319 0 : if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
4320 0 : uint32_t access_mask = SEC_STD_WRITE_OWNER|
4321 : SEC_STD_WRITE_DAC|
4322 : SEC_STD_READ_CONTROL|
4323 : FILE_READ_ATTRIBUTES|
4324 : FILE_WRITE_ATTRIBUTES;
4325 :
4326 0 : status = get_posix_fsp(conn,
4327 : req,
4328 : smb_fname,
4329 : access_mask,
4330 : &fsp);
4331 :
4332 0 : if (!NT_STATUS_IS_OK(status)) {
4333 0 : goto out;
4334 : }
4335 0 : close_fsp = true;
4336 : }
4337 :
4338 : /* Here we know fsp != NULL */
4339 0 : SMB_ASSERT(fsp != NULL);
4340 :
4341 0 : status = refuse_symlink_fsp(fsp);
4342 0 : if (!NT_STATUS_IS_OK(status)) {
4343 0 : goto out;
4344 : }
4345 :
4346 : /* If we have a default acl, this *must* be a directory. */
4347 0 : if (valid_def_acls && !fsp->fsp_flags.is_directory) {
4348 0 : DBG_INFO("Can't set default acls on "
4349 : "non-directory %s\n",
4350 : fsp_str_dbg(fsp));
4351 0 : return NT_STATUS_INVALID_HANDLE;
4352 : }
4353 :
4354 0 : DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
4355 : "num_def_acls = %"PRIu16"\n",
4356 : fsp_str_dbg(fsp),
4357 : num_file_acls,
4358 : num_def_acls);
4359 :
4360 : /* Move pdata to the start of the file ACL entries. */
4361 0 : pdata += SMB_POSIX_ACL_HEADER_SIZE;
4362 :
4363 0 : if (valid_file_acls) {
4364 0 : status = set_unix_posix_acl(conn,
4365 : fsp,
4366 : num_file_acls,
4367 : pdata);
4368 0 : if (!NT_STATUS_IS_OK(status)) {
4369 0 : goto out;
4370 : }
4371 : }
4372 :
4373 : /* Move pdata to the start of the default ACL entries. */
4374 0 : pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
4375 :
4376 0 : if (valid_def_acls) {
4377 0 : status = set_unix_posix_default_acl(conn,
4378 : fsp,
4379 : num_def_acls,
4380 : pdata);
4381 0 : if (!NT_STATUS_IS_OK(status)) {
4382 0 : goto out;
4383 : }
4384 : }
4385 :
4386 0 : status = NT_STATUS_OK;
4387 :
4388 0 : out:
4389 :
4390 0 : if (close_fsp) {
4391 0 : (void)close_file_free(req, &fsp, NORMAL_CLOSE);
4392 : }
4393 0 : return status;
4394 : #endif
4395 : }
4396 :
4397 0 : static void call_trans2setpathinfo(
4398 : connection_struct *conn,
4399 : struct smb_request *req,
4400 : char **pparams,
4401 : int total_params,
4402 : char **ppdata,
4403 : int total_data,
4404 : unsigned int max_data_bytes)
4405 : {
4406 : uint16_t info_level;
4407 0 : struct smb_filename *smb_fname = NULL;
4408 0 : struct files_struct *dirfsp = NULL;
4409 0 : struct files_struct *fsp = NULL;
4410 0 : char *params = *pparams;
4411 0 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4412 0 : NTTIME twrp = 0;
4413 0 : char *fname = NULL;
4414 : bool info_level_handled;
4415 0 : int data_return_size = 0;
4416 : NTSTATUS status;
4417 :
4418 0 : if (params == NULL) {
4419 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4420 0 : return;
4421 : }
4422 :
4423 : /* set path info */
4424 0 : if (total_params < 7) {
4425 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4426 0 : return;
4427 : }
4428 :
4429 0 : info_level = SVAL(params,0);
4430 :
4431 0 : if (INFO_LEVEL_IS_UNIX(info_level)) {
4432 0 : if (!lp_smb1_unix_extensions()) {
4433 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4434 0 : return;
4435 : }
4436 0 : if (!req->posix_pathnames) {
4437 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4438 0 : return;
4439 : }
4440 : }
4441 :
4442 0 : if (req->posix_pathnames) {
4443 0 : srvstr_get_path_posix(req,
4444 : params,
4445 0 : req->flags2,
4446 : &fname,
4447 0 : ¶ms[6],
4448 0 : total_params - 6,
4449 : STR_TERMINATE,
4450 : &status);
4451 : } else {
4452 0 : srvstr_get_path(req,
4453 : params,
4454 0 : req->flags2,
4455 : &fname,
4456 0 : ¶ms[6],
4457 0 : total_params - 6,
4458 : STR_TERMINATE,
4459 : &status);
4460 : }
4461 0 : if (!NT_STATUS_IS_OK(status)) {
4462 0 : reply_nterror(req, status);
4463 0 : return;
4464 : }
4465 :
4466 0 : DBG_NOTICE("fname=%s info_level=%d totdata=%d\n",
4467 : fname,
4468 : info_level,
4469 : total_data);
4470 :
4471 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
4472 0 : extract_snapshot_token(fname, &twrp);
4473 : }
4474 0 : status = filename_convert_dirfsp(req,
4475 : conn,
4476 : fname,
4477 : ucf_flags,
4478 : twrp,
4479 : &dirfsp,
4480 : &smb_fname);
4481 0 : if (!NT_STATUS_IS_OK(status)) {
4482 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4483 0 : reply_botherror(req,
4484 : NT_STATUS_PATH_NOT_COVERED,
4485 : ERRSRV, ERRbadpath);
4486 0 : return;
4487 : }
4488 0 : reply_nterror(req, status);
4489 0 : return;
4490 : }
4491 :
4492 0 : info_level_handled = true; /* Untouched in switch cases below */
4493 :
4494 0 : switch (info_level) {
4495 :
4496 0 : default:
4497 0 : info_level_handled = false;
4498 0 : break;
4499 :
4500 0 : case SMB_POSIX_PATH_OPEN:
4501 0 : status = smb_posix_open(
4502 : conn,
4503 : req,
4504 : ppdata,
4505 : total_data,
4506 : smb_fname,
4507 : &data_return_size);
4508 0 : break;
4509 :
4510 0 : case SMB_POSIX_PATH_UNLINK:
4511 0 : status = smb_posix_unlink(
4512 : conn, req, *ppdata, total_data, smb_fname);
4513 0 : break;
4514 :
4515 0 : case SMB_SET_FILE_UNIX_LINK:
4516 0 : status = smb_set_file_unix_link(
4517 : conn, req, *ppdata, total_data, smb_fname);
4518 0 : break;
4519 :
4520 0 : case SMB_SET_FILE_UNIX_HLINK:
4521 0 : status = smb_set_file_unix_hlink(
4522 : conn, req, *ppdata, total_data, smb_fname);
4523 0 : break;
4524 :
4525 0 : case SMB_SET_FILE_UNIX_BASIC:
4526 0 : status = smb_set_file_unix_basic(
4527 : conn,
4528 : req,
4529 : *ppdata,
4530 : total_data,
4531 0 : smb_fname->fsp,
4532 : smb_fname);
4533 0 : break;
4534 :
4535 0 : case SMB_SET_FILE_UNIX_INFO2:
4536 0 : status = smb_set_file_unix_info2(
4537 : conn,
4538 : req,
4539 : *ppdata,
4540 : total_data,
4541 0 : smb_fname->fsp,
4542 : smb_fname);
4543 0 : break;
4544 0 : case SMB_SET_POSIX_ACL:
4545 0 : status = smb_set_posix_acl(
4546 : conn, req, *ppdata, total_data, NULL, smb_fname);
4547 0 : break;
4548 : }
4549 :
4550 0 : if (info_level_handled) {
4551 0 : handle_trans2setfilepathinfo_result(
4552 : conn,
4553 : req,
4554 : info_level,
4555 : status,
4556 : *ppdata,
4557 : data_return_size,
4558 : max_data_bytes);
4559 0 : return;
4560 : }
4561 :
4562 : /*
4563 : * smb_fname->fsp may be NULL if smb_fname points at a symlink
4564 : * and we're in POSIX context, so be careful when using fsp
4565 : * below, it can still be NULL.
4566 : */
4567 0 : fsp = smb_fname->fsp;
4568 :
4569 0 : status = smbd_do_setfilepathinfo(
4570 : conn,
4571 : req,
4572 : req,
4573 : info_level,
4574 : fsp,
4575 : smb_fname,
4576 : ppdata,
4577 : total_data,
4578 : &data_return_size);
4579 :
4580 0 : handle_trans2setfilepathinfo_result(
4581 : conn,
4582 : req,
4583 : info_level,
4584 : status,
4585 : *ppdata,
4586 : data_return_size,
4587 : max_data_bytes);
4588 : }
4589 :
4590 0 : static void call_trans2setfileinfo(
4591 : connection_struct *conn,
4592 : struct smb_request *req,
4593 : char **pparams,
4594 : int total_params,
4595 : char **ppdata,
4596 : int total_data,
4597 : unsigned int max_data_bytes)
4598 : {
4599 0 : char *pdata = *ppdata;
4600 : uint16_t info_level;
4601 0 : struct smb_filename *smb_fname = NULL;
4602 0 : struct files_struct *fsp = NULL;
4603 0 : char *params = *pparams;
4604 0 : int data_return_size = 0;
4605 : bool info_level_handled;
4606 : NTSTATUS status;
4607 : int ret;
4608 :
4609 0 : if (params == NULL) {
4610 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4611 0 : return;
4612 : }
4613 0 : if (total_params < 4) {
4614 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4615 0 : return;
4616 : }
4617 :
4618 0 : fsp = file_fsp(req, SVAL(params,0));
4619 : /* Basic check for non-null fsp. */
4620 0 : if (!check_fsp_open(conn, req, fsp)) {
4621 0 : return;
4622 : }
4623 0 : info_level = SVAL(params,2);
4624 :
4625 0 : if (INFO_LEVEL_IS_UNIX(info_level)) {
4626 0 : if (!lp_smb1_unix_extensions()) {
4627 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4628 0 : return;
4629 : }
4630 0 : if (!req->posix_pathnames) {
4631 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4632 0 : return;
4633 : }
4634 : }
4635 :
4636 0 : smb_fname = fsp->fsp_name;
4637 :
4638 0 : DBG_NOTICE("fnum=%s fname=%s info_level=%d totdata=%d\n",
4639 : fsp_fnum_dbg(fsp),
4640 : fsp_str_dbg(fsp),
4641 : info_level,
4642 : total_data);
4643 :
4644 0 : if (fsp_get_pathref_fd(fsp) == -1) {
4645 : /*
4646 : * This is actually a SETFILEINFO on a directory
4647 : * handle (returned from an NT SMB). NT5.0 seems
4648 : * to do this call. JRA.
4649 : */
4650 0 : ret = vfs_stat(conn, smb_fname);
4651 0 : if (ret != 0) {
4652 0 : DBG_NOTICE("vfs_stat of %s failed (%s)\n",
4653 : smb_fname_str_dbg(smb_fname),
4654 : strerror(errno));
4655 0 : reply_nterror(req, map_nt_error_from_unix(errno));
4656 0 : return;
4657 : }
4658 0 : } else if (fsp->print_file) {
4659 : /*
4660 : * Doing a DELETE_ON_CLOSE should cancel a print job.
4661 : */
4662 0 : if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) &&
4663 0 : CVAL(pdata,0)) {
4664 :
4665 0 : fsp->fsp_flags.delete_on_close = true;
4666 :
4667 0 : DBG_NOTICE("Cancelling print job (%s)\n",
4668 : fsp_str_dbg(fsp));
4669 :
4670 0 : SSVAL(params,0,0);
4671 0 : send_trans2_replies(
4672 : conn,
4673 : req,
4674 0 : NT_STATUS_OK,
4675 : params,
4676 : 2,
4677 : *ppdata, 0,
4678 : max_data_bytes);
4679 0 : return;
4680 : } else {
4681 0 : reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
4682 0 : return;
4683 : }
4684 : } else {
4685 : /*
4686 : * Original code - this is an open file.
4687 : */
4688 0 : status = vfs_stat_fsp(fsp);
4689 0 : if (!NT_STATUS_IS_OK(status)) {
4690 0 : DBG_NOTICE("fstat of %s failed (%s)\n",
4691 : fsp_fnum_dbg(fsp),
4692 : nt_errstr(status));
4693 0 : reply_nterror(req, status);
4694 0 : return;
4695 : }
4696 : }
4697 :
4698 0 : info_level_handled = true; /* Untouched in switch cases below */
4699 :
4700 0 : switch (info_level) {
4701 :
4702 0 : default:
4703 0 : info_level_handled = false;
4704 0 : break;
4705 :
4706 0 : case SMB_SET_FILE_UNIX_BASIC:
4707 0 : status = smb_set_file_unix_basic(
4708 : conn, req, pdata, total_data, fsp, smb_fname);
4709 0 : break;
4710 :
4711 0 : case SMB_SET_FILE_UNIX_INFO2:
4712 0 : status = smb_set_file_unix_info2(
4713 : conn, req, pdata, total_data, fsp, smb_fname);
4714 0 : break;
4715 :
4716 0 : case SMB_SET_POSIX_LOCK:
4717 0 : status = smb_set_posix_lock(
4718 : conn, req, *ppdata, total_data, fsp);
4719 0 : break;
4720 : }
4721 :
4722 0 : if (info_level_handled) {
4723 0 : handle_trans2setfilepathinfo_result(
4724 : conn,
4725 : req,
4726 : info_level,
4727 : status,
4728 : *ppdata,
4729 : data_return_size,
4730 : max_data_bytes);
4731 0 : return;
4732 : }
4733 :
4734 0 : status = smbd_do_setfilepathinfo(
4735 : conn,
4736 : req,
4737 : req,
4738 : info_level,
4739 : fsp,
4740 : smb_fname,
4741 : ppdata,
4742 : total_data,
4743 : &data_return_size);
4744 :
4745 0 : handle_trans2setfilepathinfo_result(
4746 : conn,
4747 : req,
4748 : info_level,
4749 : status,
4750 : *ppdata,
4751 : data_return_size,
4752 : max_data_bytes);
4753 : }
4754 :
4755 : /****************************************************************************
4756 : Reply to a TRANS2_MKDIR (make directory with extended attributes).
4757 : ****************************************************************************/
4758 :
4759 0 : static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
4760 : char **pparams, int total_params,
4761 : char **ppdata, int total_data,
4762 : unsigned int max_data_bytes)
4763 : {
4764 0 : struct files_struct *dirfsp = NULL;
4765 0 : struct files_struct *fsp = NULL;
4766 0 : struct smb_filename *smb_dname = NULL;
4767 0 : char *params = *pparams;
4768 0 : char *pdata = *ppdata;
4769 0 : char *directory = NULL;
4770 0 : NTSTATUS status = NT_STATUS_OK;
4771 0 : struct ea_list *ea_list = NULL;
4772 0 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4773 0 : NTTIME twrp = 0;
4774 0 : TALLOC_CTX *ctx = talloc_tos();
4775 :
4776 0 : if (!CAN_WRITE(conn)) {
4777 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4778 0 : return;
4779 : }
4780 :
4781 0 : if (total_params < 5) {
4782 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4783 0 : return;
4784 : }
4785 :
4786 0 : if (req->posix_pathnames) {
4787 0 : srvstr_get_path_posix(ctx,
4788 : params,
4789 0 : req->flags2,
4790 : &directory,
4791 0 : ¶ms[4],
4792 0 : total_params - 4,
4793 : STR_TERMINATE,
4794 : &status);
4795 : } else {
4796 0 : srvstr_get_path(ctx,
4797 : params,
4798 0 : req->flags2,
4799 : &directory,
4800 0 : ¶ms[4],
4801 0 : total_params - 4,
4802 : STR_TERMINATE,
4803 : &status);
4804 : }
4805 0 : if (!NT_STATUS_IS_OK(status)) {
4806 0 : reply_nterror(req, status);
4807 0 : return;
4808 : }
4809 :
4810 0 : DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4811 :
4812 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
4813 0 : extract_snapshot_token(directory, &twrp);
4814 : }
4815 0 : status = filename_convert_dirfsp(ctx,
4816 : conn,
4817 : directory,
4818 : ucf_flags,
4819 : twrp,
4820 : &dirfsp,
4821 : &smb_dname);
4822 0 : if (!NT_STATUS_IS_OK(status)) {
4823 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4824 0 : reply_botherror(req,
4825 : NT_STATUS_PATH_NOT_COVERED,
4826 : ERRSRV, ERRbadpath);
4827 0 : return;
4828 : }
4829 0 : reply_nterror(req, status);
4830 0 : return;
4831 : }
4832 :
4833 : /*
4834 : * OS/2 workplace shell seems to send SET_EA requests of "null"
4835 : * length (4 bytes containing IVAL 4).
4836 : * They seem to have no effect. Bug #3212. JRA.
4837 : */
4838 :
4839 0 : if (total_data && (total_data != 4)) {
4840 : /* Any data in this call is an EA list. */
4841 0 : if (total_data < 10) {
4842 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4843 0 : goto out;
4844 : }
4845 :
4846 0 : if (IVAL(pdata,0) > total_data) {
4847 0 : DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4848 : IVAL(pdata,0), (unsigned int)total_data));
4849 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4850 0 : goto out;
4851 : }
4852 :
4853 0 : ea_list = read_ea_list(talloc_tos(), pdata + 4,
4854 0 : total_data - 4);
4855 0 : if (!ea_list) {
4856 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4857 0 : goto out;
4858 : }
4859 :
4860 0 : if (!lp_ea_support(SNUM(conn))) {
4861 0 : reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
4862 0 : goto out;
4863 : }
4864 : }
4865 : /* If total_data == 4 Windows doesn't care what values
4866 : * are placed in that field, it just ignores them.
4867 : * The System i QNTC IBM SMB client puts bad values here,
4868 : * so ignore them. */
4869 :
4870 0 : status = SMB_VFS_CREATE_FILE(
4871 : conn, /* conn */
4872 : req, /* req */
4873 : dirfsp, /* dirfsp */
4874 : smb_dname, /* fname */
4875 : MAXIMUM_ALLOWED_ACCESS, /* access_mask */
4876 : FILE_SHARE_NONE, /* share_access */
4877 : FILE_CREATE, /* create_disposition*/
4878 : FILE_DIRECTORY_FILE, /* create_options */
4879 : FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
4880 : 0, /* oplock_request */
4881 : NULL, /* lease */
4882 : 0, /* allocation_size */
4883 : 0, /* private_flags */
4884 : NULL, /* sd */
4885 : NULL, /* ea_list */
4886 : &fsp, /* result */
4887 : NULL, /* pinfo */
4888 : NULL, NULL); /* create context */
4889 0 : if (!NT_STATUS_IS_OK(status)) {
4890 0 : reply_nterror(req, status);
4891 0 : goto out;
4892 : }
4893 :
4894 : /* Try and set any given EA. */
4895 0 : if (ea_list) {
4896 0 : status = set_ea(conn, fsp, ea_list);
4897 0 : if (!NT_STATUS_IS_OK(status)) {
4898 0 : reply_nterror(req, status);
4899 0 : goto out;
4900 : }
4901 : }
4902 :
4903 : /* Realloc the parameter and data sizes */
4904 0 : *pparams = (char *)SMB_REALLOC(*pparams,2);
4905 0 : if(*pparams == NULL) {
4906 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
4907 0 : goto out;
4908 : }
4909 0 : params = *pparams;
4910 :
4911 0 : SSVAL(params,0,0);
4912 :
4913 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
4914 :
4915 0 : out:
4916 0 : if (fsp != NULL) {
4917 0 : close_file_free(NULL, &fsp, NORMAL_CLOSE);
4918 : }
4919 0 : TALLOC_FREE(smb_dname);
4920 0 : return;
4921 : }
4922 :
4923 : /****************************************************************************
4924 : Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4925 : We don't actually do this - we just send a null response.
4926 : ****************************************************************************/
4927 :
4928 0 : static void call_trans2findnotifyfirst(connection_struct *conn,
4929 : struct smb_request *req,
4930 : char **pparams, int total_params,
4931 : char **ppdata, int total_data,
4932 : unsigned int max_data_bytes)
4933 : {
4934 0 : char *params = *pparams;
4935 : uint16_t info_level;
4936 :
4937 0 : if (total_params < 6) {
4938 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4939 0 : return;
4940 : }
4941 :
4942 0 : info_level = SVAL(params,4);
4943 0 : DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4944 :
4945 0 : switch (info_level) {
4946 0 : case 1:
4947 : case 2:
4948 0 : break;
4949 0 : default:
4950 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4951 0 : return;
4952 : }
4953 :
4954 : /* Realloc the parameter and data sizes */
4955 0 : *pparams = (char *)SMB_REALLOC(*pparams,6);
4956 0 : if (*pparams == NULL) {
4957 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
4958 0 : return;
4959 : }
4960 0 : params = *pparams;
4961 :
4962 0 : SSVAL(params,0,fnf_handle);
4963 0 : SSVAL(params,2,0); /* No changes */
4964 0 : SSVAL(params,4,0); /* No EA errors */
4965 :
4966 0 : fnf_handle++;
4967 :
4968 0 : if(fnf_handle == 0)
4969 0 : fnf_handle = 257;
4970 :
4971 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
4972 :
4973 0 : return;
4974 : }
4975 :
4976 : /****************************************************************************
4977 : Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4978 : changes). Currently this does nothing.
4979 : ****************************************************************************/
4980 :
4981 0 : static void call_trans2findnotifynext(connection_struct *conn,
4982 : struct smb_request *req,
4983 : char **pparams, int total_params,
4984 : char **ppdata, int total_data,
4985 : unsigned int max_data_bytes)
4986 : {
4987 0 : char *params = *pparams;
4988 :
4989 0 : DEBUG(3,("call_trans2findnotifynext\n"));
4990 :
4991 : /* Realloc the parameter and data sizes */
4992 0 : *pparams = (char *)SMB_REALLOC(*pparams,4);
4993 0 : if (*pparams == NULL) {
4994 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
4995 0 : return;
4996 : }
4997 0 : params = *pparams;
4998 :
4999 0 : SSVAL(params,0,0); /* No changes */
5000 0 : SSVAL(params,2,0); /* No EA errors */
5001 :
5002 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
5003 :
5004 0 : return;
5005 : }
5006 :
5007 : /****************************************************************************
5008 : Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5009 : ****************************************************************************/
5010 :
5011 0 : static void call_trans2getdfsreferral(connection_struct *conn,
5012 : struct smb_request *req,
5013 : char **pparams, int total_params,
5014 : char **ppdata, int total_data,
5015 : unsigned int max_data_bytes)
5016 : {
5017 0 : char *params = *pparams;
5018 0 : char *pathname = NULL;
5019 0 : int reply_size = 0;
5020 : int max_referral_level;
5021 0 : NTSTATUS status = NT_STATUS_OK;
5022 0 : TALLOC_CTX *ctx = talloc_tos();
5023 :
5024 0 : DEBUG(10,("call_trans2getdfsreferral\n"));
5025 :
5026 0 : if (!IS_IPC(conn)) {
5027 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5028 0 : return;
5029 : }
5030 :
5031 0 : if (total_params < 3) {
5032 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5033 0 : return;
5034 : }
5035 :
5036 0 : max_referral_level = SVAL(params,0);
5037 :
5038 0 : if(!lp_host_msdfs()) {
5039 0 : reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5040 0 : return;
5041 : }
5042 :
5043 0 : srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
5044 : total_params - 2, STR_TERMINATE);
5045 0 : if (!pathname) {
5046 0 : reply_nterror(req, NT_STATUS_NOT_FOUND);
5047 0 : return;
5048 : }
5049 0 : reply_size = setup_dfs_referral(
5050 : conn, pathname, max_referral_level, ppdata, &status);
5051 0 : if (reply_size < 0) {
5052 0 : reply_nterror(req, status);
5053 0 : return;
5054 : }
5055 :
5056 0 : SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
5057 : SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5058 0 : send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
5059 :
5060 0 : return;
5061 : }
5062 :
5063 : #define LMCAT_SPL 0x53
5064 : #define LMFUNC_GETJOBID 0x60
5065 :
5066 : /****************************************************************************
5067 : Reply to a TRANS2_IOCTL - used for OS/2 printing.
5068 : ****************************************************************************/
5069 :
5070 0 : static void call_trans2ioctl(connection_struct *conn,
5071 : struct smb_request *req,
5072 : char **pparams, int total_params,
5073 : char **ppdata, int total_data,
5074 : unsigned int max_data_bytes)
5075 : {
5076 : const struct loadparm_substitution *lp_sub =
5077 0 : loadparm_s3_global_substitution();
5078 0 : char *pdata = *ppdata;
5079 0 : files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
5080 : NTSTATUS status;
5081 0 : size_t len = 0;
5082 :
5083 : /* check for an invalid fid before proceeding */
5084 :
5085 0 : if (!fsp) {
5086 0 : reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5087 0 : return;
5088 : }
5089 :
5090 0 : if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
5091 0 : && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5092 0 : *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5093 0 : if (*ppdata == NULL) {
5094 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
5095 0 : return;
5096 : }
5097 0 : pdata = *ppdata;
5098 :
5099 : /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5100 : CAN ACCEPT THIS IN UNICODE. JRA. */
5101 :
5102 : /* Job number */
5103 0 : SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
5104 :
5105 0 : status = srvstr_push(pdata, req->flags2, pdata + 2,
5106 : lp_netbios_name(), 15,
5107 : STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
5108 0 : if (!NT_STATUS_IS_OK(status)) {
5109 0 : reply_nterror(req, status);
5110 0 : return;
5111 : }
5112 0 : status = srvstr_push(pdata, req->flags2, pdata+18,
5113 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
5114 : STR_ASCII|STR_TERMINATE, &len); /* Service name */
5115 0 : if (!NT_STATUS_IS_OK(status)) {
5116 0 : reply_nterror(req, status);
5117 0 : return;
5118 : }
5119 0 : send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
5120 : max_data_bytes);
5121 0 : return;
5122 : }
5123 :
5124 0 : DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5125 0 : reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5126 : }
5127 :
5128 8 : static void handle_trans2(connection_struct *conn, struct smb_request *req,
5129 : struct trans_state *state)
5130 : {
5131 8 : if (get_Protocol() >= PROTOCOL_NT1) {
5132 8 : req->flags2 |= 0x40; /* IS_LONG_NAME */
5133 8 : SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
5134 : }
5135 :
5136 8 : if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
5137 0 : if (state->call != TRANSACT2_QFSINFO &&
5138 0 : state->call != TRANSACT2_SETFSINFO) {
5139 0 : DEBUG(0,("handle_trans2: encryption required "
5140 : "with call 0x%x\n",
5141 : (unsigned int)state->call));
5142 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5143 0 : return;
5144 : }
5145 : }
5146 :
5147 8 : SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
5148 :
5149 : /* Now we must call the relevant TRANS2 function */
5150 8 : switch(state->call) {
5151 0 : case TRANSACT2_OPEN:
5152 : {
5153 0 : START_PROFILE(Trans2_open);
5154 0 : call_trans2open(conn, req,
5155 0 : &state->param, state->total_param,
5156 0 : &state->data, state->total_data,
5157 : state->max_data_return);
5158 0 : END_PROFILE(Trans2_open);
5159 0 : break;
5160 : }
5161 :
5162 0 : case TRANSACT2_FINDFIRST:
5163 : {
5164 0 : START_PROFILE(Trans2_findfirst);
5165 0 : call_trans2findfirst(conn, req,
5166 0 : &state->param, state->total_param,
5167 0 : &state->data, state->total_data,
5168 : state->max_data_return);
5169 0 : END_PROFILE(Trans2_findfirst);
5170 0 : break;
5171 : }
5172 :
5173 0 : case TRANSACT2_FINDNEXT:
5174 : {
5175 0 : START_PROFILE(Trans2_findnext);
5176 0 : call_trans2findnext(conn, req,
5177 0 : &state->param, state->total_param,
5178 0 : &state->data, state->total_data,
5179 : state->max_data_return);
5180 0 : END_PROFILE(Trans2_findnext);
5181 0 : break;
5182 : }
5183 :
5184 8 : case TRANSACT2_QFSINFO:
5185 : {
5186 8 : START_PROFILE(Trans2_qfsinfo);
5187 8 : call_trans2qfsinfo(conn, req,
5188 8 : &state->param, state->total_param,
5189 8 : &state->data, state->total_data,
5190 : state->max_data_return);
5191 8 : END_PROFILE(Trans2_qfsinfo);
5192 8 : break;
5193 : }
5194 :
5195 0 : case TRANSACT2_SETFSINFO:
5196 : {
5197 0 : START_PROFILE(Trans2_setfsinfo);
5198 0 : call_trans2setfsinfo(conn, req,
5199 0 : &state->param, state->total_param,
5200 0 : &state->data, state->total_data,
5201 : state->max_data_return);
5202 0 : END_PROFILE(Trans2_setfsinfo);
5203 0 : break;
5204 : }
5205 :
5206 0 : case TRANSACT2_QPATHINFO:
5207 : {
5208 0 : START_PROFILE(Trans2_qpathinfo);
5209 0 : call_trans2qpathinfo(
5210 : conn,
5211 : req,
5212 : &state->param,
5213 0 : state->total_param,
5214 : &state->data,
5215 0 : state->total_data,
5216 : state->max_data_return);
5217 0 : END_PROFILE(Trans2_qpathinfo);
5218 0 : break;
5219 : }
5220 :
5221 0 : case TRANSACT2_QFILEINFO:
5222 : {
5223 0 : START_PROFILE(Trans2_qfileinfo);
5224 0 : call_trans2qfileinfo(
5225 : conn,
5226 : req,
5227 : &state->param,
5228 0 : state->total_param,
5229 : &state->data,
5230 0 : state->total_data,
5231 : state->max_data_return);
5232 0 : END_PROFILE(Trans2_qfileinfo);
5233 0 : break;
5234 : }
5235 :
5236 0 : case TRANSACT2_SETPATHINFO:
5237 : {
5238 0 : START_PROFILE(Trans2_setpathinfo);
5239 0 : call_trans2setpathinfo(
5240 : conn,
5241 : req,
5242 : &state->param,
5243 0 : state->total_param,
5244 : &state->data,
5245 0 : state->total_data,
5246 : state->max_data_return);
5247 0 : END_PROFILE(Trans2_setpathinfo);
5248 0 : break;
5249 : }
5250 :
5251 0 : case TRANSACT2_SETFILEINFO:
5252 : {
5253 0 : START_PROFILE(Trans2_setfileinfo);
5254 0 : call_trans2setfileinfo(
5255 : conn,
5256 : req,
5257 : &state->param,
5258 0 : state->total_param,
5259 : &state->data,
5260 0 : state->total_data,
5261 : state->max_data_return);
5262 0 : END_PROFILE(Trans2_setfileinfo);
5263 0 : break;
5264 : }
5265 :
5266 0 : case TRANSACT2_FINDNOTIFYFIRST:
5267 : {
5268 0 : START_PROFILE(Trans2_findnotifyfirst);
5269 0 : call_trans2findnotifyfirst(conn, req,
5270 0 : &state->param, state->total_param,
5271 0 : &state->data, state->total_data,
5272 : state->max_data_return);
5273 0 : END_PROFILE(Trans2_findnotifyfirst);
5274 0 : break;
5275 : }
5276 :
5277 0 : case TRANSACT2_FINDNOTIFYNEXT:
5278 : {
5279 0 : START_PROFILE(Trans2_findnotifynext);
5280 0 : call_trans2findnotifynext(conn, req,
5281 0 : &state->param, state->total_param,
5282 0 : &state->data, state->total_data,
5283 : state->max_data_return);
5284 0 : END_PROFILE(Trans2_findnotifynext);
5285 0 : break;
5286 : }
5287 :
5288 0 : case TRANSACT2_MKDIR:
5289 : {
5290 0 : START_PROFILE(Trans2_mkdir);
5291 0 : call_trans2mkdir(conn, req,
5292 0 : &state->param, state->total_param,
5293 0 : &state->data, state->total_data,
5294 : state->max_data_return);
5295 0 : END_PROFILE(Trans2_mkdir);
5296 0 : break;
5297 : }
5298 :
5299 0 : case TRANSACT2_GET_DFS_REFERRAL:
5300 : {
5301 0 : START_PROFILE(Trans2_get_dfs_referral);
5302 0 : call_trans2getdfsreferral(conn, req,
5303 0 : &state->param, state->total_param,
5304 0 : &state->data, state->total_data,
5305 : state->max_data_return);
5306 0 : END_PROFILE(Trans2_get_dfs_referral);
5307 0 : break;
5308 : }
5309 :
5310 0 : case TRANSACT2_IOCTL:
5311 : {
5312 0 : START_PROFILE(Trans2_ioctl);
5313 0 : call_trans2ioctl(conn, req,
5314 0 : &state->param, state->total_param,
5315 0 : &state->data, state->total_data,
5316 : state->max_data_return);
5317 0 : END_PROFILE(Trans2_ioctl);
5318 0 : break;
5319 : }
5320 :
5321 0 : default:
5322 : /* Error in request */
5323 0 : DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5324 0 : reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
5325 : }
5326 : }
5327 :
5328 : /****************************************************************************
5329 : Reply to a SMBtrans2.
5330 : ****************************************************************************/
5331 :
5332 8 : void reply_trans2(struct smb_request *req)
5333 : {
5334 8 : connection_struct *conn = req->conn;
5335 : unsigned int dsoff;
5336 : unsigned int dscnt;
5337 : unsigned int psoff;
5338 : unsigned int pscnt;
5339 : unsigned int tran_call;
5340 : struct trans_state *state;
5341 : NTSTATUS result;
5342 :
5343 8 : START_PROFILE(SMBtrans2);
5344 :
5345 8 : if (req->wct < 14) {
5346 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5347 0 : END_PROFILE(SMBtrans2);
5348 0 : return;
5349 : }
5350 :
5351 8 : dsoff = SVAL(req->vwv+12, 0);
5352 8 : dscnt = SVAL(req->vwv+11, 0);
5353 8 : psoff = SVAL(req->vwv+10, 0);
5354 8 : pscnt = SVAL(req->vwv+9, 0);
5355 8 : tran_call = SVAL(req->vwv+14, 0);
5356 :
5357 8 : result = allow_new_trans(conn->pending_trans, req->mid);
5358 8 : if (!NT_STATUS_IS_OK(result)) {
5359 0 : DEBUG(2, ("Got invalid trans2 request: %s\n",
5360 : nt_errstr(result)));
5361 0 : reply_nterror(req, result);
5362 0 : END_PROFILE(SMBtrans2);
5363 0 : return;
5364 : }
5365 :
5366 8 : if (IS_IPC(conn)) {
5367 0 : switch (tran_call) {
5368 : /* List the allowed trans2 calls on IPC$ */
5369 0 : case TRANSACT2_OPEN:
5370 : case TRANSACT2_GET_DFS_REFERRAL:
5371 : case TRANSACT2_QFILEINFO:
5372 : case TRANSACT2_QFSINFO:
5373 : case TRANSACT2_SETFSINFO:
5374 0 : break;
5375 0 : default:
5376 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5377 0 : END_PROFILE(SMBtrans2);
5378 0 : return;
5379 : }
5380 : }
5381 :
5382 8 : if ((state = talloc(conn, struct trans_state)) == NULL) {
5383 0 : DEBUG(0, ("talloc failed\n"));
5384 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
5385 0 : END_PROFILE(SMBtrans2);
5386 0 : return;
5387 : }
5388 :
5389 8 : state->cmd = SMBtrans2;
5390 :
5391 8 : state->mid = req->mid;
5392 8 : state->vuid = req->vuid;
5393 8 : state->setup_count = SVAL(req->vwv+13, 0);
5394 8 : state->setup = NULL;
5395 8 : state->total_param = SVAL(req->vwv+0, 0);
5396 8 : state->param = NULL;
5397 8 : state->total_data = SVAL(req->vwv+1, 0);
5398 8 : state->data = NULL;
5399 8 : state->max_param_return = SVAL(req->vwv+2, 0);
5400 8 : state->max_data_return = SVAL(req->vwv+3, 0);
5401 8 : state->max_setup_return = SVAL(req->vwv+4, 0);
5402 8 : state->close_on_completion = BITSETW(req->vwv+5, 0);
5403 8 : state->one_way = BITSETW(req->vwv+5, 1);
5404 :
5405 8 : state->call = tran_call;
5406 :
5407 : /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5408 : is so as a sanity check */
5409 8 : if (state->setup_count != 1) {
5410 : /*
5411 : * Need to have rc=0 for ioctl to get job id for OS/2.
5412 : * Network printing will fail if function is not successful.
5413 : * Similar function in reply.c will be used if protocol
5414 : * is LANMAN1.0 instead of LM1.2X002.
5415 : * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5416 : * outbuf doesn't have to be set(only job id is used).
5417 : */
5418 0 : if ( (state->setup_count == 4)
5419 0 : && (tran_call == TRANSACT2_IOCTL)
5420 0 : && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
5421 0 : && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
5422 0 : DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5423 : } else {
5424 0 : DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5425 0 : DEBUG(2,("Transaction is %d\n",tran_call));
5426 0 : TALLOC_FREE(state);
5427 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5428 0 : END_PROFILE(SMBtrans2);
5429 0 : return;
5430 : }
5431 : }
5432 :
5433 8 : if ((dscnt > state->total_data) || (pscnt > state->total_param))
5434 0 : goto bad_param;
5435 :
5436 8 : if (state->total_data) {
5437 :
5438 0 : if (smb_buffer_oob(state->total_data, 0, dscnt)
5439 0 : || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
5440 0 : goto bad_param;
5441 : }
5442 :
5443 : /* Can't use talloc here, the core routines do realloc on the
5444 : * params and data. */
5445 0 : state->data = (char *)SMB_MALLOC(state->total_data);
5446 0 : if (state->data == NULL) {
5447 0 : DEBUG(0,("reply_trans2: data malloc fail for %u "
5448 : "bytes !\n", (unsigned int)state->total_data));
5449 0 : TALLOC_FREE(state);
5450 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
5451 0 : END_PROFILE(SMBtrans2);
5452 0 : return;
5453 : }
5454 :
5455 0 : memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
5456 : }
5457 :
5458 8 : if (state->total_param) {
5459 :
5460 8 : if (smb_buffer_oob(state->total_param, 0, pscnt)
5461 8 : || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
5462 0 : goto bad_param;
5463 : }
5464 :
5465 : /* Can't use talloc here, the core routines do realloc on the
5466 : * params and data. */
5467 8 : state->param = (char *)SMB_MALLOC(state->total_param);
5468 8 : if (state->param == NULL) {
5469 0 : DEBUG(0,("reply_trans: param malloc fail for %u "
5470 : "bytes !\n", (unsigned int)state->total_param));
5471 0 : SAFE_FREE(state->data);
5472 0 : TALLOC_FREE(state);
5473 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
5474 0 : END_PROFILE(SMBtrans2);
5475 0 : return;
5476 : }
5477 :
5478 8 : memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
5479 : }
5480 :
5481 8 : state->received_data = dscnt;
5482 8 : state->received_param = pscnt;
5483 :
5484 8 : if ((state->received_param == state->total_param) &&
5485 8 : (state->received_data == state->total_data)) {
5486 :
5487 8 : handle_trans2(conn, req, state);
5488 :
5489 8 : SAFE_FREE(state->data);
5490 8 : SAFE_FREE(state->param);
5491 8 : TALLOC_FREE(state);
5492 8 : END_PROFILE(SMBtrans2);
5493 8 : return;
5494 : }
5495 :
5496 0 : DLIST_ADD(conn->pending_trans, state);
5497 :
5498 : /* We need to send an interim response then receive the rest
5499 : of the parameter/data bytes */
5500 0 : reply_smb1_outbuf(req, 0, 0);
5501 0 : show_msg((char *)req->outbuf);
5502 0 : END_PROFILE(SMBtrans2);
5503 0 : return;
5504 :
5505 0 : bad_param:
5506 :
5507 0 : DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5508 0 : SAFE_FREE(state->data);
5509 0 : SAFE_FREE(state->param);
5510 0 : TALLOC_FREE(state);
5511 0 : END_PROFILE(SMBtrans2);
5512 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5513 : }
5514 :
5515 : /****************************************************************************
5516 : Reply to a SMBtranss2
5517 : ****************************************************************************/
5518 :
5519 0 : void reply_transs2(struct smb_request *req)
5520 : {
5521 0 : connection_struct *conn = req->conn;
5522 : unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5523 : struct trans_state *state;
5524 :
5525 0 : START_PROFILE(SMBtranss2);
5526 :
5527 0 : show_msg((const char *)req->inbuf);
5528 :
5529 : /* Windows clients expect all replies to
5530 : a transact secondary (SMBtranss2 0x33)
5531 : to have a command code of transact
5532 : (SMBtrans2 0x32). See bug #8989
5533 : and also [MS-CIFS] section 2.2.4.47.2
5534 : for details.
5535 : */
5536 0 : req->cmd = SMBtrans2;
5537 :
5538 0 : if (req->wct < 8) {
5539 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5540 0 : END_PROFILE(SMBtranss2);
5541 0 : return;
5542 : }
5543 :
5544 0 : for (state = conn->pending_trans; state != NULL;
5545 0 : state = state->next) {
5546 0 : if (state->mid == req->mid) {
5547 0 : break;
5548 : }
5549 : }
5550 :
5551 0 : if ((state == NULL) || (state->cmd != SMBtrans2)) {
5552 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5553 0 : END_PROFILE(SMBtranss2);
5554 0 : return;
5555 : }
5556 :
5557 : /* Revise state->total_param and state->total_data in case they have
5558 : changed downwards */
5559 :
5560 0 : if (SVAL(req->vwv+0, 0) < state->total_param)
5561 0 : state->total_param = SVAL(req->vwv+0, 0);
5562 0 : if (SVAL(req->vwv+1, 0) < state->total_data)
5563 0 : state->total_data = SVAL(req->vwv+1, 0);
5564 :
5565 0 : pcnt = SVAL(req->vwv+2, 0);
5566 0 : poff = SVAL(req->vwv+3, 0);
5567 0 : pdisp = SVAL(req->vwv+4, 0);
5568 :
5569 0 : dcnt = SVAL(req->vwv+5, 0);
5570 0 : doff = SVAL(req->vwv+6, 0);
5571 0 : ddisp = SVAL(req->vwv+7, 0);
5572 :
5573 0 : state->received_param += pcnt;
5574 0 : state->received_data += dcnt;
5575 :
5576 0 : if ((state->received_data > state->total_data) ||
5577 0 : (state->received_param > state->total_param))
5578 0 : goto bad_param;
5579 :
5580 0 : if (pcnt) {
5581 0 : if (smb_buffer_oob(state->total_param, pdisp, pcnt)
5582 0 : || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
5583 0 : goto bad_param;
5584 : }
5585 0 : memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
5586 : }
5587 :
5588 0 : if (dcnt) {
5589 0 : if (smb_buffer_oob(state->total_data, ddisp, dcnt)
5590 0 : || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
5591 0 : goto bad_param;
5592 : }
5593 0 : memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
5594 : }
5595 :
5596 0 : if ((state->received_param < state->total_param) ||
5597 0 : (state->received_data < state->total_data)) {
5598 0 : END_PROFILE(SMBtranss2);
5599 0 : return;
5600 : }
5601 :
5602 0 : handle_trans2(conn, req, state);
5603 :
5604 0 : DLIST_REMOVE(conn->pending_trans, state);
5605 0 : SAFE_FREE(state->data);
5606 0 : SAFE_FREE(state->param);
5607 0 : TALLOC_FREE(state);
5608 :
5609 0 : END_PROFILE(SMBtranss2);
5610 0 : return;
5611 :
5612 0 : bad_param:
5613 :
5614 0 : DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5615 0 : DLIST_REMOVE(conn->pending_trans, state);
5616 0 : SAFE_FREE(state->data);
5617 0 : SAFE_FREE(state->param);
5618 0 : TALLOC_FREE(state);
5619 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5620 0 : END_PROFILE(SMBtranss2);
5621 0 : return;
5622 : }
|