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 : 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 20 : 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 12 : 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 12 : 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 20 : 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 : 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 (fsp == NULL ||
300 0 : fsp->fsp_flags.is_pathref ||
301 0 : fsp_get_io_fd(fsp) == -1)
302 : {
303 0 : return NT_STATUS_INVALID_HANDLE;
304 : }
305 :
306 0 : if (total_data != POSIX_LOCK_DATA_SIZE) {
307 0 : return NT_STATUS_INVALID_PARAMETER;
308 : }
309 :
310 0 : switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
311 0 : case POSIX_LOCK_TYPE_READ:
312 0 : lock_type = READ_LOCK;
313 0 : break;
314 0 : case POSIX_LOCK_TYPE_WRITE:
315 : /* Return the right POSIX-mappable error code for files opened read-only. */
316 0 : if (!fsp->fsp_flags.can_write) {
317 0 : return NT_STATUS_INVALID_HANDLE;
318 : }
319 0 : lock_type = WRITE_LOCK;
320 0 : break;
321 0 : case POSIX_LOCK_TYPE_UNLOCK:
322 0 : lock_type = UNLOCK_LOCK;
323 0 : break;
324 0 : default:
325 0 : return NT_STATUS_INVALID_PARAMETER;
326 : }
327 :
328 0 : switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
329 0 : case POSIX_LOCK_FLAG_NOWAIT:
330 0 : blocking_lock = false;
331 0 : break;
332 0 : case POSIX_LOCK_FLAG_WAIT:
333 0 : blocking_lock = true;
334 0 : break;
335 0 : default:
336 0 : return NT_STATUS_INVALID_PARAMETER;
337 : }
338 :
339 0 : if (!lp_blocking_locks(SNUM(conn))) {
340 0 : blocking_lock = False;
341 : }
342 :
343 0 : smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
344 0 : offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
345 0 : ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
346 0 : count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
347 0 : ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
348 :
349 0 : DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
350 : "count = %"PRIu64", offset = %"PRIu64"\n",
351 : fsp_str_dbg(fsp),
352 : (unsigned int)lock_type,
353 : smblctx,
354 : count,
355 : offset);
356 :
357 0 : if (lock_type == UNLOCK_LOCK) {
358 0 : struct smbd_lock_element l = {
359 0 : .req_guid = smbd_request_guid(req, 0),
360 : .smblctx = smblctx,
361 : .brltype = UNLOCK_LOCK,
362 : .lock_flav = POSIX_LOCK,
363 : .offset = offset,
364 : .count = count,
365 : };
366 0 : status = smbd_do_unlocking(req, fsp, 1, &l);
367 0 : return status;
368 : }
369 :
370 0 : lck = talloc(req, struct smbd_lock_element);
371 0 : if (lck == NULL) {
372 0 : return NT_STATUS_NO_MEMORY;
373 : }
374 :
375 0 : *lck = (struct smbd_lock_element) {
376 0 : .req_guid = smbd_request_guid(req, 0),
377 : .smblctx = smblctx,
378 : .brltype = lock_type,
379 : .lock_flav = POSIX_LOCK,
380 : .count = count,
381 : .offset = offset,
382 : };
383 :
384 0 : subreq = smbd_smb1_do_locks_send(
385 : fsp,
386 0 : req->sconn->ev_ctx,
387 : &req,
388 : fsp,
389 : blocking_lock ? UINT32_MAX : 0,
390 : true, /* large_offset */
391 : 1,
392 : lck);
393 0 : if (subreq == NULL) {
394 0 : TALLOC_FREE(lck);
395 0 : return NT_STATUS_NO_MEMORY;
396 : }
397 0 : tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
398 0 : return NT_STATUS_EVENT_PENDING;
399 : }
400 :
401 0 : static void smb_set_posix_lock_done(struct tevent_req *subreq)
402 : {
403 0 : struct smb_request *req = NULL;
404 : NTSTATUS status;
405 : bool ok;
406 :
407 0 : ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
408 0 : SMB_ASSERT(ok);
409 :
410 0 : status = smbd_smb1_do_locks_recv(subreq);
411 0 : TALLOC_FREE(subreq);
412 :
413 0 : if (NT_STATUS_IS_OK(status)) {
414 0 : char params[2] = {0};
415 : /* Fake up max_data_bytes here - we know it fits. */
416 0 : send_trans2_replies(
417 0 : req->conn,
418 : req,
419 0 : NT_STATUS_OK,
420 : params,
421 : 2,
422 : NULL,
423 : 0,
424 : 0xffff);
425 : } else {
426 0 : reply_nterror(req, status);
427 0 : ok = smb1_srv_send(
428 0 : req->xconn,
429 0 : (char *)req->outbuf,
430 : true,
431 0 : req->seqnum+1,
432 0 : IS_CONN_ENCRYPTED(req->conn),
433 : NULL);
434 0 : if (!ok) {
435 0 : exit_server_cleanly("smb_set_posix_lock_done: "
436 : "smb1_srv_send failed.");
437 : }
438 : }
439 :
440 0 : TALLOC_FREE(req);
441 0 : return;
442 : }
443 :
444 : /****************************************************************************
445 : Read a list of EA names from an incoming data buffer. Create an ea_list with them.
446 : ****************************************************************************/
447 :
448 0 : static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
449 : {
450 0 : struct ea_list *ea_list_head = NULL;
451 0 : size_t converted_size, offset = 0;
452 :
453 0 : while (offset + 2 < data_size) {
454 0 : struct ea_list *eal = talloc_zero(ctx, struct ea_list);
455 0 : unsigned int namelen = CVAL(pdata,offset);
456 :
457 0 : offset++; /* Go past the namelen byte. */
458 :
459 : /* integer wrap paranioa. */
460 0 : if ((offset + namelen < offset) || (offset + namelen < namelen) ||
461 0 : (offset > data_size) || (namelen > data_size) ||
462 0 : (offset + namelen >= data_size)) {
463 : break;
464 : }
465 : /* Ensure the name is null terminated. */
466 0 : if (pdata[offset + namelen] != '\0') {
467 0 : return NULL;
468 : }
469 0 : if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
470 : &converted_size)) {
471 0 : DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
472 : "failed: %s", strerror(errno)));
473 : }
474 0 : if (!eal->ea.name) {
475 0 : return NULL;
476 : }
477 :
478 0 : offset += (namelen + 1); /* Go past the name + terminating zero. */
479 0 : DLIST_ADD_END(ea_list_head, eal);
480 0 : DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
481 : }
482 :
483 0 : return ea_list_head;
484 : }
485 :
486 : /****************************************************************************
487 : Reply to a TRANSACT2_OPEN.
488 : ****************************************************************************/
489 :
490 0 : static void call_trans2open(connection_struct *conn,
491 : struct smb_request *req,
492 : char **pparams, int total_params,
493 : char **ppdata, int total_data,
494 : unsigned int max_data_bytes)
495 : {
496 0 : struct smb_filename *smb_fname = NULL;
497 0 : char *params = *pparams;
498 0 : char *pdata = *ppdata;
499 : int deny_mode;
500 : int32_t open_attr;
501 : bool oplock_request;
502 : #if 0
503 : bool return_additional_info;
504 : int16 open_sattr;
505 : time_t open_time;
506 : #endif
507 : int open_ofun;
508 : uint32_t open_size;
509 : char *pname;
510 0 : char *fname = NULL;
511 0 : off_t size=0;
512 0 : int fattr=0,mtime=0;
513 0 : SMB_INO_T inode = 0;
514 0 : int smb_action = 0;
515 0 : struct files_struct *dirfsp = NULL;
516 : files_struct *fsp;
517 0 : struct ea_list *ea_list = NULL;
518 0 : uint16_t flags = 0;
519 : NTSTATUS status;
520 : uint32_t access_mask;
521 : uint32_t share_mode;
522 : uint32_t create_disposition;
523 0 : uint32_t create_options = 0;
524 0 : uint32_t private_flags = 0;
525 0 : NTTIME twrp = 0;
526 0 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
527 0 : TALLOC_CTX *ctx = talloc_tos();
528 :
529 : /*
530 : * Ensure we have enough parameters to perform the operation.
531 : */
532 :
533 0 : if (total_params < 29) {
534 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
535 0 : goto out;
536 : }
537 :
538 0 : flags = SVAL(params, 0);
539 0 : deny_mode = SVAL(params, 2);
540 0 : open_attr = SVAL(params,6);
541 0 : oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
542 0 : if (oplock_request) {
543 0 : oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
544 : }
545 :
546 : #if 0
547 : return_additional_info = BITSETW(params,0);
548 : open_sattr = SVAL(params, 4);
549 : open_time = make_unix_date3(params+8);
550 : #endif
551 0 : open_ofun = SVAL(params,12);
552 0 : open_size = IVAL(params,14);
553 0 : pname = ¶ms[28];
554 :
555 0 : if (IS_IPC(conn)) {
556 0 : reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
557 0 : goto out;
558 : }
559 :
560 0 : if (req->posix_pathnames) {
561 0 : srvstr_get_path_posix(ctx,
562 : params,
563 0 : req->flags2,
564 : &fname,
565 : pname,
566 0 : total_params - 28,
567 : STR_TERMINATE,
568 : &status);
569 : } else {
570 0 : srvstr_get_path(ctx,
571 : params,
572 0 : req->flags2,
573 : &fname,
574 : pname,
575 0 : total_params - 28,
576 : STR_TERMINATE,
577 : &status);
578 : }
579 0 : if (!NT_STATUS_IS_OK(status)) {
580 0 : reply_nterror(req, status);
581 0 : goto out;
582 : }
583 :
584 0 : DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
585 : fname, (unsigned int)deny_mode, (unsigned int)open_attr,
586 : (unsigned int)open_ofun, open_size));
587 :
588 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
589 0 : extract_snapshot_token(fname, &twrp);
590 : }
591 0 : status = filename_convert_dirfsp(ctx,
592 : conn,
593 : fname,
594 : ucf_flags,
595 : twrp,
596 : &dirfsp,
597 : &smb_fname);
598 0 : if (!NT_STATUS_IS_OK(status)) {
599 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
600 0 : reply_botherror(req,
601 : NT_STATUS_PATH_NOT_COVERED,
602 : ERRSRV, ERRbadpath);
603 0 : goto out;
604 : }
605 0 : reply_nterror(req, status);
606 0 : goto out;
607 : }
608 :
609 0 : if (open_ofun == 0) {
610 0 : reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
611 0 : goto out;
612 : }
613 :
614 0 : if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
615 : open_ofun,
616 : &access_mask, &share_mode,
617 : &create_disposition,
618 : &create_options,
619 : &private_flags)) {
620 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
621 0 : goto out;
622 : }
623 :
624 : /* Any data in this call is an EA list. */
625 0 : if (total_data && (total_data != 4)) {
626 0 : if (total_data < 10) {
627 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
628 0 : goto out;
629 : }
630 :
631 0 : if (IVAL(pdata,0) > total_data) {
632 0 : DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
633 : IVAL(pdata,0), (unsigned int)total_data));
634 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
635 0 : goto out;
636 : }
637 :
638 0 : ea_list = read_ea_list(talloc_tos(), pdata + 4,
639 0 : total_data - 4);
640 0 : if (!ea_list) {
641 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
642 0 : goto out;
643 : }
644 :
645 0 : if (!lp_ea_support(SNUM(conn))) {
646 0 : reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
647 0 : goto out;
648 : }
649 :
650 0 : if (!req->posix_pathnames &&
651 0 : ea_list_has_invalid_name(ea_list)) {
652 0 : int param_len = 30;
653 0 : *pparams = (char *)SMB_REALLOC(*pparams, param_len);
654 0 : if(*pparams == NULL ) {
655 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
656 0 : goto out;
657 : }
658 0 : params = *pparams;
659 0 : memset(params, '\0', param_len);
660 0 : send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
661 : params, param_len, NULL, 0, max_data_bytes);
662 0 : goto out;
663 : }
664 : }
665 :
666 0 : status = SMB_VFS_CREATE_FILE(
667 : conn, /* conn */
668 : req, /* req */
669 : dirfsp, /* dirfsp */
670 : smb_fname, /* fname */
671 : access_mask, /* access_mask */
672 : share_mode, /* share_access */
673 : create_disposition, /* create_disposition*/
674 : create_options, /* create_options */
675 : open_attr, /* file_attributes */
676 : oplock_request, /* oplock_request */
677 : NULL, /* lease */
678 : open_size, /* allocation_size */
679 : private_flags,
680 : NULL, /* sd */
681 : ea_list, /* ea_list */
682 : &fsp, /* result */
683 : &smb_action, /* psbuf */
684 : NULL, NULL); /* create context */
685 :
686 0 : if (!NT_STATUS_IS_OK(status)) {
687 0 : if (open_was_deferred(req->xconn, req->mid)) {
688 : /* We have re-scheduled this call. */
689 0 : goto out;
690 : }
691 :
692 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
693 0 : reply_openerror(req, status);
694 0 : goto out;
695 : }
696 :
697 0 : fsp = fcb_or_dos_open(
698 : req,
699 : smb_fname,
700 : access_mask,
701 : create_options,
702 : private_flags);
703 0 : if (fsp == NULL) {
704 0 : bool ok = defer_smb1_sharing_violation(req);
705 0 : if (ok) {
706 0 : goto out;
707 : }
708 0 : reply_openerror(req, status);
709 0 : goto out;
710 : }
711 :
712 0 : smb_action = FILE_WAS_OPENED;
713 : }
714 :
715 0 : size = get_file_size_stat(&smb_fname->st);
716 0 : fattr = fdos_mode(fsp);
717 0 : mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
718 0 : inode = smb_fname->st.st_ex_ino;
719 0 : if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
720 0 : close_file_free(req, &fsp, ERROR_CLOSE);
721 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
722 0 : goto out;
723 : }
724 :
725 : /* Realloc the size of parameters and data we will return */
726 0 : *pparams = (char *)SMB_REALLOC(*pparams, 30);
727 0 : if(*pparams == NULL ) {
728 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
729 0 : goto out;
730 : }
731 0 : params = *pparams;
732 :
733 0 : SSVAL(params,0,fsp->fnum);
734 0 : SSVAL(params,2,fattr);
735 0 : srv_put_dos_date2(params,4, mtime);
736 0 : SIVAL(params,8, (uint32_t)size);
737 0 : SSVAL(params,12,deny_mode);
738 0 : SSVAL(params,14,0); /* open_type - file or directory. */
739 0 : SSVAL(params,16,0); /* open_state - only valid for IPC device. */
740 :
741 0 : if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
742 0 : smb_action |= EXTENDED_OPLOCK_GRANTED;
743 : }
744 :
745 0 : SSVAL(params,18,smb_action);
746 :
747 : /*
748 : * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
749 : */
750 0 : SIVAL(params,20,inode);
751 0 : SSVAL(params,24,0); /* Padding. */
752 0 : if (flags & 8) {
753 0 : uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
754 0 : SIVAL(params, 26, ea_size);
755 : } else {
756 0 : SIVAL(params, 26, 0);
757 : }
758 :
759 : /* Send the required number of replies */
760 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
761 0 : out:
762 0 : TALLOC_FREE(smb_fname);
763 0 : }
764 :
765 0 : static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
766 : connection_struct *conn,
767 : struct dptr_struct *dirptr,
768 : uint16_t flags2,
769 : const char *path_mask,
770 : uint32_t dirtype,
771 : int info_level,
772 : bool requires_resume_key,
773 : bool dont_descend,
774 : bool ask_sharemode,
775 : char **ppdata,
776 : char *base_data,
777 : char *end_data,
778 : int space_remaining,
779 : bool *got_exact_match,
780 : int *last_entry_off,
781 : struct ea_list *name_list)
782 : {
783 0 : uint8_t align = 4;
784 0 : const bool do_pad = true;
785 :
786 0 : if (info_level >= 1 && info_level <= 3) {
787 : /* No alignment on earlier info levels. */
788 0 : align = 1;
789 : }
790 :
791 0 : return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
792 : path_mask, dirtype, info_level,
793 : requires_resume_key, dont_descend, ask_sharemode,
794 : true, align, do_pad,
795 : ppdata, base_data, end_data,
796 : space_remaining,
797 : NULL,
798 : got_exact_match,
799 : last_entry_off, name_list, NULL);
800 : }
801 :
802 : /****************************************************************************
803 : Reply to a TRANS2_FINDFIRST.
804 : ****************************************************************************/
805 :
806 0 : static void call_trans2findfirst(connection_struct *conn,
807 : struct smb_request *req,
808 : char **pparams, int total_params,
809 : char **ppdata, int total_data,
810 : unsigned int max_data_bytes)
811 : {
812 : /* We must be careful here that we don't return more than the
813 : allowed number of data bytes. If this means returning fewer than
814 : maxentries then so be it. We assume that the redirector has
815 : enough room for the fixed number of parameter bytes it has
816 : requested. */
817 0 : struct smb_filename *smb_dname = NULL;
818 0 : char *params = *pparams;
819 0 : char *pdata = *ppdata;
820 : char *data_end;
821 : uint32_t dirtype;
822 : int maxentries;
823 : uint16_t findfirst_flags;
824 : bool close_after_first;
825 : bool close_if_end;
826 : bool requires_resume_key;
827 : int info_level;
828 0 : char *directory = NULL;
829 0 : char *mask = NULL;
830 : char *p;
831 0 : int last_entry_off=0;
832 0 : int dptr_num = -1;
833 0 : int numentries = 0;
834 : int i;
835 0 : bool finished = False;
836 0 : bool dont_descend = False;
837 0 : bool out_of_space = False;
838 : int space_remaining;
839 0 : struct ea_list *ea_list = NULL;
840 0 : NTSTATUS ntstatus = NT_STATUS_OK;
841 0 : bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
842 0 : struct smbd_server_connection *sconn = req->sconn;
843 0 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
844 0 : bool backup_priv = false;
845 0 : bool as_root = false;
846 0 : files_struct *fsp = NULL;
847 0 : struct files_struct *dirfsp = NULL;
848 0 : const struct loadparm_substitution *lp_sub =
849 0 : loadparm_s3_global_substitution();
850 :
851 0 : if (total_params < 13) {
852 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
853 0 : goto out;
854 : }
855 :
856 0 : dirtype = SVAL(params,0);
857 0 : maxentries = SVAL(params,2);
858 0 : findfirst_flags = SVAL(params,4);
859 0 : close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
860 0 : close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
861 0 : requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
862 0 : backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
863 0 : security_token_has_privilege(get_current_nttok(conn),
864 : SEC_PRIV_BACKUP));
865 :
866 0 : info_level = SVAL(params,6);
867 :
868 0 : DBG_NOTICE("dirtype = %"PRIx32", maxentries = %d, "
869 : "close_after_first=%d, close_if_end = %d "
870 : "requires_resume_key = %d backup_priv = %d level = 0x%x, "
871 : "max_data_bytes = %d\n",
872 : dirtype,
873 : maxentries,
874 : close_after_first,
875 : close_if_end,
876 : requires_resume_key,
877 : backup_priv,
878 : info_level,
879 : max_data_bytes);
880 :
881 0 : if (!maxentries) {
882 : /* W2K3 seems to treat zero as 1. */
883 0 : maxentries = 1;
884 : }
885 :
886 0 : switch (info_level) {
887 0 : case SMB_FIND_INFO_STANDARD:
888 : case SMB_FIND_EA_SIZE:
889 : case SMB_FIND_EA_LIST:
890 : case SMB_FIND_FILE_DIRECTORY_INFO:
891 : case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
892 : case SMB_FIND_FILE_NAMES_INFO:
893 : case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
894 : case SMB_FIND_ID_FULL_DIRECTORY_INFO:
895 : case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
896 0 : break;
897 0 : case SMB_FIND_FILE_UNIX:
898 : case SMB_FIND_FILE_UNIX_INFO2:
899 0 : if (!lp_smb1_unix_extensions()) {
900 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
901 0 : goto out;
902 : }
903 0 : if (!req->posix_pathnames) {
904 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
905 0 : goto out;
906 : }
907 0 : break;
908 0 : default:
909 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
910 0 : goto out;
911 : }
912 :
913 0 : if (req->posix_pathnames) {
914 : /* Always use filesystem for UNIX mtime query. */
915 0 : ask_sharemode = false;
916 : }
917 :
918 0 : if (req->posix_pathnames) {
919 0 : srvstr_get_path_posix(talloc_tos(),
920 : params,
921 0 : req->flags2,
922 : &directory,
923 0 : params+12,
924 0 : total_params - 12,
925 : STR_TERMINATE,
926 : &ntstatus);
927 : } else {
928 0 : srvstr_get_path(talloc_tos(),
929 : params,
930 0 : req->flags2,
931 : &directory,
932 0 : params+12,
933 0 : total_params - 12,
934 : STR_TERMINATE,
935 : &ntstatus);
936 : }
937 0 : if (!NT_STATUS_IS_OK(ntstatus)) {
938 0 : reply_nterror(req, ntstatus);
939 0 : goto out;
940 : }
941 :
942 0 : if (backup_priv) {
943 0 : become_root();
944 0 : as_root = true;
945 : }
946 0 : ntstatus = filename_convert_smb1_search_path(talloc_tos(),
947 : conn,
948 : directory,
949 : ucf_flags,
950 : &dirfsp,
951 : &smb_dname,
952 : &mask);
953 :
954 0 : if (!NT_STATUS_IS_OK(ntstatus)) {
955 0 : if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
956 0 : reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
957 : ERRSRV, ERRbadpath);
958 0 : goto out;
959 : }
960 0 : reply_nterror(req, ntstatus);
961 0 : goto out;
962 : }
963 :
964 0 : TALLOC_FREE(directory);
965 0 : directory = smb_dname->base_name;
966 :
967 0 : DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
968 :
969 0 : if (info_level == SMB_FIND_EA_LIST) {
970 : uint32_t ea_size;
971 :
972 0 : if (total_data < 4) {
973 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
974 0 : goto out;
975 : }
976 :
977 0 : ea_size = IVAL(pdata,0);
978 0 : if (ea_size != total_data) {
979 0 : DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
980 : total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
981 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 0 : goto out;
983 : }
984 :
985 0 : if (!lp_ea_support(SNUM(conn))) {
986 0 : reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
987 0 : goto out;
988 : }
989 :
990 : /* Pull out the list of names. */
991 0 : ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
992 0 : if (!ea_list) {
993 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
994 0 : goto out;
995 : }
996 : }
997 :
998 0 : if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
999 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1000 0 : goto out;
1001 : }
1002 :
1003 0 : *ppdata = (char *)SMB_REALLOC(
1004 : *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1005 0 : if(*ppdata == NULL ) {
1006 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1007 0 : goto out;
1008 : }
1009 0 : pdata = *ppdata;
1010 0 : data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1011 : /*
1012 : * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1013 : * error.
1014 : */
1015 0 : memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
1016 : /* Realloc the params space */
1017 0 : *pparams = (char *)SMB_REALLOC(*pparams, 10);
1018 0 : if (*pparams == NULL) {
1019 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1020 0 : goto out;
1021 : }
1022 0 : params = *pparams;
1023 :
1024 : /*
1025 : * Open an fsp on this directory for the dptr.
1026 : */
1027 0 : ntstatus = SMB_VFS_CREATE_FILE(
1028 : conn, /* conn */
1029 : req, /* req */
1030 : dirfsp, /* dirfsp */
1031 : smb_dname, /* dname */
1032 : FILE_LIST_DIRECTORY, /* access_mask */
1033 : FILE_SHARE_READ|
1034 : FILE_SHARE_WRITE, /* share_access */
1035 : FILE_OPEN, /* create_disposition*/
1036 : FILE_DIRECTORY_FILE, /* create_options */
1037 : FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1038 : NO_OPLOCK, /* oplock_request */
1039 : NULL, /* lease */
1040 : 0, /* allocation_size */
1041 : 0, /* private_flags */
1042 : NULL, /* sd */
1043 : NULL, /* ea_list */
1044 : &fsp, /* result */
1045 : NULL, /* pinfo */
1046 : NULL, /* in_context */
1047 : NULL);/* out_context */
1048 :
1049 0 : if (!NT_STATUS_IS_OK(ntstatus)) {
1050 0 : DBG_ERR("failed to open directory %s\n",
1051 : smb_fname_str_dbg(smb_dname));
1052 0 : reply_nterror(req, ntstatus);
1053 0 : goto out;
1054 : }
1055 :
1056 : /* Save the wildcard match and attribs we are using on this directory -
1057 : needed as lanman2 assumes these are being saved between calls */
1058 :
1059 0 : ntstatus = dptr_create(conn,
1060 : req,
1061 : fsp, /* fsp */
1062 : False,
1063 : True,
1064 0 : req->smbpid,
1065 : mask,
1066 : dirtype,
1067 0 : &fsp->dptr);
1068 :
1069 0 : if (!NT_STATUS_IS_OK(ntstatus)) {
1070 : /*
1071 : * Use NULL here for the first parameter (req)
1072 : * as this is not a client visible handle so
1073 : * can'tbe part of an SMB1 chain.
1074 : */
1075 0 : close_file_free(NULL, &fsp, NORMAL_CLOSE);
1076 0 : reply_nterror(req, ntstatus);
1077 0 : goto out;
1078 : }
1079 :
1080 0 : if (backup_priv) {
1081 : /* Remember this in case we have
1082 : to do a findnext. */
1083 0 : dptr_set_priv(fsp->dptr);
1084 : }
1085 :
1086 0 : dptr_num = dptr_dnum(fsp->dptr);
1087 0 : DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1088 :
1089 : /* We don't need to check for VOL here as this is returned by
1090 : a different TRANS2 call. */
1091 :
1092 0 : DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1093 : directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
1094 0 : if (in_list(directory,
1095 0 : lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
1096 0 : dptr_case_sensitive(fsp->dptr))) {
1097 0 : dont_descend = True;
1098 : }
1099 :
1100 0 : p = pdata;
1101 0 : space_remaining = max_data_bytes;
1102 0 : out_of_space = False;
1103 :
1104 0 : for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1105 0 : bool got_exact_match = False;
1106 :
1107 : /* this is a heuristic to avoid seeking the dirptr except when
1108 : absolutely necessary. It allows for a filename of about 40 chars */
1109 0 : if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1110 0 : out_of_space = True;
1111 0 : finished = False;
1112 : } else {
1113 0 : ntstatus = get_lanman2_dir_entry(talloc_tos(),
1114 : conn,
1115 0 : fsp->dptr,
1116 0 : req->flags2,
1117 : mask,dirtype,info_level,
1118 : requires_resume_key,dont_descend,
1119 : ask_sharemode,
1120 : &p,pdata,data_end,
1121 : space_remaining,
1122 : &got_exact_match,
1123 : &last_entry_off, ea_list);
1124 0 : if (NT_STATUS_EQUAL(ntstatus,
1125 : NT_STATUS_ILLEGAL_CHARACTER)) {
1126 : /*
1127 : * Bad character conversion on name. Ignore this
1128 : * entry.
1129 : */
1130 0 : continue;
1131 : }
1132 0 : if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1133 0 : out_of_space = true;
1134 : } else {
1135 0 : finished = !NT_STATUS_IS_OK(ntstatus);
1136 : }
1137 : }
1138 :
1139 0 : if (!finished && !out_of_space)
1140 0 : numentries++;
1141 :
1142 : /*
1143 : * As an optimisation if we know we aren't looking
1144 : * for a wildcard name (ie. the name matches the wildcard exactly)
1145 : * then we can finish on any (first) match.
1146 : * This speeds up large directory searches. JRA.
1147 : */
1148 :
1149 0 : if(got_exact_match)
1150 0 : finished = True;
1151 :
1152 : /* Ensure space_remaining never goes -ve. */
1153 0 : if (PTR_DIFF(p,pdata) > max_data_bytes) {
1154 0 : space_remaining = 0;
1155 0 : out_of_space = true;
1156 : } else {
1157 0 : space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1158 : }
1159 : }
1160 :
1161 : /* Check if we can close the dirptr */
1162 0 : if(close_after_first || (finished && close_if_end)) {
1163 0 : DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1164 0 : dptr_num = -1;
1165 0 : close_file_free(NULL, &fsp, NORMAL_CLOSE);
1166 : }
1167 :
1168 : /*
1169 : * If there are no matching entries we must return ERRDOS/ERRbadfile -
1170 : * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1171 : * the protocol level is less than NT1. Tested with smbclient. JRA.
1172 : * This should fix the OS/2 client bug #2335.
1173 : */
1174 :
1175 0 : if(numentries == 0) {
1176 0 : dptr_num = -1;
1177 : /*
1178 : * We may have already closed the file in the
1179 : * close_after_first or finished case above.
1180 : */
1181 0 : if (fsp != NULL) {
1182 0 : close_file_free(NULL, &fsp, NORMAL_CLOSE);
1183 : }
1184 0 : if (get_Protocol() < PROTOCOL_NT1) {
1185 0 : reply_force_doserror(req, ERRDOS, ERRnofiles);
1186 0 : goto out;
1187 : } else {
1188 0 : reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
1189 : ERRDOS, ERRbadfile);
1190 0 : goto out;
1191 : }
1192 : }
1193 :
1194 : /* At this point pdata points to numentries directory entries. */
1195 :
1196 : /* Set up the return parameter block */
1197 0 : SSVAL(params,0,dptr_num);
1198 0 : SSVAL(params,2,numentries);
1199 0 : SSVAL(params,4,finished);
1200 0 : SSVAL(params,6,0); /* Never an EA error */
1201 0 : SSVAL(params,8,last_entry_off);
1202 :
1203 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
1204 : max_data_bytes);
1205 :
1206 0 : if ((! *directory) && dptr_path(sconn, dptr_num)) {
1207 0 : directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
1208 0 : if (!directory) {
1209 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1210 : }
1211 : }
1212 :
1213 0 : DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1214 : smb_fn_name(req->cmd),
1215 : mask, directory, dirtype, numentries ) );
1216 :
1217 : /*
1218 : * Force a name mangle here to ensure that the
1219 : * mask as an 8.3 name is top of the mangled cache.
1220 : * The reasons for this are subtle. Don't remove
1221 : * this code unless you know what you are doing
1222 : * (see PR#13758). JRA.
1223 : */
1224 :
1225 0 : if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
1226 : char mangled_name[13];
1227 0 : name_to_8_3(mask, mangled_name, True, conn->params);
1228 : }
1229 0 : out:
1230 :
1231 0 : if (as_root) {
1232 0 : unbecome_root();
1233 : }
1234 :
1235 0 : TALLOC_FREE(smb_dname);
1236 0 : return;
1237 : }
1238 :
1239 : /****************************************************************************
1240 : Reply to a TRANS2_FINDNEXT.
1241 : ****************************************************************************/
1242 :
1243 0 : static void call_trans2findnext(connection_struct *conn,
1244 : struct smb_request *req,
1245 : char **pparams, int total_params,
1246 : char **ppdata, int total_data,
1247 : unsigned int max_data_bytes)
1248 : {
1249 : /* We must be careful here that we don't return more than the
1250 : allowed number of data bytes. If this means returning fewer than
1251 : maxentries then so be it. We assume that the redirector has
1252 : enough room for the fixed number of parameter bytes it has
1253 : requested. */
1254 0 : char *params = *pparams;
1255 0 : char *pdata = *ppdata;
1256 : char *data_end;
1257 : int dptr_num;
1258 : int maxentries;
1259 : uint16_t info_level;
1260 : uint32_t resume_key;
1261 : uint16_t findnext_flags;
1262 : bool close_after_request;
1263 : bool close_if_end;
1264 : bool requires_resume_key;
1265 : bool continue_bit;
1266 0 : char *resume_name = NULL;
1267 0 : const char *mask = NULL;
1268 0 : const char *directory = NULL;
1269 0 : char *p = NULL;
1270 : uint16_t dirtype;
1271 0 : int numentries = 0;
1272 0 : int i, last_entry_off=0;
1273 0 : bool finished = False;
1274 0 : bool dont_descend = False;
1275 0 : bool out_of_space = False;
1276 : int space_remaining;
1277 0 : struct ea_list *ea_list = NULL;
1278 0 : NTSTATUS ntstatus = NT_STATUS_OK;
1279 0 : bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1280 0 : TALLOC_CTX *ctx = talloc_tos();
1281 0 : struct smbd_server_connection *sconn = req->sconn;
1282 0 : bool backup_priv = false;
1283 0 : bool as_root = false;
1284 0 : files_struct *fsp = NULL;
1285 0 : const struct loadparm_substitution *lp_sub =
1286 0 : loadparm_s3_global_substitution();
1287 :
1288 0 : if (total_params < 13) {
1289 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1290 0 : return;
1291 : }
1292 :
1293 0 : dptr_num = SVAL(params,0);
1294 0 : maxentries = SVAL(params,2);
1295 0 : info_level = SVAL(params,4);
1296 0 : resume_key = IVAL(params,6);
1297 0 : findnext_flags = SVAL(params,10);
1298 0 : close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1299 0 : close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1300 0 : requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1301 0 : continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1302 :
1303 0 : if (!continue_bit) {
1304 : /* We only need resume_name if continue_bit is zero. */
1305 0 : if (req->posix_pathnames) {
1306 0 : srvstr_get_path_posix(ctx,
1307 : params,
1308 0 : req->flags2,
1309 : &resume_name,
1310 0 : params+12,
1311 0 : total_params - 12,
1312 : STR_TERMINATE,
1313 : &ntstatus);
1314 : } else {
1315 0 : srvstr_get_path(ctx,
1316 : params,
1317 0 : req->flags2,
1318 : &resume_name,
1319 0 : params+12,
1320 0 : total_params - 12,
1321 : STR_TERMINATE,
1322 : &ntstatus);
1323 : }
1324 0 : if (!NT_STATUS_IS_OK(ntstatus)) {
1325 : /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1326 : complain (it thinks we're asking for the directory above the shared
1327 : path or an invalid name). Catch this as the resume name is only compared, never used in
1328 : a file access. JRA. */
1329 0 : srvstr_pull_talloc(ctx, params, req->flags2,
1330 : &resume_name, params+12,
1331 : total_params - 12,
1332 : STR_TERMINATE);
1333 :
1334 0 : if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
1335 0 : reply_nterror(req, ntstatus);
1336 0 : return;
1337 : }
1338 : }
1339 : }
1340 :
1341 0 : DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1342 : close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1343 : resume_key = %d resume name = %s continue=%d level = %d\n",
1344 : dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1345 : requires_resume_key, resume_key,
1346 : resume_name ? resume_name : "(NULL)", continue_bit, info_level));
1347 :
1348 0 : if (!maxentries) {
1349 : /* W2K3 seems to treat zero as 1. */
1350 0 : maxentries = 1;
1351 : }
1352 :
1353 0 : switch (info_level) {
1354 0 : case SMB_FIND_INFO_STANDARD:
1355 : case SMB_FIND_EA_SIZE:
1356 : case SMB_FIND_EA_LIST:
1357 : case SMB_FIND_FILE_DIRECTORY_INFO:
1358 : case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1359 : case SMB_FIND_FILE_NAMES_INFO:
1360 : case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1361 : case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1362 : case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1363 0 : break;
1364 0 : case SMB_FIND_FILE_UNIX:
1365 : case SMB_FIND_FILE_UNIX_INFO2:
1366 : /* Always use filesystem for UNIX mtime query. */
1367 0 : ask_sharemode = false;
1368 0 : if (!lp_smb1_unix_extensions()) {
1369 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1370 0 : return;
1371 : }
1372 0 : if (!req->posix_pathnames) {
1373 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1374 0 : return;
1375 : }
1376 0 : break;
1377 0 : default:
1378 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1379 0 : return;
1380 : }
1381 :
1382 0 : if (info_level == SMB_FIND_EA_LIST) {
1383 : uint32_t ea_size;
1384 :
1385 0 : if (total_data < 4) {
1386 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1387 0 : return;
1388 : }
1389 :
1390 0 : ea_size = IVAL(pdata,0);
1391 0 : if (ea_size != total_data) {
1392 0 : DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1393 : total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1394 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1395 0 : return;
1396 : }
1397 :
1398 0 : if (!lp_ea_support(SNUM(conn))) {
1399 0 : reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1400 0 : return;
1401 : }
1402 :
1403 : /* Pull out the list of names. */
1404 0 : ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1405 0 : if (!ea_list) {
1406 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1407 0 : return;
1408 : }
1409 : }
1410 :
1411 0 : if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1412 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1413 0 : return;
1414 : }
1415 :
1416 0 : *ppdata = (char *)SMB_REALLOC(
1417 : *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1418 0 : if(*ppdata == NULL) {
1419 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1420 0 : return;
1421 : }
1422 :
1423 0 : pdata = *ppdata;
1424 0 : data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1425 :
1426 : /*
1427 : * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
1428 : * error.
1429 : */
1430 0 : memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
1431 : /* Realloc the params space */
1432 0 : *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1433 0 : if(*pparams == NULL ) {
1434 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1435 0 : return;
1436 : }
1437 :
1438 0 : params = *pparams;
1439 :
1440 : /* Check that the dptr is valid */
1441 0 : fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1442 0 : if (fsp == NULL) {
1443 0 : reply_nterror(req, STATUS_NO_MORE_FILES);
1444 0 : return;
1445 : }
1446 :
1447 0 : directory = dptr_path(sconn, dptr_num);
1448 :
1449 : /* Get the wildcard mask from the dptr */
1450 0 : if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
1451 0 : DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1452 0 : reply_nterror(req, STATUS_NO_MORE_FILES);
1453 0 : return;
1454 : }
1455 :
1456 : /* Get the attr mask from the dptr */
1457 0 : dirtype = dptr_attr(sconn, dptr_num);
1458 :
1459 0 : backup_priv = dptr_get_priv(fsp->dptr);
1460 :
1461 0 : DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
1462 : "backup_priv = %d\n",
1463 : dptr_num, mask, dirtype,
1464 : (long)fsp->dptr,
1465 : dptr_TellDir(fsp->dptr),
1466 : (int)backup_priv));
1467 :
1468 : /* We don't need to check for VOL here as this is returned by
1469 : a different TRANS2 call. */
1470 :
1471 0 : DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1472 : directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1473 0 : if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),
1474 0 : dptr_case_sensitive(fsp->dptr)))
1475 0 : dont_descend = True;
1476 :
1477 0 : p = pdata;
1478 0 : space_remaining = max_data_bytes;
1479 0 : out_of_space = False;
1480 :
1481 0 : if (backup_priv) {
1482 0 : become_root();
1483 0 : as_root = true;
1484 : }
1485 :
1486 : /*
1487 : * Seek to the correct position. We no longer use the resume key but
1488 : * depend on the last file name instead.
1489 : */
1490 :
1491 0 : if(!continue_bit && resume_name && *resume_name) {
1492 : SMB_STRUCT_STAT st;
1493 0 : bool posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
1494 :
1495 0 : long current_pos = 0;
1496 : /*
1497 : * Remember, name_to_8_3 is called by
1498 : * get_lanman2_dir_entry(), so the resume name
1499 : * could be mangled. Ensure we check the unmangled name.
1500 : */
1501 :
1502 0 : if (!posix_open &&
1503 0 : mangle_is_mangled(resume_name, conn->params)) {
1504 0 : char *new_resume_name = NULL;
1505 0 : mangle_lookup_name_from_8_3(ctx,
1506 : resume_name,
1507 : &new_resume_name,
1508 0 : conn->params);
1509 0 : if (new_resume_name) {
1510 0 : resume_name = new_resume_name;
1511 : }
1512 : }
1513 :
1514 : /*
1515 : * Fix for NT redirector problem triggered by resume key indexes
1516 : * changing between directory scans. We now return a resume key of 0
1517 : * and instead look for the filename to continue from (also given
1518 : * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1519 : * findfirst/findnext (as is usual) then the directory pointer
1520 : * should already be at the correct place.
1521 : */
1522 :
1523 0 : finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
1524 : } /* end if resume_name && !continue_bit */
1525 :
1526 0 : for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1527 0 : bool got_exact_match = False;
1528 :
1529 : /* this is a heuristic to avoid seeking the fsp->dptr except when
1530 : absolutely necessary. It allows for a filename of about 40 chars */
1531 0 : if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1532 0 : out_of_space = True;
1533 0 : finished = False;
1534 : } else {
1535 0 : ntstatus = get_lanman2_dir_entry(ctx,
1536 : conn,
1537 0 : fsp->dptr,
1538 0 : req->flags2,
1539 : mask,dirtype,info_level,
1540 : requires_resume_key,dont_descend,
1541 : ask_sharemode,
1542 : &p,pdata,data_end,
1543 : space_remaining,
1544 : &got_exact_match,
1545 : &last_entry_off, ea_list);
1546 0 : if (NT_STATUS_EQUAL(ntstatus,
1547 : NT_STATUS_ILLEGAL_CHARACTER)) {
1548 : /*
1549 : * Bad character conversion on name. Ignore this
1550 : * entry.
1551 : */
1552 0 : continue;
1553 : }
1554 0 : if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
1555 0 : out_of_space = true;
1556 : } else {
1557 0 : finished = !NT_STATUS_IS_OK(ntstatus);
1558 : }
1559 : }
1560 :
1561 0 : if (!finished && !out_of_space)
1562 0 : numentries++;
1563 :
1564 : /*
1565 : * As an optimisation if we know we aren't looking
1566 : * for a wildcard name (ie. the name matches the wildcard exactly)
1567 : * then we can finish on any (first) match.
1568 : * This speeds up large directory searches. JRA.
1569 : */
1570 :
1571 0 : if(got_exact_match)
1572 0 : finished = True;
1573 :
1574 0 : space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1575 : }
1576 :
1577 0 : DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1578 : smb_fn_name(req->cmd),
1579 : mask, directory, dirtype, numentries ) );
1580 :
1581 : /* Check if we can close the fsp->dptr */
1582 0 : if(close_after_request || (finished && close_if_end)) {
1583 0 : DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1584 0 : dptr_num = -1;
1585 0 : close_file_free(NULL, &fsp, NORMAL_CLOSE);
1586 : }
1587 :
1588 0 : if (as_root) {
1589 0 : unbecome_root();
1590 : }
1591 :
1592 : /* Set up the return parameter block */
1593 0 : SSVAL(params,0,numentries);
1594 0 : SSVAL(params,2,finished);
1595 0 : SSVAL(params,4,0); /* Never an EA error */
1596 0 : SSVAL(params,6,last_entry_off);
1597 :
1598 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
1599 : max_data_bytes);
1600 :
1601 0 : return;
1602 : }
1603 :
1604 : /****************************************************************************
1605 : Reply to a TRANS2_QFSINFO (query filesystem info).
1606 : ****************************************************************************/
1607 :
1608 8 : static void call_trans2qfsinfo(connection_struct *conn,
1609 : struct smb_request *req,
1610 : char **pparams, int total_params,
1611 : char **ppdata, int total_data,
1612 : unsigned int max_data_bytes)
1613 : {
1614 8 : char *params = *pparams;
1615 : uint16_t info_level;
1616 8 : int data_len = 0;
1617 : size_t fixed_portion;
1618 : NTSTATUS status;
1619 :
1620 8 : if (total_params < 2) {
1621 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1622 0 : return;
1623 : }
1624 :
1625 8 : info_level = SVAL(params,0);
1626 :
1627 8 : if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1628 0 : if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
1629 0 : DEBUG(0,("call_trans2qfsinfo: encryption required "
1630 : "and info level 0x%x sent.\n",
1631 : (unsigned int)info_level));
1632 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1633 0 : return;
1634 : }
1635 : }
1636 :
1637 8 : DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1638 :
1639 8 : status = smbd_do_qfsinfo(req->xconn, conn, req,
1640 : info_level,
1641 8 : req->flags2,
1642 : max_data_bytes,
1643 : &fixed_portion,
1644 : NULL,
1645 : ppdata, &data_len);
1646 8 : if (!NT_STATUS_IS_OK(status)) {
1647 0 : reply_nterror(req, status);
1648 0 : return;
1649 : }
1650 :
1651 8 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
1652 : max_data_bytes);
1653 :
1654 8 : DEBUG( 4, ( "%s info_level = %d\n",
1655 : smb_fn_name(req->cmd), info_level) );
1656 :
1657 8 : return;
1658 : }
1659 :
1660 : /****************************************************************************
1661 : Reply to a TRANS2_SETFSINFO (set filesystem info).
1662 : ****************************************************************************/
1663 :
1664 0 : static void call_trans2setfsinfo(connection_struct *conn,
1665 : struct smb_request *req,
1666 : char **pparams, int total_params,
1667 : char **ppdata, int total_data,
1668 : unsigned int max_data_bytes)
1669 : {
1670 0 : const struct loadparm_substitution *lp_sub =
1671 0 : loadparm_s3_global_substitution();
1672 0 : struct smbXsrv_connection *xconn = req->xconn;
1673 0 : char *pdata = *ppdata;
1674 0 : char *params = *pparams;
1675 : uint16_t info_level;
1676 :
1677 0 : DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
1678 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
1679 :
1680 : /* */
1681 0 : if (total_params < 4) {
1682 0 : DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1683 : total_params));
1684 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1685 0 : return;
1686 : }
1687 :
1688 0 : info_level = SVAL(params,2);
1689 :
1690 0 : if (IS_IPC(conn)) {
1691 0 : if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
1692 : info_level != SMB_SET_CIFS_UNIX_INFO) {
1693 0 : DEBUG(0,("call_trans2setfsinfo: not an allowed "
1694 : "info level (0x%x) on IPC$.\n",
1695 : (unsigned int)info_level));
1696 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1697 0 : return;
1698 : }
1699 : }
1700 :
1701 0 : if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
1702 0 : if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
1703 0 : DEBUG(0,("call_trans2setfsinfo: encryption required "
1704 : "and info level 0x%x sent.\n",
1705 : (unsigned int)info_level));
1706 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1707 0 : return;
1708 : }
1709 : }
1710 :
1711 0 : switch(info_level) {
1712 0 : case SMB_SET_CIFS_UNIX_INFO:
1713 0 : if (!lp_smb1_unix_extensions()) {
1714 0 : DEBUG(2,("call_trans2setfsinfo: "
1715 : "SMB_SET_CIFS_UNIX_INFO is invalid with "
1716 : "unix extensions off\n"));
1717 0 : reply_nterror(req,
1718 : NT_STATUS_INVALID_LEVEL);
1719 0 : return;
1720 : }
1721 :
1722 : /* There should be 12 bytes of capabilities set. */
1723 0 : if (total_data < 12) {
1724 0 : reply_nterror(
1725 : req,
1726 : NT_STATUS_INVALID_PARAMETER);
1727 0 : return;
1728 : }
1729 0 : xconn->smb1.unix_info.client_major = SVAL(pdata,0);
1730 0 : xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
1731 0 : xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
1732 0 : xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
1733 : /* Just print these values for now. */
1734 0 : DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
1735 : "major = %u, minor = %u cap_low = 0x%x, "
1736 : "cap_high = 0x%xn",
1737 : (unsigned int)xconn->
1738 : smb1.unix_info.client_major,
1739 : (unsigned int)xconn->
1740 : smb1.unix_info.client_minor,
1741 : (unsigned int)xconn->
1742 : smb1.unix_info.client_cap_low,
1743 : (unsigned int)xconn->
1744 : smb1.unix_info.client_cap_high));
1745 :
1746 : /* Here is where we must switch to posix pathname processing... */
1747 0 : if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1748 0 : lp_set_posix_pathnames();
1749 0 : mangle_change_to_posix();
1750 : }
1751 :
1752 0 : if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
1753 0 : !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
1754 : /* Client that knows how to do posix locks,
1755 : * but not posix open/mkdir operations. Set a
1756 : * default type for read/write checks. */
1757 :
1758 0 : lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
1759 :
1760 : }
1761 0 : break;
1762 :
1763 0 : case SMB_REQUEST_TRANSPORT_ENCRYPTION:
1764 : {
1765 : NTSTATUS status;
1766 0 : size_t param_len = 0;
1767 0 : size_t data_len = total_data;
1768 :
1769 0 : if (!lp_smb1_unix_extensions()) {
1770 0 : reply_nterror(
1771 : req,
1772 : NT_STATUS_INVALID_LEVEL);
1773 0 : return;
1774 : }
1775 :
1776 0 : if (lp_server_smb_encrypt(SNUM(conn)) ==
1777 : SMB_ENCRYPTION_OFF) {
1778 0 : reply_nterror(
1779 : req,
1780 : NT_STATUS_NOT_SUPPORTED);
1781 0 : return;
1782 : }
1783 :
1784 0 : if (xconn->smb1.echo_handler.trusted_fde) {
1785 0 : DEBUG( 2,("call_trans2setfsinfo: "
1786 : "request transport encryption disabled"
1787 : "with 'fork echo handler = yes'\n"));
1788 0 : reply_nterror(
1789 : req,
1790 : NT_STATUS_NOT_SUPPORTED);
1791 0 : return;
1792 : }
1793 :
1794 0 : DEBUG( 4,("call_trans2setfsinfo: "
1795 : "request transport encryption.\n"));
1796 :
1797 0 : status = srv_request_encryption_setup(conn,
1798 : (unsigned char **)ppdata,
1799 : &data_len,
1800 : (unsigned char **)pparams,
1801 : ¶m_len);
1802 :
1803 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
1804 0 : !NT_STATUS_IS_OK(status)) {
1805 0 : reply_nterror(req, status);
1806 0 : return;
1807 : }
1808 :
1809 0 : send_trans2_replies(conn, req,
1810 0 : NT_STATUS_OK,
1811 : *pparams,
1812 : param_len,
1813 : *ppdata,
1814 : data_len,
1815 : max_data_bytes);
1816 :
1817 0 : if (NT_STATUS_IS_OK(status)) {
1818 : /* Server-side transport
1819 : * encryption is now *on*. */
1820 0 : status = srv_encryption_start(conn);
1821 0 : if (!NT_STATUS_IS_OK(status)) {
1822 0 : char *reason = talloc_asprintf(talloc_tos(),
1823 : "Failure in setting "
1824 : "up encrypted transport: %s",
1825 : nt_errstr(status));
1826 0 : exit_server_cleanly(reason);
1827 : }
1828 : }
1829 0 : return;
1830 : }
1831 :
1832 0 : case SMB_FS_QUOTA_INFORMATION:
1833 : {
1834 : NTSTATUS status;
1835 0 : DATA_BLOB qdata = {
1836 : .data = (uint8_t *)pdata,
1837 : .length = total_data
1838 : };
1839 0 : files_struct *fsp = NULL;
1840 0 : fsp = file_fsp(req, SVAL(params,0));
1841 :
1842 0 : status = smb_set_fsquota(conn,
1843 : req,
1844 : fsp,
1845 : &qdata);
1846 0 : if (!NT_STATUS_IS_OK(status)) {
1847 0 : reply_nterror(req, status);
1848 0 : return;
1849 : }
1850 0 : break;
1851 : }
1852 0 : default:
1853 0 : DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1854 : info_level));
1855 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1856 0 : return;
1857 : break;
1858 : }
1859 :
1860 : /*
1861 : * sending this reply works fine,
1862 : * but I'm not sure it's the same
1863 : * like windows do...
1864 : * --metze
1865 : */
1866 0 : reply_smb1_outbuf(req, 10, 0);
1867 : }
1868 :
1869 : /****************************************************************************
1870 : Reply to a TRANSACT2_QFILEINFO on a PIPE !
1871 : ****************************************************************************/
1872 :
1873 0 : static void call_trans2qpipeinfo(connection_struct *conn,
1874 : struct smb_request *req,
1875 : files_struct *fsp,
1876 : uint16_t info_level,
1877 : unsigned int tran_call,
1878 : char **pparams, int total_params,
1879 : char **ppdata, int total_data,
1880 : unsigned int max_data_bytes)
1881 : {
1882 0 : char *params = *pparams;
1883 0 : char *pdata = *ppdata;
1884 0 : unsigned int data_size = 0;
1885 0 : unsigned int param_size = 2;
1886 :
1887 0 : if (!fsp_is_np(fsp)) {
1888 0 : reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1889 0 : return;
1890 : }
1891 :
1892 0 : *pparams = (char *)SMB_REALLOC(*pparams,2);
1893 0 : if (*pparams == NULL) {
1894 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1895 0 : return;
1896 : }
1897 0 : params = *pparams;
1898 0 : SSVAL(params,0,0);
1899 0 : if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
1900 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1901 0 : return;
1902 : }
1903 0 : data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
1904 0 : *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
1905 0 : if (*ppdata == NULL ) {
1906 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
1907 0 : return;
1908 : }
1909 0 : pdata = *ppdata;
1910 :
1911 0 : switch (info_level) {
1912 0 : case SMB_FILE_STANDARD_INFORMATION:
1913 0 : memset(pdata,0,24);
1914 0 : SOFF_T(pdata,0,4096LL);
1915 0 : SIVAL(pdata,16,1);
1916 0 : SIVAL(pdata,20,1);
1917 0 : data_size = 24;
1918 0 : break;
1919 :
1920 0 : default:
1921 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1922 0 : return;
1923 : }
1924 :
1925 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
1926 : max_data_bytes);
1927 :
1928 0 : return;
1929 : }
1930 :
1931 : /****************************************************************************
1932 : Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1933 : file name or file id).
1934 : ****************************************************************************/
1935 :
1936 0 : static void call_trans2qfilepathinfo(connection_struct *conn,
1937 : struct smb_request *req,
1938 : unsigned int tran_call,
1939 : char **pparams, int total_params,
1940 : char **ppdata, int total_data,
1941 : unsigned int max_data_bytes)
1942 : {
1943 0 : char *params = *pparams;
1944 0 : char *pdata = *ppdata;
1945 : uint16_t info_level;
1946 0 : unsigned int data_size = 0;
1947 0 : unsigned int param_size = 2;
1948 0 : struct smb_filename *smb_fname = NULL;
1949 0 : bool delete_pending = False;
1950 : struct timespec write_time_ts;
1951 0 : struct files_struct *dirfsp = NULL;
1952 0 : files_struct *fsp = NULL;
1953 : struct file_id fileid;
1954 0 : struct ea_list *ea_list = NULL;
1955 0 : int lock_data_count = 0;
1956 0 : char *lock_data = NULL;
1957 : size_t fixed_portion;
1958 0 : NTSTATUS status = NT_STATUS_OK;
1959 : int ret;
1960 :
1961 0 : if (!params) {
1962 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1963 0 : return;
1964 : }
1965 :
1966 0 : ZERO_STRUCT(write_time_ts);
1967 :
1968 0 : if (tran_call == TRANSACT2_QFILEINFO) {
1969 0 : if (total_params < 4) {
1970 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1971 0 : return;
1972 : }
1973 :
1974 0 : fsp = file_fsp(req, SVAL(params,0));
1975 0 : info_level = SVAL(params,2);
1976 :
1977 0 : if (IS_IPC(conn)) {
1978 0 : call_trans2qpipeinfo(
1979 : conn,
1980 : req,
1981 : fsp,
1982 : info_level,
1983 : tran_call,
1984 : pparams,
1985 : total_params,
1986 : ppdata,
1987 : total_data,
1988 : max_data_bytes);
1989 0 : return;
1990 : }
1991 :
1992 0 : DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1993 :
1994 0 : if (INFO_LEVEL_IS_UNIX(info_level)) {
1995 0 : if (!lp_smb1_unix_extensions()) {
1996 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1997 0 : return;
1998 : }
1999 0 : if (!req->posix_pathnames) {
2000 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2001 0 : return;
2002 : }
2003 : }
2004 :
2005 : /* Initial check for valid fsp ptr. */
2006 0 : if (!check_fsp_open(conn, req, fsp)) {
2007 0 : return;
2008 : }
2009 :
2010 0 : smb_fname = fsp->fsp_name;
2011 :
2012 0 : if(fsp->fake_file_handle) {
2013 : /*
2014 : * This is actually for the QUOTA_FAKE_FILE --metze
2015 : */
2016 :
2017 : /* We know this name is ok, it's already passed the checks. */
2018 :
2019 0 : } else if(fsp_get_pathref_fd(fsp) == -1) {
2020 : /*
2021 : * This is actually a QFILEINFO on a directory
2022 : * handle (returned from an NT SMB). NT5.0 seems
2023 : * to do this call. JRA.
2024 : */
2025 0 : ret = vfs_stat(conn, smb_fname);
2026 0 : if (ret != 0) {
2027 0 : DBG_NOTICE("vfs_stat of %s failed (%s)\n",
2028 : smb_fname_str_dbg(smb_fname),
2029 : strerror(errno));
2030 0 : reply_nterror(req,
2031 : map_nt_error_from_unix(errno));
2032 0 : return;
2033 : }
2034 :
2035 0 : if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
2036 0 : fileid = vfs_file_id_from_sbuf(
2037 0 : conn, &smb_fname->st);
2038 0 : get_file_infos(fileid, fsp->name_hash,
2039 : &delete_pending,
2040 : &write_time_ts);
2041 : }
2042 : } else {
2043 : /*
2044 : * Original code - this is an open file.
2045 : */
2046 0 : status = vfs_stat_fsp(fsp);
2047 0 : if (!NT_STATUS_IS_OK(status)) {
2048 0 : DEBUG(3, ("fstat of %s failed (%s)\n",
2049 : fsp_fnum_dbg(fsp), nt_errstr(status)));
2050 0 : reply_nterror(req, status);
2051 0 : return;
2052 : }
2053 0 : if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
2054 0 : fileid = vfs_file_id_from_sbuf(
2055 0 : conn, &smb_fname->st);
2056 0 : get_file_infos(fileid, fsp->name_hash,
2057 : &delete_pending,
2058 : &write_time_ts);
2059 : }
2060 : }
2061 :
2062 : } else {
2063 : uint32_t name_hash;
2064 0 : char *fname = NULL;
2065 0 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2066 0 : NTTIME twrp = 0;
2067 :
2068 : /* qpathinfo */
2069 0 : if (total_params < 7) {
2070 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2071 0 : return;
2072 : }
2073 :
2074 0 : info_level = SVAL(params,0);
2075 :
2076 0 : DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2077 :
2078 0 : if (INFO_LEVEL_IS_UNIX(info_level)) {
2079 0 : if (!lp_smb1_unix_extensions()) {
2080 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2081 0 : return;
2082 : }
2083 0 : if (!req->posix_pathnames) {
2084 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2085 0 : return;
2086 : }
2087 : }
2088 :
2089 0 : if (req->posix_pathnames) {
2090 0 : srvstr_get_path_posix(req,
2091 : params,
2092 0 : req->flags2,
2093 : &fname,
2094 0 : ¶ms[6],
2095 0 : total_params - 6,
2096 : STR_TERMINATE,
2097 : &status);
2098 : } else {
2099 0 : srvstr_get_path(req,
2100 : params,
2101 0 : req->flags2,
2102 : &fname,
2103 0 : ¶ms[6],
2104 0 : total_params - 6,
2105 : STR_TERMINATE,
2106 : &status);
2107 : }
2108 0 : if (!NT_STATUS_IS_OK(status)) {
2109 0 : reply_nterror(req, status);
2110 0 : return;
2111 : }
2112 :
2113 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
2114 0 : extract_snapshot_token(fname, &twrp);
2115 : }
2116 0 : status = filename_convert_dirfsp(req,
2117 : conn,
2118 : fname,
2119 : ucf_flags,
2120 : twrp,
2121 : &dirfsp,
2122 : &smb_fname);
2123 0 : if (!NT_STATUS_IS_OK(status)) {
2124 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2125 0 : reply_botherror(req,
2126 : NT_STATUS_PATH_NOT_COVERED,
2127 : ERRSRV, ERRbadpath);
2128 0 : return;
2129 : }
2130 0 : reply_nterror(req, status);
2131 0 : return;
2132 : }
2133 :
2134 : /*
2135 : * qpathinfo must operate on an existing file, so we
2136 : * can exit early if filename_convert_dirfsp() returned the
2137 : * "new file" NT_STATUS_OK, !VALID_STAT case.
2138 : */
2139 :
2140 0 : if (!VALID_STAT(smb_fname->st)) {
2141 0 : reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2142 0 : return;
2143 : }
2144 :
2145 : /*
2146 : * smb_fname->fsp may be NULL if smb_fname points at a symlink
2147 : * and we're in POSIX context, so be careful when using fsp
2148 : * below, it can still be NULL.
2149 : */
2150 0 : fsp = smb_fname->fsp;
2151 :
2152 : /* If this is a stream, check if there is a delete_pending. */
2153 0 : if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
2154 0 : && is_ntfs_stream_smb_fname(smb_fname)) {
2155 : struct smb_filename *smb_fname_base;
2156 :
2157 : /* Create an smb_filename with stream_name == NULL. */
2158 0 : smb_fname_base = synthetic_smb_fname(
2159 : talloc_tos(),
2160 0 : smb_fname->base_name,
2161 : NULL,
2162 : NULL,
2163 0 : smb_fname->twrp,
2164 0 : smb_fname->flags);
2165 0 : if (smb_fname_base == NULL) {
2166 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2167 0 : return;
2168 : }
2169 :
2170 0 : ret = vfs_stat(conn, smb_fname_base);
2171 0 : if (ret != 0) {
2172 0 : DBG_NOTICE("vfs_stat of %s failed "
2173 : "(%s)\n",
2174 : smb_fname_str_dbg(smb_fname_base),
2175 : strerror(errno));
2176 0 : TALLOC_FREE(smb_fname_base);
2177 0 : reply_nterror(req,
2178 : map_nt_error_from_unix(errno));
2179 0 : return;
2180 : }
2181 :
2182 0 : status = file_name_hash(conn,
2183 : smb_fname_str_dbg(smb_fname_base),
2184 : &name_hash);
2185 0 : if (!NT_STATUS_IS_OK(status)) {
2186 0 : TALLOC_FREE(smb_fname_base);
2187 0 : reply_nterror(req, status);
2188 0 : return;
2189 : }
2190 :
2191 0 : fileid = vfs_file_id_from_sbuf(conn,
2192 0 : &smb_fname_base->st);
2193 0 : TALLOC_FREE(smb_fname_base);
2194 0 : get_file_infos(fileid, name_hash, &delete_pending, NULL);
2195 0 : if (delete_pending) {
2196 0 : reply_nterror(req, NT_STATUS_DELETE_PENDING);
2197 0 : return;
2198 : }
2199 : }
2200 :
2201 0 : status = file_name_hash(conn,
2202 : smb_fname_str_dbg(smb_fname),
2203 : &name_hash);
2204 0 : if (!NT_STATUS_IS_OK(status)) {
2205 0 : reply_nterror(req, status);
2206 0 : return;
2207 : }
2208 :
2209 0 : if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
2210 0 : fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2211 0 : get_file_infos(fileid, name_hash, &delete_pending,
2212 : &write_time_ts);
2213 : }
2214 :
2215 0 : if (delete_pending) {
2216 0 : reply_nterror(req, NT_STATUS_DELETE_PENDING);
2217 0 : return;
2218 : }
2219 : }
2220 :
2221 0 : DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
2222 : "total_data=%d\n", smb_fname_str_dbg(smb_fname),
2223 : fsp_fnum_dbg(fsp),
2224 : info_level,tran_call,total_data));
2225 :
2226 : /* Pull out any data sent here before we realloc. */
2227 0 : switch (info_level) {
2228 0 : case SMB_INFO_QUERY_EAS_FROM_LIST:
2229 : {
2230 : /* Pull any EA list from the data portion. */
2231 : uint32_t ea_size;
2232 :
2233 0 : if (total_data < 4) {
2234 0 : reply_nterror(
2235 : req, NT_STATUS_INVALID_PARAMETER);
2236 0 : return;
2237 : }
2238 0 : ea_size = IVAL(pdata,0);
2239 :
2240 0 : if (total_data > 0 && ea_size != total_data) {
2241 0 : DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2242 : total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2243 0 : reply_nterror(
2244 : req, NT_STATUS_INVALID_PARAMETER);
2245 0 : return;
2246 : }
2247 :
2248 0 : if (!lp_ea_support(SNUM(conn))) {
2249 0 : reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2250 0 : return;
2251 : }
2252 :
2253 : /* Pull out the list of names. */
2254 0 : ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
2255 0 : if (!ea_list) {
2256 0 : reply_nterror(
2257 : req, NT_STATUS_INVALID_PARAMETER);
2258 0 : return;
2259 : }
2260 0 : break;
2261 : }
2262 :
2263 0 : case SMB_QUERY_POSIX_LOCK:
2264 : {
2265 0 : if (fsp == NULL ||
2266 0 : fsp->fsp_flags.is_pathref ||
2267 0 : fsp_get_io_fd(fsp) == -1)
2268 : {
2269 0 : reply_nterror(req, NT_STATUS_INVALID_HANDLE);
2270 0 : return;
2271 : }
2272 :
2273 0 : if (total_data != POSIX_LOCK_DATA_SIZE) {
2274 0 : reply_nterror(
2275 : req, NT_STATUS_INVALID_PARAMETER);
2276 0 : return;
2277 : }
2278 :
2279 : /* Copy the lock range data. */
2280 0 : lock_data = (char *)talloc_memdup(
2281 : req, pdata, total_data);
2282 0 : if (!lock_data) {
2283 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2284 0 : return;
2285 : }
2286 0 : lock_data_count = total_data;
2287 0 : break;
2288 : }
2289 0 : default:
2290 0 : break;
2291 : }
2292 :
2293 0 : *pparams = (char *)SMB_REALLOC(*pparams,2);
2294 0 : if (*pparams == NULL) {
2295 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2296 0 : return;
2297 : }
2298 0 : params = *pparams;
2299 0 : SSVAL(params,0,0);
2300 :
2301 : /*
2302 : * draft-leach-cifs-v1-spec-02.txt
2303 : * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
2304 : * says:
2305 : *
2306 : * The requested information is placed in the Data portion of the
2307 : * transaction response. For the information levels greater than 0x100,
2308 : * the transaction response has 1 parameter word which should be
2309 : * ignored by the client.
2310 : *
2311 : * However Windows only follows this rule for the IS_NAME_VALID call.
2312 : */
2313 0 : switch (info_level) {
2314 0 : case SMB_INFO_IS_NAME_VALID:
2315 0 : param_size = 0;
2316 0 : break;
2317 : }
2318 :
2319 0 : if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
2320 : /*
2321 : * We use levels that start with 0xFF00
2322 : * internally to represent SMB2 specific levels
2323 : */
2324 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2325 0 : return;
2326 : }
2327 :
2328 0 : status = smbd_do_qfilepathinfo(conn, req, req, info_level,
2329 : fsp, smb_fname,
2330 : delete_pending, write_time_ts,
2331 : ea_list,
2332 : lock_data_count, lock_data,
2333 0 : req->flags2, max_data_bytes,
2334 : &fixed_portion,
2335 : ppdata, &data_size);
2336 0 : if (!NT_STATUS_IS_OK(status)) {
2337 0 : if (open_was_deferred(req->xconn, req->mid)) {
2338 : /* We have re-scheduled this call. */
2339 0 : return;
2340 : }
2341 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2342 0 : bool ok = defer_smb1_sharing_violation(req);
2343 0 : if (ok) {
2344 0 : return;
2345 : }
2346 : }
2347 0 : reply_nterror(req, status);
2348 0 : return;
2349 : }
2350 0 : if (fixed_portion > max_data_bytes) {
2351 0 : reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
2352 0 : return;
2353 : }
2354 :
2355 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
2356 : max_data_bytes);
2357 :
2358 0 : return;
2359 : }
2360 :
2361 : /****************************************************************************
2362 : Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
2363 : ****************************************************************************/
2364 :
2365 0 : static void call_trans2setfilepathinfo(connection_struct *conn,
2366 : struct smb_request *req,
2367 : unsigned int tran_call,
2368 : char **pparams, int total_params,
2369 : char **ppdata, int total_data,
2370 : unsigned int max_data_bytes)
2371 : {
2372 0 : char *params = *pparams;
2373 0 : char *pdata = *ppdata;
2374 : uint16_t info_level;
2375 0 : struct smb_filename *smb_fname = NULL;
2376 0 : struct files_struct *dirfsp = NULL;
2377 0 : files_struct *fsp = NULL;
2378 0 : NTSTATUS status = NT_STATUS_OK;
2379 0 : int data_return_size = 0;
2380 : int ret;
2381 :
2382 0 : if (!params) {
2383 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2384 0 : return;
2385 : }
2386 :
2387 0 : if (tran_call == TRANSACT2_SETFILEINFO) {
2388 0 : if (total_params < 4) {
2389 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2390 0 : return;
2391 : }
2392 :
2393 0 : fsp = file_fsp(req, SVAL(params,0));
2394 : /* Basic check for non-null fsp. */
2395 0 : if (!check_fsp_open(conn, req, fsp)) {
2396 0 : return;
2397 : }
2398 0 : info_level = SVAL(params,2);
2399 :
2400 0 : if (INFO_LEVEL_IS_UNIX(info_level)) {
2401 0 : if (!lp_smb1_unix_extensions()) {
2402 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2403 0 : return;
2404 : }
2405 0 : if (!req->posix_pathnames) {
2406 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2407 0 : return;
2408 : }
2409 : }
2410 :
2411 0 : smb_fname = fsp->fsp_name;
2412 :
2413 0 : if (fsp_get_pathref_fd(fsp) == -1) {
2414 : /*
2415 : * This is actually a SETFILEINFO on a directory
2416 : * handle (returned from an NT SMB). NT5.0 seems
2417 : * to do this call. JRA.
2418 : */
2419 0 : ret = vfs_stat(conn, smb_fname);
2420 0 : if (ret != 0) {
2421 0 : DBG_NOTICE("vfs_stat of %s failed (%s)\n",
2422 : smb_fname_str_dbg(smb_fname),
2423 : strerror(errno));
2424 0 : reply_nterror(req,
2425 : map_nt_error_from_unix(errno));
2426 0 : return;
2427 : }
2428 0 : } else if (fsp->print_file) {
2429 : /*
2430 : * Doing a DELETE_ON_CLOSE should cancel a print job.
2431 : */
2432 0 : if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2433 :
2434 0 : fsp->fsp_flags.delete_on_close = true;
2435 :
2436 0 : DEBUG(3,("call_trans2setfilepathinfo: "
2437 : "Cancelling print job (%s)\n",
2438 : fsp_str_dbg(fsp)));
2439 :
2440 0 : SSVAL(params,0,0);
2441 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
2442 : *ppdata, 0,
2443 : max_data_bytes);
2444 0 : return;
2445 : } else {
2446 0 : reply_nterror(req,
2447 : NT_STATUS_OBJECT_PATH_NOT_FOUND);
2448 0 : return;
2449 : }
2450 : } else {
2451 : /*
2452 : * Original code - this is an open file.
2453 : */
2454 0 : status = vfs_stat_fsp(fsp);
2455 0 : if (!NT_STATUS_IS_OK(status)) {
2456 0 : DEBUG(3,("call_trans2setfilepathinfo: fstat "
2457 : "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
2458 : nt_errstr(status)));
2459 0 : reply_nterror(req, status);
2460 0 : return;
2461 : }
2462 : }
2463 : } else {
2464 0 : char *fname = NULL;
2465 0 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2466 0 : bool require_existing_object = true;
2467 0 : NTTIME twrp = 0;
2468 :
2469 : /* set path info */
2470 0 : if (total_params < 7) {
2471 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2472 0 : return;
2473 : }
2474 :
2475 0 : info_level = SVAL(params,0);
2476 :
2477 0 : if (INFO_LEVEL_IS_UNIX(info_level)) {
2478 0 : if (!lp_smb1_unix_extensions()) {
2479 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2480 0 : return;
2481 : }
2482 0 : if (!req->posix_pathnames) {
2483 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2484 0 : return;
2485 : }
2486 : }
2487 :
2488 0 : if (req->posix_pathnames) {
2489 0 : srvstr_get_path_posix(req,
2490 : params,
2491 0 : req->flags2,
2492 : &fname,
2493 0 : ¶ms[6],
2494 0 : total_params - 6,
2495 : STR_TERMINATE,
2496 : &status);
2497 : } else {
2498 0 : srvstr_get_path(req,
2499 : params,
2500 0 : req->flags2,
2501 : &fname,
2502 0 : ¶ms[6],
2503 0 : total_params - 6,
2504 : STR_TERMINATE,
2505 : &status);
2506 : }
2507 0 : if (!NT_STATUS_IS_OK(status)) {
2508 0 : reply_nterror(req, status);
2509 0 : return;
2510 : }
2511 :
2512 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
2513 0 : extract_snapshot_token(fname, &twrp);
2514 : }
2515 0 : status = filename_convert_dirfsp(req,
2516 : conn,
2517 : fname,
2518 : ucf_flags,
2519 : twrp,
2520 : &dirfsp,
2521 : &smb_fname);
2522 0 : if (!NT_STATUS_IS_OK(status)) {
2523 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2524 0 : reply_botherror(req,
2525 : NT_STATUS_PATH_NOT_COVERED,
2526 : ERRSRV, ERRbadpath);
2527 0 : return;
2528 : }
2529 0 : reply_nterror(req, status);
2530 0 : return;
2531 : }
2532 :
2533 : /*
2534 : * smb_fname->fsp may be NULL if smb_fname points at a symlink
2535 : * and we're in POSIX context, so be careful when using fsp
2536 : * below, it can still be NULL.
2537 : */
2538 0 : fsp = smb_fname->fsp;
2539 :
2540 : /*
2541 : * There are 4 info levels which can
2542 : * create a new object in the filesystem.
2543 : * They are:
2544 : * SMB_SET_FILE_UNIX_LINK -> creates POSIX symlink.
2545 : * SMB_POSIX_PATH_OPEN -> creates POSIX file or directory.
2546 : * SMB_SET_FILE_UNIX_BASIC:
2547 : * SMB_SET_FILE_UNIX_INFO2: can create a POSIX special file.
2548 : *
2549 : * These info levels do not require an existing object.
2550 : */
2551 0 : switch (info_level) {
2552 0 : case SMB_SET_FILE_UNIX_LINK:
2553 : case SMB_POSIX_PATH_OPEN:
2554 : case SMB_SET_FILE_UNIX_BASIC:
2555 : case SMB_SET_FILE_UNIX_INFO2:
2556 0 : require_existing_object = false;
2557 0 : break;
2558 0 : default:
2559 0 : break;
2560 : }
2561 :
2562 0 : if (!VALID_STAT(smb_fname->st) && require_existing_object) {
2563 0 : reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2564 : }
2565 : }
2566 :
2567 0 : DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
2568 : "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
2569 : fsp_fnum_dbg(fsp),
2570 : info_level,total_data));
2571 :
2572 : /* Realloc the parameter size */
2573 0 : *pparams = (char *)SMB_REALLOC(*pparams,2);
2574 0 : if (*pparams == NULL) {
2575 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2576 0 : return;
2577 : }
2578 0 : params = *pparams;
2579 :
2580 0 : SSVAL(params,0,0);
2581 :
2582 0 : status = smbd_do_setfilepathinfo(conn, req, req,
2583 : info_level,
2584 : fsp,
2585 : smb_fname,
2586 : ppdata, total_data,
2587 : &data_return_size);
2588 0 : if (!NT_STATUS_IS_OK(status)) {
2589 0 : if (open_was_deferred(req->xconn, req->mid)) {
2590 : /* We have re-scheduled this call. */
2591 0 : return;
2592 : }
2593 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2594 0 : bool ok = defer_smb1_sharing_violation(req);
2595 0 : if (ok) {
2596 0 : return;
2597 : }
2598 : }
2599 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
2600 : /* We have re-scheduled this call. */
2601 0 : return;
2602 : }
2603 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2604 0 : reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2605 : ERRSRV, ERRbadpath);
2606 0 : return;
2607 : }
2608 0 : if (info_level == SMB_POSIX_PATH_OPEN) {
2609 0 : reply_openerror(req, status);
2610 0 : return;
2611 : }
2612 :
2613 : /*
2614 : * Invalid EA name needs to return 2 param bytes,
2615 : * not a zero-length error packet.
2616 : */
2617 0 : if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
2618 0 : send_trans2_replies(conn, req, status, params, 2, NULL, 0,
2619 : max_data_bytes);
2620 : } else {
2621 0 : reply_nterror(req, status);
2622 : }
2623 0 : return;
2624 : }
2625 :
2626 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
2627 : max_data_bytes);
2628 :
2629 0 : return;
2630 : }
2631 :
2632 : /****************************************************************************
2633 : Reply to a TRANS2_MKDIR (make directory with extended attributes).
2634 : ****************************************************************************/
2635 :
2636 0 : static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
2637 : char **pparams, int total_params,
2638 : char **ppdata, int total_data,
2639 : unsigned int max_data_bytes)
2640 : {
2641 0 : struct files_struct *dirfsp = NULL;
2642 0 : struct files_struct *fsp = NULL;
2643 0 : struct smb_filename *smb_dname = NULL;
2644 0 : char *params = *pparams;
2645 0 : char *pdata = *ppdata;
2646 0 : char *directory = NULL;
2647 0 : NTSTATUS status = NT_STATUS_OK;
2648 0 : struct ea_list *ea_list = NULL;
2649 0 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2650 0 : NTTIME twrp = 0;
2651 0 : TALLOC_CTX *ctx = talloc_tos();
2652 :
2653 0 : if (!CAN_WRITE(conn)) {
2654 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2655 0 : return;
2656 : }
2657 :
2658 0 : if (total_params < 5) {
2659 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2660 0 : return;
2661 : }
2662 :
2663 0 : if (req->posix_pathnames) {
2664 0 : srvstr_get_path_posix(ctx,
2665 : params,
2666 0 : req->flags2,
2667 : &directory,
2668 0 : ¶ms[4],
2669 0 : total_params - 4,
2670 : STR_TERMINATE,
2671 : &status);
2672 : } else {
2673 0 : srvstr_get_path(ctx,
2674 : params,
2675 0 : req->flags2,
2676 : &directory,
2677 0 : ¶ms[4],
2678 0 : total_params - 4,
2679 : STR_TERMINATE,
2680 : &status);
2681 : }
2682 0 : if (!NT_STATUS_IS_OK(status)) {
2683 0 : reply_nterror(req, status);
2684 0 : return;
2685 : }
2686 :
2687 0 : DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2688 :
2689 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
2690 0 : extract_snapshot_token(directory, &twrp);
2691 : }
2692 0 : status = filename_convert_dirfsp(ctx,
2693 : conn,
2694 : directory,
2695 : ucf_flags,
2696 : twrp,
2697 : &dirfsp,
2698 : &smb_dname);
2699 0 : if (!NT_STATUS_IS_OK(status)) {
2700 0 : if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2701 0 : reply_botherror(req,
2702 : NT_STATUS_PATH_NOT_COVERED,
2703 : ERRSRV, ERRbadpath);
2704 0 : return;
2705 : }
2706 0 : reply_nterror(req, status);
2707 0 : return;
2708 : }
2709 :
2710 : /*
2711 : * OS/2 workplace shell seems to send SET_EA requests of "null"
2712 : * length (4 bytes containing IVAL 4).
2713 : * They seem to have no effect. Bug #3212. JRA.
2714 : */
2715 :
2716 0 : if (total_data && (total_data != 4)) {
2717 : /* Any data in this call is an EA list. */
2718 0 : if (total_data < 10) {
2719 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2720 0 : goto out;
2721 : }
2722 :
2723 0 : if (IVAL(pdata,0) > total_data) {
2724 0 : DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
2725 : IVAL(pdata,0), (unsigned int)total_data));
2726 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2727 0 : goto out;
2728 : }
2729 :
2730 0 : ea_list = read_ea_list(talloc_tos(), pdata + 4,
2731 0 : total_data - 4);
2732 0 : if (!ea_list) {
2733 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2734 0 : goto out;
2735 : }
2736 :
2737 0 : if (!lp_ea_support(SNUM(conn))) {
2738 0 : reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2739 0 : goto out;
2740 : }
2741 : }
2742 : /* If total_data == 4 Windows doesn't care what values
2743 : * are placed in that field, it just ignores them.
2744 : * The System i QNTC IBM SMB client puts bad values here,
2745 : * so ignore them. */
2746 :
2747 0 : status = SMB_VFS_CREATE_FILE(
2748 : conn, /* conn */
2749 : req, /* req */
2750 : dirfsp, /* dirfsp */
2751 : smb_dname, /* fname */
2752 : MAXIMUM_ALLOWED_ACCESS, /* access_mask */
2753 : FILE_SHARE_NONE, /* share_access */
2754 : FILE_CREATE, /* create_disposition*/
2755 : FILE_DIRECTORY_FILE, /* create_options */
2756 : FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
2757 : 0, /* oplock_request */
2758 : NULL, /* lease */
2759 : 0, /* allocation_size */
2760 : 0, /* private_flags */
2761 : NULL, /* sd */
2762 : NULL, /* ea_list */
2763 : &fsp, /* result */
2764 : NULL, /* pinfo */
2765 : NULL, NULL); /* create context */
2766 0 : if (!NT_STATUS_IS_OK(status)) {
2767 0 : reply_nterror(req, status);
2768 0 : goto out;
2769 : }
2770 :
2771 : /* Try and set any given EA. */
2772 0 : if (ea_list) {
2773 0 : status = set_ea(conn, fsp, ea_list);
2774 0 : if (!NT_STATUS_IS_OK(status)) {
2775 0 : reply_nterror(req, status);
2776 0 : goto out;
2777 : }
2778 : }
2779 :
2780 : /* Realloc the parameter and data sizes */
2781 0 : *pparams = (char *)SMB_REALLOC(*pparams,2);
2782 0 : if(*pparams == NULL) {
2783 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2784 0 : goto out;
2785 : }
2786 0 : params = *pparams;
2787 :
2788 0 : SSVAL(params,0,0);
2789 :
2790 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
2791 :
2792 0 : out:
2793 0 : if (fsp != NULL) {
2794 0 : close_file_free(NULL, &fsp, NORMAL_CLOSE);
2795 : }
2796 0 : TALLOC_FREE(smb_dname);
2797 0 : return;
2798 : }
2799 :
2800 : /****************************************************************************
2801 : Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2802 : We don't actually do this - we just send a null response.
2803 : ****************************************************************************/
2804 :
2805 0 : static void call_trans2findnotifyfirst(connection_struct *conn,
2806 : struct smb_request *req,
2807 : char **pparams, int total_params,
2808 : char **ppdata, int total_data,
2809 : unsigned int max_data_bytes)
2810 : {
2811 0 : char *params = *pparams;
2812 : uint16_t info_level;
2813 :
2814 0 : if (total_params < 6) {
2815 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2816 0 : return;
2817 : }
2818 :
2819 0 : info_level = SVAL(params,4);
2820 0 : DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2821 :
2822 0 : switch (info_level) {
2823 0 : case 1:
2824 : case 2:
2825 0 : break;
2826 0 : default:
2827 0 : reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2828 0 : return;
2829 : }
2830 :
2831 : /* Realloc the parameter and data sizes */
2832 0 : *pparams = (char *)SMB_REALLOC(*pparams,6);
2833 0 : if (*pparams == NULL) {
2834 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2835 0 : return;
2836 : }
2837 0 : params = *pparams;
2838 :
2839 0 : SSVAL(params,0,fnf_handle);
2840 0 : SSVAL(params,2,0); /* No changes */
2841 0 : SSVAL(params,4,0); /* No EA errors */
2842 :
2843 0 : fnf_handle++;
2844 :
2845 0 : if(fnf_handle == 0)
2846 0 : fnf_handle = 257;
2847 :
2848 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
2849 :
2850 0 : return;
2851 : }
2852 :
2853 : /****************************************************************************
2854 : Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
2855 : changes). Currently this does nothing.
2856 : ****************************************************************************/
2857 :
2858 0 : static void call_trans2findnotifynext(connection_struct *conn,
2859 : struct smb_request *req,
2860 : char **pparams, int total_params,
2861 : char **ppdata, int total_data,
2862 : unsigned int max_data_bytes)
2863 : {
2864 0 : char *params = *pparams;
2865 :
2866 0 : DEBUG(3,("call_trans2findnotifynext\n"));
2867 :
2868 : /* Realloc the parameter and data sizes */
2869 0 : *pparams = (char *)SMB_REALLOC(*pparams,4);
2870 0 : if (*pparams == NULL) {
2871 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2872 0 : return;
2873 : }
2874 0 : params = *pparams;
2875 :
2876 0 : SSVAL(params,0,0); /* No changes */
2877 0 : SSVAL(params,2,0); /* No EA errors */
2878 :
2879 0 : send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
2880 :
2881 0 : return;
2882 : }
2883 :
2884 : /****************************************************************************
2885 : Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2886 : ****************************************************************************/
2887 :
2888 0 : static void call_trans2getdfsreferral(connection_struct *conn,
2889 : struct smb_request *req,
2890 : char **pparams, int total_params,
2891 : char **ppdata, int total_data,
2892 : unsigned int max_data_bytes)
2893 : {
2894 0 : char *params = *pparams;
2895 0 : char *pathname = NULL;
2896 0 : int reply_size = 0;
2897 : int max_referral_level;
2898 0 : NTSTATUS status = NT_STATUS_OK;
2899 0 : TALLOC_CTX *ctx = talloc_tos();
2900 :
2901 0 : DEBUG(10,("call_trans2getdfsreferral\n"));
2902 :
2903 0 : if (total_params < 3) {
2904 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2905 0 : return;
2906 : }
2907 :
2908 0 : max_referral_level = SVAL(params,0);
2909 :
2910 0 : if(!lp_host_msdfs()) {
2911 0 : reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2912 0 : return;
2913 : }
2914 :
2915 0 : srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
2916 : total_params - 2, STR_TERMINATE);
2917 0 : if (!pathname) {
2918 0 : reply_nterror(req, NT_STATUS_NOT_FOUND);
2919 0 : return;
2920 : }
2921 0 : if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
2922 : ppdata,&status)) < 0) {
2923 0 : reply_nterror(req, status);
2924 0 : return;
2925 : }
2926 :
2927 0 : SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
2928 : SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2929 0 : send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
2930 :
2931 0 : return;
2932 : }
2933 :
2934 : #define LMCAT_SPL 0x53
2935 : #define LMFUNC_GETJOBID 0x60
2936 :
2937 : /****************************************************************************
2938 : Reply to a TRANS2_IOCTL - used for OS/2 printing.
2939 : ****************************************************************************/
2940 :
2941 0 : static void call_trans2ioctl(connection_struct *conn,
2942 : struct smb_request *req,
2943 : char **pparams, int total_params,
2944 : char **ppdata, int total_data,
2945 : unsigned int max_data_bytes)
2946 : {
2947 0 : const struct loadparm_substitution *lp_sub =
2948 0 : loadparm_s3_global_substitution();
2949 0 : char *pdata = *ppdata;
2950 0 : files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
2951 : NTSTATUS status;
2952 0 : size_t len = 0;
2953 :
2954 : /* check for an invalid fid before proceeding */
2955 :
2956 0 : if (!fsp) {
2957 0 : reply_nterror(req, NT_STATUS_INVALID_HANDLE);
2958 0 : return;
2959 : }
2960 :
2961 0 : if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
2962 0 : && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
2963 0 : *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
2964 0 : if (*ppdata == NULL) {
2965 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
2966 0 : return;
2967 : }
2968 0 : pdata = *ppdata;
2969 :
2970 : /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
2971 : CAN ACCEPT THIS IN UNICODE. JRA. */
2972 :
2973 : /* Job number */
2974 0 : SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
2975 :
2976 0 : status = srvstr_push(pdata, req->flags2, pdata + 2,
2977 : lp_netbios_name(), 15,
2978 : STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
2979 0 : if (!NT_STATUS_IS_OK(status)) {
2980 0 : reply_nterror(req, status);
2981 0 : return;
2982 : }
2983 0 : status = srvstr_push(pdata, req->flags2, pdata+18,
2984 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
2985 : STR_ASCII|STR_TERMINATE, &len); /* Service name */
2986 0 : if (!NT_STATUS_IS_OK(status)) {
2987 0 : reply_nterror(req, status);
2988 0 : return;
2989 : }
2990 0 : send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
2991 : max_data_bytes);
2992 0 : return;
2993 : }
2994 :
2995 0 : DEBUG(2,("Unknown TRANS2_IOCTL\n"));
2996 0 : reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2997 : }
2998 :
2999 8 : static void handle_trans2(connection_struct *conn, struct smb_request *req,
3000 : struct trans_state *state)
3001 : {
3002 8 : if (get_Protocol() >= PROTOCOL_NT1) {
3003 8 : req->flags2 |= 0x40; /* IS_LONG_NAME */
3004 8 : SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
3005 : }
3006 :
3007 8 : if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3008 0 : if (state->call != TRANSACT2_QFSINFO &&
3009 0 : state->call != TRANSACT2_SETFSINFO) {
3010 0 : DEBUG(0,("handle_trans2: encryption required "
3011 : "with call 0x%x\n",
3012 : (unsigned int)state->call));
3013 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3014 0 : return;
3015 : }
3016 : }
3017 :
3018 8 : SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
3019 :
3020 : /* Now we must call the relevant TRANS2 function */
3021 8 : switch(state->call) {
3022 0 : case TRANSACT2_OPEN:
3023 : {
3024 0 : START_PROFILE(Trans2_open);
3025 0 : call_trans2open(conn, req,
3026 0 : &state->param, state->total_param,
3027 0 : &state->data, state->total_data,
3028 : state->max_data_return);
3029 0 : END_PROFILE(Trans2_open);
3030 0 : break;
3031 : }
3032 :
3033 0 : case TRANSACT2_FINDFIRST:
3034 : {
3035 0 : START_PROFILE(Trans2_findfirst);
3036 0 : call_trans2findfirst(conn, req,
3037 0 : &state->param, state->total_param,
3038 0 : &state->data, state->total_data,
3039 : state->max_data_return);
3040 0 : END_PROFILE(Trans2_findfirst);
3041 0 : break;
3042 : }
3043 :
3044 0 : case TRANSACT2_FINDNEXT:
3045 : {
3046 0 : START_PROFILE(Trans2_findnext);
3047 0 : call_trans2findnext(conn, req,
3048 0 : &state->param, state->total_param,
3049 0 : &state->data, state->total_data,
3050 : state->max_data_return);
3051 0 : END_PROFILE(Trans2_findnext);
3052 0 : break;
3053 : }
3054 :
3055 8 : case TRANSACT2_QFSINFO:
3056 : {
3057 8 : START_PROFILE(Trans2_qfsinfo);
3058 16 : call_trans2qfsinfo(conn, req,
3059 8 : &state->param, state->total_param,
3060 8 : &state->data, state->total_data,
3061 : state->max_data_return);
3062 8 : END_PROFILE(Trans2_qfsinfo);
3063 8 : break;
3064 : }
3065 :
3066 0 : case TRANSACT2_SETFSINFO:
3067 : {
3068 0 : START_PROFILE(Trans2_setfsinfo);
3069 0 : call_trans2setfsinfo(conn, req,
3070 0 : &state->param, state->total_param,
3071 0 : &state->data, state->total_data,
3072 : state->max_data_return);
3073 0 : END_PROFILE(Trans2_setfsinfo);
3074 0 : break;
3075 : }
3076 :
3077 0 : case TRANSACT2_QPATHINFO:
3078 : case TRANSACT2_QFILEINFO:
3079 : {
3080 0 : START_PROFILE(Trans2_qpathinfo);
3081 0 : call_trans2qfilepathinfo(conn, req, state->call,
3082 0 : &state->param, state->total_param,
3083 0 : &state->data, state->total_data,
3084 : state->max_data_return);
3085 0 : END_PROFILE(Trans2_qpathinfo);
3086 0 : break;
3087 : }
3088 :
3089 0 : case TRANSACT2_SETPATHINFO:
3090 : case TRANSACT2_SETFILEINFO:
3091 : {
3092 0 : START_PROFILE(Trans2_setpathinfo);
3093 0 : call_trans2setfilepathinfo(conn, req, state->call,
3094 0 : &state->param, state->total_param,
3095 0 : &state->data, state->total_data,
3096 : state->max_data_return);
3097 0 : END_PROFILE(Trans2_setpathinfo);
3098 0 : break;
3099 : }
3100 :
3101 0 : case TRANSACT2_FINDNOTIFYFIRST:
3102 : {
3103 0 : START_PROFILE(Trans2_findnotifyfirst);
3104 0 : call_trans2findnotifyfirst(conn, req,
3105 0 : &state->param, state->total_param,
3106 0 : &state->data, state->total_data,
3107 : state->max_data_return);
3108 0 : END_PROFILE(Trans2_findnotifyfirst);
3109 0 : break;
3110 : }
3111 :
3112 0 : case TRANSACT2_FINDNOTIFYNEXT:
3113 : {
3114 0 : START_PROFILE(Trans2_findnotifynext);
3115 0 : call_trans2findnotifynext(conn, req,
3116 0 : &state->param, state->total_param,
3117 0 : &state->data, state->total_data,
3118 : state->max_data_return);
3119 0 : END_PROFILE(Trans2_findnotifynext);
3120 0 : break;
3121 : }
3122 :
3123 0 : case TRANSACT2_MKDIR:
3124 : {
3125 0 : START_PROFILE(Trans2_mkdir);
3126 0 : call_trans2mkdir(conn, req,
3127 0 : &state->param, state->total_param,
3128 0 : &state->data, state->total_data,
3129 : state->max_data_return);
3130 0 : END_PROFILE(Trans2_mkdir);
3131 0 : break;
3132 : }
3133 :
3134 0 : case TRANSACT2_GET_DFS_REFERRAL:
3135 : {
3136 0 : START_PROFILE(Trans2_get_dfs_referral);
3137 0 : call_trans2getdfsreferral(conn, req,
3138 0 : &state->param, state->total_param,
3139 0 : &state->data, state->total_data,
3140 : state->max_data_return);
3141 0 : END_PROFILE(Trans2_get_dfs_referral);
3142 0 : break;
3143 : }
3144 :
3145 0 : case TRANSACT2_IOCTL:
3146 : {
3147 0 : START_PROFILE(Trans2_ioctl);
3148 0 : call_trans2ioctl(conn, req,
3149 0 : &state->param, state->total_param,
3150 0 : &state->data, state->total_data,
3151 : state->max_data_return);
3152 0 : END_PROFILE(Trans2_ioctl);
3153 0 : break;
3154 : }
3155 :
3156 0 : default:
3157 : /* Error in request */
3158 0 : DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
3159 0 : reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
3160 : }
3161 : }
3162 :
3163 : /****************************************************************************
3164 : Reply to a SMBtrans2.
3165 : ****************************************************************************/
3166 :
3167 8 : void reply_trans2(struct smb_request *req)
3168 : {
3169 8 : connection_struct *conn = req->conn;
3170 : unsigned int dsoff;
3171 : unsigned int dscnt;
3172 : unsigned int psoff;
3173 : unsigned int pscnt;
3174 : unsigned int tran_call;
3175 : struct trans_state *state;
3176 : NTSTATUS result;
3177 :
3178 8 : START_PROFILE(SMBtrans2);
3179 :
3180 8 : if (req->wct < 14) {
3181 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3182 0 : END_PROFILE(SMBtrans2);
3183 4 : return;
3184 : }
3185 :
3186 8 : dsoff = SVAL(req->vwv+12, 0);
3187 8 : dscnt = SVAL(req->vwv+11, 0);
3188 8 : psoff = SVAL(req->vwv+10, 0);
3189 8 : pscnt = SVAL(req->vwv+9, 0);
3190 8 : tran_call = SVAL(req->vwv+14, 0);
3191 :
3192 8 : result = allow_new_trans(conn->pending_trans, req->mid);
3193 8 : if (!NT_STATUS_IS_OK(result)) {
3194 0 : DEBUG(2, ("Got invalid trans2 request: %s\n",
3195 : nt_errstr(result)));
3196 0 : reply_nterror(req, result);
3197 0 : END_PROFILE(SMBtrans2);
3198 0 : return;
3199 : }
3200 :
3201 8 : if (IS_IPC(conn)) {
3202 0 : switch (tran_call) {
3203 : /* List the allowed trans2 calls on IPC$ */
3204 0 : case TRANSACT2_OPEN:
3205 : case TRANSACT2_GET_DFS_REFERRAL:
3206 : case TRANSACT2_QFILEINFO:
3207 : case TRANSACT2_QFSINFO:
3208 : case TRANSACT2_SETFSINFO:
3209 0 : break;
3210 0 : default:
3211 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3212 0 : END_PROFILE(SMBtrans2);
3213 0 : return;
3214 : }
3215 4 : }
3216 :
3217 8 : if ((state = talloc(conn, struct trans_state)) == NULL) {
3218 0 : DEBUG(0, ("talloc failed\n"));
3219 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
3220 0 : END_PROFILE(SMBtrans2);
3221 0 : return;
3222 : }
3223 :
3224 8 : state->cmd = SMBtrans2;
3225 :
3226 8 : state->mid = req->mid;
3227 8 : state->vuid = req->vuid;
3228 8 : state->setup_count = SVAL(req->vwv+13, 0);
3229 8 : state->setup = NULL;
3230 8 : state->total_param = SVAL(req->vwv+0, 0);
3231 8 : state->param = NULL;
3232 8 : state->total_data = SVAL(req->vwv+1, 0);
3233 8 : state->data = NULL;
3234 8 : state->max_param_return = SVAL(req->vwv+2, 0);
3235 8 : state->max_data_return = SVAL(req->vwv+3, 0);
3236 8 : state->max_setup_return = SVAL(req->vwv+4, 0);
3237 8 : state->close_on_completion = BITSETW(req->vwv+5, 0);
3238 8 : state->one_way = BITSETW(req->vwv+5, 1);
3239 :
3240 8 : state->call = tran_call;
3241 :
3242 : /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3243 : is so as a sanity check */
3244 8 : if (state->setup_count != 1) {
3245 : /*
3246 : * Need to have rc=0 for ioctl to get job id for OS/2.
3247 : * Network printing will fail if function is not successful.
3248 : * Similar function in reply.c will be used if protocol
3249 : * is LANMAN1.0 instead of LM1.2X002.
3250 : * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3251 : * outbuf doesn't have to be set(only job id is used).
3252 : */
3253 0 : if ( (state->setup_count == 4)
3254 0 : && (tran_call == TRANSACT2_IOCTL)
3255 0 : && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
3256 0 : && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
3257 0 : DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3258 : } else {
3259 0 : DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
3260 0 : DEBUG(2,("Transaction is %d\n",tran_call));
3261 0 : TALLOC_FREE(state);
3262 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3263 0 : END_PROFILE(SMBtrans2);
3264 0 : return;
3265 : }
3266 : }
3267 :
3268 8 : if ((dscnt > state->total_data) || (pscnt > state->total_param))
3269 0 : goto bad_param;
3270 :
3271 8 : if (state->total_data) {
3272 :
3273 0 : if (smb_buffer_oob(state->total_data, 0, dscnt)
3274 0 : || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
3275 0 : goto bad_param;
3276 : }
3277 :
3278 : /* Can't use talloc here, the core routines do realloc on the
3279 : * params and data. */
3280 0 : state->data = (char *)SMB_MALLOC(state->total_data);
3281 0 : if (state->data == NULL) {
3282 0 : DEBUG(0,("reply_trans2: data malloc fail for %u "
3283 : "bytes !\n", (unsigned int)state->total_data));
3284 0 : TALLOC_FREE(state);
3285 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
3286 0 : END_PROFILE(SMBtrans2);
3287 0 : return;
3288 : }
3289 :
3290 0 : memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
3291 : }
3292 :
3293 8 : if (state->total_param) {
3294 :
3295 8 : if (smb_buffer_oob(state->total_param, 0, pscnt)
3296 8 : || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
3297 0 : goto bad_param;
3298 : }
3299 :
3300 : /* Can't use talloc here, the core routines do realloc on the
3301 : * params and data. */
3302 8 : state->param = (char *)SMB_MALLOC(state->total_param);
3303 8 : if (state->param == NULL) {
3304 0 : DEBUG(0,("reply_trans: param malloc fail for %u "
3305 : "bytes !\n", (unsigned int)state->total_param));
3306 0 : SAFE_FREE(state->data);
3307 0 : TALLOC_FREE(state);
3308 0 : reply_nterror(req, NT_STATUS_NO_MEMORY);
3309 0 : END_PROFILE(SMBtrans2);
3310 0 : return;
3311 : }
3312 :
3313 8 : memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
3314 : }
3315 :
3316 8 : state->received_data = dscnt;
3317 8 : state->received_param = pscnt;
3318 :
3319 12 : if ((state->received_param == state->total_param) &&
3320 8 : (state->received_data == state->total_data)) {
3321 :
3322 8 : handle_trans2(conn, req, state);
3323 :
3324 8 : SAFE_FREE(state->data);
3325 8 : SAFE_FREE(state->param);
3326 8 : TALLOC_FREE(state);
3327 8 : END_PROFILE(SMBtrans2);
3328 8 : return;
3329 : }
3330 :
3331 0 : DLIST_ADD(conn->pending_trans, state);
3332 :
3333 : /* We need to send an interim response then receive the rest
3334 : of the parameter/data bytes */
3335 0 : reply_smb1_outbuf(req, 0, 0);
3336 0 : show_msg((char *)req->outbuf);
3337 0 : END_PROFILE(SMBtrans2);
3338 0 : return;
3339 :
3340 0 : bad_param:
3341 :
3342 0 : DEBUG(0,("reply_trans2: invalid trans parameters\n"));
3343 0 : SAFE_FREE(state->data);
3344 0 : SAFE_FREE(state->param);
3345 0 : TALLOC_FREE(state);
3346 0 : END_PROFILE(SMBtrans2);
3347 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3348 : }
3349 :
3350 : /****************************************************************************
3351 : Reply to a SMBtranss2
3352 : ****************************************************************************/
3353 :
3354 0 : void reply_transs2(struct smb_request *req)
3355 : {
3356 0 : connection_struct *conn = req->conn;
3357 : unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
3358 : struct trans_state *state;
3359 :
3360 0 : START_PROFILE(SMBtranss2);
3361 :
3362 0 : show_msg((const char *)req->inbuf);
3363 :
3364 : /* Windows clients expect all replies to
3365 : a transact secondary (SMBtranss2 0x33)
3366 : to have a command code of transact
3367 : (SMBtrans2 0x32). See bug #8989
3368 : and also [MS-CIFS] section 2.2.4.47.2
3369 : for details.
3370 : */
3371 0 : req->cmd = SMBtrans2;
3372 :
3373 0 : if (req->wct < 8) {
3374 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3375 0 : END_PROFILE(SMBtranss2);
3376 0 : return;
3377 : }
3378 :
3379 0 : for (state = conn->pending_trans; state != NULL;
3380 0 : state = state->next) {
3381 0 : if (state->mid == req->mid) {
3382 0 : break;
3383 : }
3384 : }
3385 :
3386 0 : if ((state == NULL) || (state->cmd != SMBtrans2)) {
3387 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3388 0 : END_PROFILE(SMBtranss2);
3389 0 : return;
3390 : }
3391 :
3392 : /* Revise state->total_param and state->total_data in case they have
3393 : changed downwards */
3394 :
3395 0 : if (SVAL(req->vwv+0, 0) < state->total_param)
3396 0 : state->total_param = SVAL(req->vwv+0, 0);
3397 0 : if (SVAL(req->vwv+1, 0) < state->total_data)
3398 0 : state->total_data = SVAL(req->vwv+1, 0);
3399 :
3400 0 : pcnt = SVAL(req->vwv+2, 0);
3401 0 : poff = SVAL(req->vwv+3, 0);
3402 0 : pdisp = SVAL(req->vwv+4, 0);
3403 :
3404 0 : dcnt = SVAL(req->vwv+5, 0);
3405 0 : doff = SVAL(req->vwv+6, 0);
3406 0 : ddisp = SVAL(req->vwv+7, 0);
3407 :
3408 0 : state->received_param += pcnt;
3409 0 : state->received_data += dcnt;
3410 :
3411 0 : if ((state->received_data > state->total_data) ||
3412 0 : (state->received_param > state->total_param))
3413 0 : goto bad_param;
3414 :
3415 0 : if (pcnt) {
3416 0 : if (smb_buffer_oob(state->total_param, pdisp, pcnt)
3417 0 : || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
3418 0 : goto bad_param;
3419 : }
3420 0 : memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
3421 : }
3422 :
3423 0 : if (dcnt) {
3424 0 : if (smb_buffer_oob(state->total_data, ddisp, dcnt)
3425 0 : || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
3426 0 : goto bad_param;
3427 : }
3428 0 : memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
3429 : }
3430 :
3431 0 : if ((state->received_param < state->total_param) ||
3432 0 : (state->received_data < state->total_data)) {
3433 0 : END_PROFILE(SMBtranss2);
3434 0 : return;
3435 : }
3436 :
3437 0 : handle_trans2(conn, req, state);
3438 :
3439 0 : DLIST_REMOVE(conn->pending_trans, state);
3440 0 : SAFE_FREE(state->data);
3441 0 : SAFE_FREE(state->param);
3442 0 : TALLOC_FREE(state);
3443 :
3444 0 : END_PROFILE(SMBtranss2);
3445 0 : return;
3446 :
3447 0 : bad_param:
3448 :
3449 0 : DEBUG(0,("reply_transs2: invalid trans parameters\n"));
3450 0 : DLIST_REMOVE(conn->pending_trans, state);
3451 0 : SAFE_FREE(state->data);
3452 0 : SAFE_FREE(state->param);
3453 0 : TALLOC_FREE(state);
3454 0 : reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3455 0 : END_PROFILE(SMBtranss2);
3456 0 : return;
3457 : }
|