/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- smb_roundup
- samba_private_attr_name
- get_ea_value
- get_ea_names_from_file
- get_ea_list_from_file
- fill_ea_buffer
- estimate_ea_size
- canonicalize_ea_name
- set_ea
- read_ea_name_list
- read_ea_list_entry
- read_ea_list
- ea_list_size
- ea_list_union
- send_trans2_replies
- call_trans2open
- exact_match
- unix_filetype
- unix_perms_from_wire
- check_msdfs_link
- get_lanman2_dir_entry
- call_trans2findfirst
- call_trans2findnext
- create_volume_objectid
- samba_extended_info_version
- call_trans2qfsinfo
- call_trans2setfsinfo
- count_acl_entries
- marshall_posix_acl
- store_file_unix_basic
- map_info2_flags_from_sbuf
- map_info2_flags_to_sbuf
- store_file_unix_basic_info2
- marshall_stream_info
- call_trans2qpipeinfo
- call_trans2qfilepathinfo
- hardlink_internals
- smb_set_file_time
- smb_set_file_dosmode
- smb_set_file_size
- smb_info_set_ea
- smb_set_file_disposition_info
- smb_file_position_information
- smb_file_mode_information
- smb_set_file_unix_link
- smb_set_file_unix_hlink
- smb_file_rename_information
- smb_set_posix_acl
- smb_set_posix_lock
- smb_set_info_standard
- smb_set_file_basic_info
- smb_set_file_allocation_info
- smb_set_file_end_of_file_info
- smb_unix_mknod
- smb_set_file_unix_basic
- smb_set_file_unix_info2
- smb_posix_mkdir
- smb_posix_open
- smb_posix_unlink
- call_trans2setfilepathinfo
- call_trans2mkdir
- call_trans2findnotifyfirst
- call_trans2findnotifynext
- call_trans2getdfsreferral
- call_trans2ioctl
- reply_findclose
- reply_findnclose
- handle_trans2
- reply_trans2
- reply_transs2
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 "version.h"
28 #include "smbd/globals.h"
29
30 extern enum protocol_types Protocol;
31
32 #define DIR_ENTRY_SAFETY_MARGIN 4096
33
34 static char *store_file_unix_basic(connection_struct *conn,
35 char *pdata,
36 files_struct *fsp,
37 const SMB_STRUCT_STAT *psbuf);
38
39 static char *store_file_unix_basic_info2(connection_struct *conn,
40 char *pdata,
41 files_struct *fsp,
42 const SMB_STRUCT_STAT *psbuf);
43
44 /********************************************************************
45 Roundup a value to the nearest allocation roundup size boundary.
46 Only do this for Windows clients.
47 ********************************************************************/
48
49 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
/* [<][>][^][v][top][bottom][index][help] */
50 {
51 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
52
53 /* Only roundup for Windows clients. */
54 enum remote_arch_types ra_type = get_remote_arch();
55 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
56 val = SMB_ROUNDUP(val,rval);
57 }
58 return val;
59 }
60
61 /****************************************************************************
62 Utility functions for dealing with extended attributes.
63 ****************************************************************************/
64
65 /****************************************************************************
66 Refuse to allow clients to overwrite our private xattrs.
67 ****************************************************************************/
68
69 static bool samba_private_attr_name(const char *unix_ea_name)
/* [<][>][^][v][top][bottom][index][help] */
70 {
71 static const char * const prohibited_ea_names[] = {
72 SAMBA_POSIX_INHERITANCE_EA_NAME,
73 SAMBA_XATTR_DOS_ATTRIB,
74 NULL
75 };
76
77 int i;
78
79 for (i = 0; prohibited_ea_names[i]; i++) {
80 if (strequal( prohibited_ea_names[i], unix_ea_name))
81 return true;
82 }
83 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
84 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
85 return true;
86 }
87 return false;
88 }
89
90 /****************************************************************************
91 Get one EA value. Fill in a struct ea_struct.
92 ****************************************************************************/
93
94 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
95 files_struct *fsp, const char *fname,
96 const char *ea_name, struct ea_struct *pea)
97 {
98 /* Get the value of this xattr. Max size is 64k. */
99 size_t attr_size = 256;
100 char *val = NULL;
101 ssize_t sizeret;
102
103 again:
104
105 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
106 if (!val) {
107 return NT_STATUS_NO_MEMORY;
108 }
109
110 if (fsp && fsp->fh->fd != -1) {
111 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
112 } else {
113 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
114 }
115
116 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
117 attr_size = 65536;
118 goto again;
119 }
120
121 if (sizeret == -1) {
122 return map_nt_error_from_unix(errno);
123 }
124
125 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
126 dump_data(10, (uint8 *)val, sizeret);
127
128 pea->flags = 0;
129 if (strnequal(ea_name, "user.", 5)) {
130 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
131 } else {
132 pea->name = talloc_strdup(mem_ctx, ea_name);
133 }
134 if (pea->name == NULL) {
135 TALLOC_FREE(val);
136 return NT_STATUS_NO_MEMORY;
137 }
138 pea->value.data = (unsigned char *)val;
139 pea->value.length = (size_t)sizeret;
140 return NT_STATUS_OK;
141 }
142
143 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
144 files_struct *fsp, const char *fname,
145 char ***pnames, size_t *pnum_names)
146 {
147 /* Get a list of all xattrs. Max namesize is 64k. */
148 size_t ea_namelist_size = 1024;
149 char *ea_namelist = NULL;
150
151 char *p;
152 char **names, **tmp;
153 size_t num_names;
154 ssize_t sizeret = -1;
155
156 if (!lp_ea_support(SNUM(conn))) {
157 *pnames = NULL;
158 *pnum_names = 0;
159 return NT_STATUS_OK;
160 }
161
162 /*
163 * TALLOC the result early to get the talloc hierarchy right.
164 */
165
166 names = TALLOC_ARRAY(mem_ctx, char *, 1);
167 if (names == NULL) {
168 DEBUG(0, ("talloc failed\n"));
169 return NT_STATUS_NO_MEMORY;
170 }
171
172 while (ea_namelist_size <= 65536) {
173
174 ea_namelist = TALLOC_REALLOC_ARRAY(
175 names, ea_namelist, char, ea_namelist_size);
176 if (ea_namelist == NULL) {
177 DEBUG(0, ("talloc failed\n"));
178 TALLOC_FREE(names);
179 return NT_STATUS_NO_MEMORY;
180 }
181
182 if (fsp && fsp->fh->fd != -1) {
183 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
184 ea_namelist_size);
185 } else {
186 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
187 ea_namelist_size);
188 }
189
190 if ((sizeret == -1) && (errno == ERANGE)) {
191 ea_namelist_size *= 2;
192 }
193 else {
194 break;
195 }
196 }
197
198 if (sizeret == -1) {
199 TALLOC_FREE(names);
200 return map_nt_error_from_unix(errno);
201 }
202
203 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
204 (unsigned int)sizeret));
205
206 if (sizeret == 0) {
207 TALLOC_FREE(names);
208 *pnames = NULL;
209 *pnum_names = 0;
210 return NT_STATUS_OK;
211 }
212
213 /*
214 * Ensure the result is 0-terminated
215 */
216
217 if (ea_namelist[sizeret-1] != '\0') {
218 TALLOC_FREE(names);
219 return NT_STATUS_INTERNAL_ERROR;
220 }
221
222 /*
223 * count the names
224 */
225 num_names = 0;
226
227 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
228 num_names += 1;
229 }
230
231 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
232 if (tmp == NULL) {
233 DEBUG(0, ("talloc failed\n"));
234 TALLOC_FREE(names);
235 return NT_STATUS_NO_MEMORY;
236 }
237
238 names = tmp;
239 num_names = 0;
240
241 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
242 names[num_names++] = p;
243 }
244
245 *pnames = names;
246 *pnum_names = num_names;
247 return NT_STATUS_OK;
248 }
249
250 /****************************************************************************
251 Return a linked list of the total EA's. Plus the total size
252 ****************************************************************************/
253
254 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
/* [<][>][^][v][top][bottom][index][help] */
255 const char *fname, size_t *pea_total_len)
256 {
257 /* Get a list of all xattrs. Max namesize is 64k. */
258 size_t i, num_names;
259 char **names;
260 struct ea_list *ea_list_head = NULL;
261 NTSTATUS status;
262
263 *pea_total_len = 0;
264
265 if (!lp_ea_support(SNUM(conn))) {
266 return NULL;
267 }
268
269 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
270 &names, &num_names);
271
272 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
273 return NULL;
274 }
275
276 for (i=0; i<num_names; i++) {
277 struct ea_list *listp;
278 fstring dos_ea_name;
279
280 if (strnequal(names[i], "system.", 7)
281 || samba_private_attr_name(names[i]))
282 continue;
283
284 listp = TALLOC_P(mem_ctx, struct ea_list);
285 if (listp == NULL) {
286 return NULL;
287 }
288
289 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
290 fname, names[i],
291 &listp->ea))) {
292 return NULL;
293 }
294
295 push_ascii_fstring(dos_ea_name, listp->ea.name);
296
297 *pea_total_len +=
298 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
299
300 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
301 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
302 (unsigned int)listp->ea.value.length));
303
304 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
305
306 }
307
308 /* Add on 4 for total length. */
309 if (*pea_total_len) {
310 *pea_total_len += 4;
311 }
312
313 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
314 (unsigned int)*pea_total_len));
315
316 return ea_list_head;
317 }
318
319 /****************************************************************************
320 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
321 that was filled.
322 ****************************************************************************/
323
324 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
/* [<][>][^][v][top][bottom][index][help] */
325 connection_struct *conn, struct ea_list *ea_list)
326 {
327 unsigned int ret_data_size = 4;
328 char *p = pdata;
329
330 SMB_ASSERT(total_data_size >= 4);
331
332 if (!lp_ea_support(SNUM(conn))) {
333 SIVAL(pdata,4,0);
334 return 4;
335 }
336
337 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
338 size_t dos_namelen;
339 fstring dos_ea_name;
340 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
341 dos_namelen = strlen(dos_ea_name);
342 if (dos_namelen > 255 || dos_namelen == 0) {
343 break;
344 }
345 if (ea_list->ea.value.length > 65535) {
346 break;
347 }
348 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
349 break;
350 }
351
352 /* We know we have room. */
353 SCVAL(p,0,ea_list->ea.flags);
354 SCVAL(p,1,dos_namelen);
355 SSVAL(p,2,ea_list->ea.value.length);
356 fstrcpy(p+4, dos_ea_name);
357 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
358
359 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
360 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 }
362
363 ret_data_size = PTR_DIFF(p, pdata);
364 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
365 SIVAL(pdata,0,ret_data_size);
366 return ret_data_size;
367 }
368
369 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
/* [<][>][^][v][top][bottom][index][help] */
370 {
371 size_t total_ea_len = 0;
372 TALLOC_CTX *mem_ctx = NULL;
373
374 if (!lp_ea_support(SNUM(conn))) {
375 return 0;
376 }
377 mem_ctx = talloc_tos();
378 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
379 return total_ea_len;
380 }
381
382 /****************************************************************************
383 Ensure the EA name is case insensitive by matching any existing EA name.
384 ****************************************************************************/
385
386 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
/* [<][>][^][v][top][bottom][index][help] */
387 {
388 size_t total_ea_len;
389 TALLOC_CTX *mem_ctx = talloc_tos();
390 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
391
392 for (; ea_list; ea_list = ea_list->next) {
393 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
394 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
395 &unix_ea_name[5], ea_list->ea.name));
396 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
397 break;
398 }
399 }
400 }
401
402 /****************************************************************************
403 Set or delete an extended attribute.
404 ****************************************************************************/
405
406 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
/* [<][>][^][v][top][bottom][index][help] */
407 {
408 if (!lp_ea_support(SNUM(conn))) {
409 return NT_STATUS_EAS_NOT_SUPPORTED;
410 }
411
412 for (;ea_list; ea_list = ea_list->next) {
413 int ret;
414 fstring unix_ea_name;
415
416 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
417 fstrcat(unix_ea_name, ea_list->ea.name);
418
419 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
420
421 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
422
423 if (samba_private_attr_name(unix_ea_name)) {
424 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
425 return NT_STATUS_ACCESS_DENIED;
426 }
427
428 if (ea_list->ea.value.length == 0) {
429 /* Remove the attribute. */
430 if (fsp && (fsp->fh->fd != -1)) {
431 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
432 unix_ea_name, fsp->fsp_name));
433 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
434 } else {
435 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
436 unix_ea_name, fname));
437 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
438 }
439 #ifdef ENOATTR
440 /* Removing a non existent attribute always succeeds. */
441 if (ret == -1 && errno == ENOATTR) {
442 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
443 unix_ea_name));
444 ret = 0;
445 }
446 #endif
447 } else {
448 if (fsp && (fsp->fh->fd != -1)) {
449 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
450 unix_ea_name, fsp->fsp_name));
451 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
452 ea_list->ea.value.data, ea_list->ea.value.length, 0);
453 } else {
454 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
455 unix_ea_name, fname));
456 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
457 ea_list->ea.value.data, ea_list->ea.value.length, 0);
458 }
459 }
460
461 if (ret == -1) {
462 #ifdef ENOTSUP
463 if (errno == ENOTSUP) {
464 return NT_STATUS_EAS_NOT_SUPPORTED;
465 }
466 #endif
467 return map_nt_error_from_unix(errno);
468 }
469
470 }
471 return NT_STATUS_OK;
472 }
473 /****************************************************************************
474 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
475 ****************************************************************************/
476
477 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
/* [<][>][^][v][top][bottom][index][help] */
478 {
479 struct ea_list *ea_list_head = NULL;
480 size_t converted_size, offset = 0;
481
482 while (offset + 2 < data_size) {
483 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
484 unsigned int namelen = CVAL(pdata,offset);
485
486 offset++; /* Go past the namelen byte. */
487
488 /* integer wrap paranioa. */
489 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
490 (offset > data_size) || (namelen > data_size) ||
491 (offset + namelen >= data_size)) {
492 break;
493 }
494 /* Ensure the name is null terminated. */
495 if (pdata[offset + namelen] != '\0') {
496 return NULL;
497 }
498 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
499 &converted_size)) {
500 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
501 "failed: %s", strerror(errno)));
502 }
503 if (!eal->ea.name) {
504 return NULL;
505 }
506
507 offset += (namelen + 1); /* Go past the name + terminating zero. */
508 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
509 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
510 }
511
512 return ea_list_head;
513 }
514
515 /****************************************************************************
516 Read one EA list entry from the buffer.
517 ****************************************************************************/
518
519 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
/* [<][>][^][v][top][bottom][index][help] */
520 {
521 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
522 uint16 val_len;
523 unsigned int namelen;
524 size_t converted_size;
525
526 if (!eal) {
527 return NULL;
528 }
529
530 if (data_size < 6) {
531 return NULL;
532 }
533
534 eal->ea.flags = CVAL(pdata,0);
535 namelen = CVAL(pdata,1);
536 val_len = SVAL(pdata,2);
537
538 if (4 + namelen + 1 + val_len > data_size) {
539 return NULL;
540 }
541
542 /* Ensure the name is null terminated. */
543 if (pdata[namelen + 4] != '\0') {
544 return NULL;
545 }
546 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
547 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
548 strerror(errno)));
549 }
550 if (!eal->ea.name) {
551 return NULL;
552 }
553
554 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
555 if (!eal->ea.value.data) {
556 return NULL;
557 }
558
559 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
560
561 /* Ensure we're null terminated just in case we print the value. */
562 eal->ea.value.data[val_len] = '\0';
563 /* But don't count the null. */
564 eal->ea.value.length--;
565
566 if (pbytes_used) {
567 *pbytes_used = 4 + namelen + 1 + val_len;
568 }
569
570 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
571 dump_data(10, eal->ea.value.data, eal->ea.value.length);
572
573 return eal;
574 }
575
576 /****************************************************************************
577 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
578 ****************************************************************************/
579
580 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
/* [<][>][^][v][top][bottom][index][help] */
581 {
582 struct ea_list *ea_list_head = NULL;
583 size_t offset = 0;
584 size_t bytes_used = 0;
585
586 while (offset < data_size) {
587 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
588
589 if (!eal) {
590 return NULL;
591 }
592
593 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
594 offset += bytes_used;
595 }
596
597 return ea_list_head;
598 }
599
600 /****************************************************************************
601 Count the total EA size needed.
602 ****************************************************************************/
603
604 static size_t ea_list_size(struct ea_list *ealist)
/* [<][>][^][v][top][bottom][index][help] */
605 {
606 fstring dos_ea_name;
607 struct ea_list *listp;
608 size_t ret = 0;
609
610 for (listp = ealist; listp; listp = listp->next) {
611 push_ascii_fstring(dos_ea_name, listp->ea.name);
612 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
613 }
614 /* Add on 4 for total length. */
615 if (ret) {
616 ret += 4;
617 }
618
619 return ret;
620 }
621
622 /****************************************************************************
623 Return a union of EA's from a file list and a list of names.
624 The TALLOC context for the two lists *MUST* be identical as we steal
625 memory from one list to add to another. JRA.
626 ****************************************************************************/
627
628 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
/* [<][>][^][v][top][bottom][index][help] */
629 {
630 struct ea_list *nlistp, *flistp;
631
632 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
633 for (flistp = file_list; flistp; flistp = flistp->next) {
634 if (strequal(nlistp->ea.name, flistp->ea.name)) {
635 break;
636 }
637 }
638
639 if (flistp) {
640 /* Copy the data from this entry. */
641 nlistp->ea.flags = flistp->ea.flags;
642 nlistp->ea.value = flistp->ea.value;
643 } else {
644 /* Null entry. */
645 nlistp->ea.flags = 0;
646 ZERO_STRUCT(nlistp->ea.value);
647 }
648 }
649
650 *total_ea_len = ea_list_size(name_list);
651 return name_list;
652 }
653
654 /****************************************************************************
655 Send the required number of replies back.
656 We assume all fields other than the data fields are
657 set correctly for the type of call.
658 HACK ! Always assumes smb_setup field is zero.
659 ****************************************************************************/
660
661 void send_trans2_replies(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
662 struct smb_request *req,
663 const char *params,
664 int paramsize,
665 const char *pdata,
666 int datasize,
667 int max_data_bytes)
668 {
669 /* As we are using a protocol > LANMAN1 then the max_send
670 variable must have been set in the sessetupX call.
671 This takes precedence over the max_xmit field in the
672 global struct. These different max_xmit variables should
673 be merged as this is now too confusing */
674
675 int data_to_send = datasize;
676 int params_to_send = paramsize;
677 int useable_space;
678 const char *pp = params;
679 const char *pd = pdata;
680 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
681 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
682 int data_alignment_offset = 0;
683 bool overflow = False;
684
685 /* Modify the data_to_send and datasize and set the error if
686 we're trying to send more than max_data_bytes. We still send
687 the part of the packet(s) that fit. Strange, but needed
688 for OS/2. */
689
690 if (max_data_bytes > 0 && datasize > max_data_bytes) {
691 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
692 max_data_bytes, datasize ));
693 datasize = data_to_send = max_data_bytes;
694 overflow = True;
695 }
696
697 /* If there genuinely are no parameters or data to send just send the empty packet */
698
699 if(params_to_send == 0 && data_to_send == 0) {
700 reply_outbuf(req, 10, 0);
701 show_msg((char *)req->outbuf);
702 return;
703 }
704
705 /* When sending params and data ensure that both are nicely aligned */
706 /* Only do this alignment when there is also data to send - else
707 can cause NT redirector problems. */
708
709 if (((params_to_send % 4) != 0) && (data_to_send != 0))
710 data_alignment_offset = 4 - (params_to_send % 4);
711
712 /* Space is bufsize minus Netbios over TCP header minus SMB header */
713 /* The alignment_offset is to align the param bytes on an even byte
714 boundary. NT 4.0 Beta needs this to work correctly. */
715
716 useable_space = max_send - (smb_size
717 + 2 * 10 /* wct */
718 + alignment_offset
719 + data_alignment_offset);
720
721 if (useable_space < 0) {
722 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
723 "= %d!!!", useable_space));
724 exit_server_cleanly("send_trans2_replies: Not enough space");
725 }
726
727 while (params_to_send || data_to_send) {
728 /* Calculate whether we will totally or partially fill this packet */
729
730 total_sent_thistime = params_to_send + data_to_send;
731
732 /* We can never send more than useable_space */
733 /*
734 * Note that 'useable_space' does not include the alignment offsets,
735 * but we must include the alignment offsets in the calculation of
736 * the length of the data we send over the wire, as the alignment offsets
737 * are sent here. Fix from Marc_Jacobsen@hp.com.
738 */
739
740 total_sent_thistime = MIN(total_sent_thistime, useable_space);
741
742 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
743 + data_alignment_offset);
744
745 /*
746 * We might have SMBtrans2s in req which was transferred to
747 * the outbuf, fix that.
748 */
749 SCVAL(req->outbuf, smb_com, SMBtrans2);
750
751 /* Set total params and data to be sent */
752 SSVAL(req->outbuf,smb_tprcnt,paramsize);
753 SSVAL(req->outbuf,smb_tdrcnt,datasize);
754
755 /* Calculate how many parameters and data we can fit into
756 * this packet. Parameters get precedence
757 */
758
759 params_sent_thistime = MIN(params_to_send,useable_space);
760 data_sent_thistime = useable_space - params_sent_thistime;
761 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
762
763 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
764
765 /* smb_proff is the offset from the start of the SMB header to the
766 parameter bytes, however the first 4 bytes of outbuf are
767 the Netbios over TCP header. Thus use smb_base() to subtract
768 them from the calculation */
769
770 SSVAL(req->outbuf,smb_proff,
771 ((smb_buf(req->outbuf)+alignment_offset)
772 - smb_base(req->outbuf)));
773
774 if(params_sent_thistime == 0)
775 SSVAL(req->outbuf,smb_prdisp,0);
776 else
777 /* Absolute displacement of param bytes sent in this packet */
778 SSVAL(req->outbuf,smb_prdisp,pp - params);
779
780 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
781 if(data_sent_thistime == 0) {
782 SSVAL(req->outbuf,smb_droff,0);
783 SSVAL(req->outbuf,smb_drdisp, 0);
784 } else {
785 /* The offset of the data bytes is the offset of the
786 parameter bytes plus the number of parameters being sent this time */
787 SSVAL(req->outbuf, smb_droff,
788 ((smb_buf(req->outbuf)+alignment_offset)
789 - smb_base(req->outbuf))
790 + params_sent_thistime + data_alignment_offset);
791 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
792 }
793
794 /* Initialize the padding for alignment */
795
796 if (alignment_offset != 0) {
797 memset(smb_buf(req->outbuf), 0, alignment_offset);
798 }
799
800 /* Copy the param bytes into the packet */
801
802 if(params_sent_thistime) {
803 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
804 params_sent_thistime);
805 }
806
807 /* Copy in the data bytes */
808 if(data_sent_thistime) {
809 if (data_alignment_offset != 0) {
810 memset((smb_buf(req->outbuf)+alignment_offset+
811 params_sent_thistime), 0,
812 data_alignment_offset);
813 }
814 memcpy(smb_buf(req->outbuf)+alignment_offset
815 +params_sent_thistime+data_alignment_offset,
816 pd,data_sent_thistime);
817 }
818
819 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
820 params_sent_thistime, data_sent_thistime, useable_space));
821 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
822 params_to_send, data_to_send, paramsize, datasize));
823
824 if (overflow) {
825 error_packet_set((char *)req->outbuf,
826 ERRDOS,ERRbufferoverflow,
827 STATUS_BUFFER_OVERFLOW,
828 __LINE__,__FILE__);
829 }
830
831 /* Send the packet */
832 show_msg((char *)req->outbuf);
833 if (!srv_send_smb(smbd_server_fd(),
834 (char *)req->outbuf,
835 IS_CONN_ENCRYPTED(conn),
836 &req->pcd))
837 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
838
839 TALLOC_FREE(req->outbuf);
840
841 pp += params_sent_thistime;
842 pd += data_sent_thistime;
843
844 params_to_send -= params_sent_thistime;
845 data_to_send -= data_sent_thistime;
846
847 /* Sanity check */
848 if(params_to_send < 0 || data_to_send < 0) {
849 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
850 params_to_send, data_to_send));
851 return;
852 }
853 }
854
855 return;
856 }
857
858 /****************************************************************************
859 Reply to a TRANSACT2_OPEN.
860 ****************************************************************************/
861
862 static void call_trans2open(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
863 struct smb_request *req,
864 char **pparams, int total_params,
865 char **ppdata, int total_data,
866 unsigned int max_data_bytes)
867 {
868 char *params = *pparams;
869 char *pdata = *ppdata;
870 int deny_mode;
871 int32 open_attr;
872 bool oplock_request;
873 #if 0
874 bool return_additional_info;
875 int16 open_sattr;
876 time_t open_time;
877 #endif
878 int open_ofun;
879 uint32 open_size;
880 char *pname;
881 char *fname = NULL;
882 SMB_OFF_T size=0;
883 int fattr=0,mtime=0;
884 SMB_INO_T inode = 0;
885 SMB_STRUCT_STAT sbuf;
886 int smb_action = 0;
887 files_struct *fsp;
888 struct ea_list *ea_list = NULL;
889 uint16 flags = 0;
890 NTSTATUS status;
891 uint32 access_mask;
892 uint32 share_mode;
893 uint32 create_disposition;
894 uint32 create_options = 0;
895 TALLOC_CTX *ctx = talloc_tos();
896
897 SET_STAT_INVALID(sbuf);
898
899 /*
900 * Ensure we have enough parameters to perform the operation.
901 */
902
903 if (total_params < 29) {
904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
905 return;
906 }
907
908 flags = SVAL(params, 0);
909 deny_mode = SVAL(params, 2);
910 open_attr = SVAL(params,6);
911 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
912 if (oplock_request) {
913 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
914 }
915
916 #if 0
917 return_additional_info = BITSETW(params,0);
918 open_sattr = SVAL(params, 4);
919 open_time = make_unix_date3(params+8);
920 #endif
921 open_ofun = SVAL(params,12);
922 open_size = IVAL(params,14);
923 pname = ¶ms[28];
924
925 if (IS_IPC(conn)) {
926 reply_doserror(req, ERRSRV, ERRaccess);
927 return;
928 }
929
930 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
931 total_params - 28, STR_TERMINATE,
932 &status);
933 if (!NT_STATUS_IS_OK(status)) {
934 reply_nterror(req, status);
935 return;
936 }
937
938 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
939 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
940 (unsigned int)open_ofun, open_size));
941
942 if (open_ofun == 0) {
943 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
944 return;
945 }
946
947 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
948 &access_mask,
949 &share_mode,
950 &create_disposition,
951 &create_options)) {
952 reply_doserror(req, ERRDOS, ERRbadaccess);
953 return;
954 }
955
956 /* Any data in this call is an EA list. */
957 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
958 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
959 return;
960 }
961
962 if (total_data != 4) {
963 if (total_data < 10) {
964 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
965 return;
966 }
967
968 if (IVAL(pdata,0) > total_data) {
969 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
970 IVAL(pdata,0), (unsigned int)total_data));
971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
972 return;
973 }
974
975 ea_list = read_ea_list(talloc_tos(), pdata + 4,
976 total_data - 4);
977 if (!ea_list) {
978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
979 return;
980 }
981 } else if (IVAL(pdata,0) != 4) {
982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
983 return;
984 }
985
986 status = SMB_VFS_CREATE_FILE(
987 conn, /* conn */
988 req, /* req */
989 0, /* root_dir_fid */
990 fname, /* fname */
991 CFF_DOS_PATH, /* create_file_flags */
992 access_mask, /* access_mask */
993 share_mode, /* share_access */
994 create_disposition, /* create_disposition*/
995 create_options, /* create_options */
996 open_attr, /* file_attributes */
997 oplock_request, /* oplock_request */
998 open_size, /* allocation_size */
999 NULL, /* sd */
1000 ea_list, /* ea_list */
1001 &fsp, /* result */
1002 &smb_action, /* pinfo */
1003 &sbuf); /* psbuf */
1004
1005 if (!NT_STATUS_IS_OK(status)) {
1006 if (open_was_deferred(req->mid)) {
1007 /* We have re-scheduled this call. */
1008 return;
1009 }
1010 reply_openerror(req, status);
1011 return;
1012 }
1013
1014 size = get_file_size_stat(&sbuf);
1015 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1016 mtime = sbuf.st_mtime;
1017 inode = sbuf.st_ino;
1018 if (fattr & aDIR) {
1019 close_file(req, fsp, ERROR_CLOSE);
1020 reply_doserror(req, ERRDOS,ERRnoaccess);
1021 return;
1022 }
1023
1024 /* Realloc the size of parameters and data we will return */
1025 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1026 if(*pparams == NULL ) {
1027 reply_nterror(req, NT_STATUS_NO_MEMORY);
1028 return;
1029 }
1030 params = *pparams;
1031
1032 SSVAL(params,0,fsp->fnum);
1033 SSVAL(params,2,fattr);
1034 srv_put_dos_date2(params,4, mtime);
1035 SIVAL(params,8, (uint32)size);
1036 SSVAL(params,12,deny_mode);
1037 SSVAL(params,14,0); /* open_type - file or directory. */
1038 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1039
1040 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1041 smb_action |= EXTENDED_OPLOCK_GRANTED;
1042 }
1043
1044 SSVAL(params,18,smb_action);
1045
1046 /*
1047 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1048 */
1049 SIVAL(params,20,inode);
1050 SSVAL(params,24,0); /* Padding. */
1051 if (flags & 8) {
1052 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1053 SIVAL(params, 26, ea_size);
1054 } else {
1055 SIVAL(params, 26, 0);
1056 }
1057
1058 /* Send the required number of replies */
1059 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1060 }
1061
1062 /*********************************************************
1063 Routine to check if a given string matches exactly.
1064 as a special case a mask of "." does NOT match. That
1065 is required for correct wildcard semantics
1066 Case can be significant or not.
1067 **********************************************************/
1068
1069 static bool exact_match(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
1070 const char *str,
1071 const char *mask)
1072 {
1073 if (mask[0] == '.' && mask[1] == 0)
1074 return False;
1075 if (dptr_has_wild(conn->dirptr)) {
1076 return False;
1077 }
1078 if (conn->case_sensitive)
1079 return strcmp(str,mask)==0;
1080 else
1081 return StrCaseCmp(str,mask) == 0;
1082 }
1083
1084 /****************************************************************************
1085 Return the filetype for UNIX extensions.
1086 ****************************************************************************/
1087
1088 static uint32 unix_filetype(mode_t mode)
/* [<][>][^][v][top][bottom][index][help] */
1089 {
1090 if(S_ISREG(mode))
1091 return UNIX_TYPE_FILE;
1092 else if(S_ISDIR(mode))
1093 return UNIX_TYPE_DIR;
1094 #ifdef S_ISLNK
1095 else if(S_ISLNK(mode))
1096 return UNIX_TYPE_SYMLINK;
1097 #endif
1098 #ifdef S_ISCHR
1099 else if(S_ISCHR(mode))
1100 return UNIX_TYPE_CHARDEV;
1101 #endif
1102 #ifdef S_ISBLK
1103 else if(S_ISBLK(mode))
1104 return UNIX_TYPE_BLKDEV;
1105 #endif
1106 #ifdef S_ISFIFO
1107 else if(S_ISFIFO(mode))
1108 return UNIX_TYPE_FIFO;
1109 #endif
1110 #ifdef S_ISSOCK
1111 else if(S_ISSOCK(mode))
1112 return UNIX_TYPE_SOCKET;
1113 #endif
1114
1115 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1116 return UNIX_TYPE_UNKNOWN;
1117 }
1118
1119 /****************************************************************************
1120 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1121 ****************************************************************************/
1122
1123 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1124
1125 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
1126 SMB_STRUCT_STAT *psbuf,
1127 uint32 perms,
1128 enum perm_type ptype,
1129 mode_t *ret_perms)
1130 {
1131 mode_t ret = 0;
1132
1133 if (perms == SMB_MODE_NO_CHANGE) {
1134 if (!VALID_STAT(*psbuf)) {
1135 return NT_STATUS_INVALID_PARAMETER;
1136 } else {
1137 *ret_perms = psbuf->st_mode;
1138 return NT_STATUS_OK;
1139 }
1140 }
1141
1142 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1143 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1144 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1145 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1146 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1147 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1148 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1149 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1150 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1151 #ifdef S_ISVTX
1152 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1153 #endif
1154 #ifdef S_ISGID
1155 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1156 #endif
1157 #ifdef S_ISUID
1158 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1159 #endif
1160
1161 switch (ptype) {
1162 case PERM_NEW_FILE:
1163 /* Apply mode mask */
1164 ret &= lp_create_mask(SNUM(conn));
1165 /* Add in force bits */
1166 ret |= lp_force_create_mode(SNUM(conn));
1167 break;
1168 case PERM_NEW_DIR:
1169 ret &= lp_dir_mask(SNUM(conn));
1170 /* Add in force bits */
1171 ret |= lp_force_dir_mode(SNUM(conn));
1172 break;
1173 case PERM_EXISTING_FILE:
1174 /* Apply mode mask */
1175 ret &= lp_security_mask(SNUM(conn));
1176 /* Add in force bits */
1177 ret |= lp_force_security_mode(SNUM(conn));
1178 break;
1179 case PERM_EXISTING_DIR:
1180 /* Apply mode mask */
1181 ret &= lp_dir_security_mask(SNUM(conn));
1182 /* Add in force bits */
1183 ret |= lp_force_dir_security_mode(SNUM(conn));
1184 break;
1185 }
1186
1187 *ret_perms = ret;
1188 return NT_STATUS_OK;
1189 }
1190
1191 /****************************************************************************
1192 Needed to show the msdfs symlinks as directories. Modifies psbuf
1193 to be a directory if it's a msdfs link.
1194 ****************************************************************************/
1195
1196 static bool check_msdfs_link(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
1197 const char *pathname,
1198 SMB_STRUCT_STAT *psbuf)
1199 {
1200 int saved_errno = errno;
1201 if(lp_host_msdfs() &&
1202 lp_msdfs_root(SNUM(conn)) &&
1203 is_msdfs_link(conn, pathname, psbuf)) {
1204
1205 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1206 "as a directory\n",
1207 pathname));
1208 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1209 errno = saved_errno;
1210 return true;
1211 }
1212 errno = saved_errno;
1213 return false;
1214 }
1215
1216
1217 /****************************************************************************
1218 Get a level dependent lanman2 dir entry.
1219 ****************************************************************************/
1220
1221 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
/* [<][>][^][v][top][bottom][index][help] */
1222 connection_struct *conn,
1223 uint16 flags2,
1224 const char *path_mask,
1225 uint32 dirtype,
1226 int info_level,
1227 int requires_resume_key,
1228 bool dont_descend,
1229 bool ask_sharemode,
1230 char **ppdata,
1231 char *base_data,
1232 char *end_data,
1233 int space_remaining,
1234 bool *out_of_space,
1235 bool *got_exact_match,
1236 int *last_entry_off,
1237 struct ea_list *name_list)
1238 {
1239 char *dname;
1240 bool found = False;
1241 SMB_STRUCT_STAT sbuf;
1242 const char *mask = NULL;
1243 char *pathreal = NULL;
1244 char *fname = NULL;
1245 char *p, *q, *pdata = *ppdata;
1246 uint32 reskey=0;
1247 long prev_dirpos=0;
1248 uint32 mode=0;
1249 SMB_OFF_T file_size = 0;
1250 uint64_t allocation_size = 0;
1251 uint32 len;
1252 struct timespec mdate_ts, adate_ts, create_date_ts;
1253 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1254 char *nameptr;
1255 char *last_entry_ptr;
1256 bool was_8_3;
1257 uint32 nt_extmode; /* Used for NT connections instead of mode */
1258 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1259 bool check_mangled_names = lp_manglednames(conn->params);
1260 char mangled_name[13]; /* mangled 8.3 name. */
1261
1262 *out_of_space = False;
1263 *got_exact_match = False;
1264
1265 ZERO_STRUCT(mdate_ts);
1266 ZERO_STRUCT(adate_ts);
1267 ZERO_STRUCT(create_date_ts);
1268
1269 if (!conn->dirptr) {
1270 return(False);
1271 }
1272
1273 p = strrchr_m(path_mask,'/');
1274 if(p != NULL) {
1275 if(p[1] == '\0') {
1276 mask = talloc_strdup(ctx,"*.*");
1277 } else {
1278 mask = p+1;
1279 }
1280 } else {
1281 mask = path_mask;
1282 }
1283
1284 while (!found) {
1285 bool got_match;
1286 bool ms_dfs_link = False;
1287
1288 /* Needed if we run out of space */
1289 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1290 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1291
1292 /*
1293 * Due to bugs in NT client redirectors we are not using
1294 * resume keys any more - set them to zero.
1295 * Check out the related comments in findfirst/findnext.
1296 * JRA.
1297 */
1298
1299 reskey = 0;
1300
1301 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1302 (long)conn->dirptr,curr_dirpos));
1303
1304 if (!dname) {
1305 return(False);
1306 }
1307
1308 /*
1309 * fname may get mangled, dname is never mangled.
1310 * Whenever we're accessing the filesystem we use
1311 * pathreal which is composed from dname.
1312 */
1313
1314 pathreal = NULL;
1315 fname = dname;
1316
1317 /* Mangle fname if it's an illegal name. */
1318 if (mangle_must_mangle(dname,conn->params)) {
1319 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1320 TALLOC_FREE(fname);
1321 continue; /* Error - couldn't mangle. */
1322 }
1323 fname = talloc_strdup(ctx, mangled_name);
1324 if (!fname) {
1325 return False;
1326 }
1327 }
1328
1329 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1330 got_match = mask_match(fname, mask, conn->case_sensitive);
1331 }
1332
1333 if(!got_match && check_mangled_names &&
1334 !mangle_is_8_3(fname, False, conn->params)) {
1335 /*
1336 * It turns out that NT matches wildcards against
1337 * both long *and* short names. This may explain some
1338 * of the wildcard wierdness from old DOS clients
1339 * that some people have been seeing.... JRA.
1340 */
1341 /* Force the mangling into 8.3. */
1342 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1343 TALLOC_FREE(fname);
1344 continue; /* Error - couldn't mangle. */
1345 }
1346
1347 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1348 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1349 }
1350 }
1351
1352 if (got_match) {
1353 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1354
1355 if (dont_descend && !isdots) {
1356 TALLOC_FREE(fname);
1357 continue;
1358 }
1359
1360 if (needslash) {
1361 pathreal = NULL;
1362 pathreal = talloc_asprintf(ctx,
1363 "%s/%s",
1364 conn->dirpath,
1365 dname);
1366 } else {
1367 pathreal = talloc_asprintf(ctx,
1368 "%s%s",
1369 conn->dirpath,
1370 dname);
1371 }
1372
1373 if (!pathreal) {
1374 TALLOC_FREE(fname);
1375 return False;
1376 }
1377
1378 if (INFO_LEVEL_IS_UNIX(info_level)) {
1379 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1380 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1381 pathreal,strerror(errno)));
1382 TALLOC_FREE(pathreal);
1383 TALLOC_FREE(fname);
1384 continue;
1385 }
1386 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1387 /* Needed to show the msdfs symlinks as
1388 * directories */
1389
1390 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1391 if (!ms_dfs_link) {
1392 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1393 pathreal,strerror(errno)));
1394 TALLOC_FREE(pathreal);
1395 TALLOC_FREE(fname);
1396 continue;
1397 }
1398 }
1399
1400 if (ms_dfs_link) {
1401 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1402 } else {
1403 mode = dos_mode(conn,pathreal,&sbuf);
1404 }
1405
1406 if (!dir_check_ftype(conn,mode,dirtype)) {
1407 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1408 TALLOC_FREE(pathreal);
1409 TALLOC_FREE(fname);
1410 continue;
1411 }
1412
1413 if (!(mode & aDIR)) {
1414 file_size = get_file_size_stat(&sbuf);
1415 }
1416 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1417
1418 mdate_ts = get_mtimespec(&sbuf);
1419 adate_ts = get_atimespec(&sbuf);
1420 create_date_ts = get_create_timespec(&sbuf,
1421 lp_fake_dir_create_times(SNUM(conn)));
1422
1423 if (ask_sharemode) {
1424 struct timespec write_time_ts;
1425 struct file_id fileid;
1426
1427 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1428 get_file_infos(fileid, NULL, &write_time_ts);
1429 if (!null_timespec(write_time_ts)) {
1430 mdate_ts = write_time_ts;
1431 }
1432 }
1433
1434 if (lp_dos_filetime_resolution(SNUM(conn))) {
1435 dos_filetime_timespec(&create_date_ts);
1436 dos_filetime_timespec(&mdate_ts);
1437 dos_filetime_timespec(&adate_ts);
1438 }
1439
1440 create_date = convert_timespec_to_time_t(create_date_ts);
1441 mdate = convert_timespec_to_time_t(mdate_ts);
1442 adate = convert_timespec_to_time_t(adate_ts);
1443
1444 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1445 pathreal,fname));
1446
1447 found = True;
1448
1449 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1450 }
1451
1452 if (!found)
1453 TALLOC_FREE(fname);
1454 }
1455
1456 p = pdata;
1457 last_entry_ptr = p;
1458
1459 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1460
1461 switch (info_level) {
1462 case SMB_FIND_INFO_STANDARD:
1463 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1464 if(requires_resume_key) {
1465 SIVAL(p,0,reskey);
1466 p += 4;
1467 }
1468 srv_put_dos_date2(p,0,create_date);
1469 srv_put_dos_date2(p,4,adate);
1470 srv_put_dos_date2(p,8,mdate);
1471 SIVAL(p,12,(uint32)file_size);
1472 SIVAL(p,16,(uint32)allocation_size);
1473 SSVAL(p,20,mode);
1474 p += 23;
1475 nameptr = p;
1476 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1477 p += ucs2_align(base_data, p, 0);
1478 }
1479 len = srvstr_push(base_data, flags2, p,
1480 fname, PTR_DIFF(end_data, p),
1481 STR_TERMINATE);
1482 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1483 if (len > 2) {
1484 SCVAL(nameptr, -1, len - 2);
1485 } else {
1486 SCVAL(nameptr, -1, 0);
1487 }
1488 } else {
1489 if (len > 1) {
1490 SCVAL(nameptr, -1, len - 1);
1491 } else {
1492 SCVAL(nameptr, -1, 0);
1493 }
1494 }
1495 p += len;
1496 break;
1497
1498 case SMB_FIND_EA_SIZE:
1499 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1500 if(requires_resume_key) {
1501 SIVAL(p,0,reskey);
1502 p += 4;
1503 }
1504 srv_put_dos_date2(p,0,create_date);
1505 srv_put_dos_date2(p,4,adate);
1506 srv_put_dos_date2(p,8,mdate);
1507 SIVAL(p,12,(uint32)file_size);
1508 SIVAL(p,16,(uint32)allocation_size);
1509 SSVAL(p,20,mode);
1510 {
1511 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1512 SIVAL(p,22,ea_size); /* Extended attributes */
1513 }
1514 p += 27;
1515 nameptr = p - 1;
1516 len = srvstr_push(base_data, flags2,
1517 p, fname, PTR_DIFF(end_data, p),
1518 STR_TERMINATE | STR_NOALIGN);
1519 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1520 if (len > 2) {
1521 len -= 2;
1522 } else {
1523 len = 0;
1524 }
1525 } else {
1526 if (len > 1) {
1527 len -= 1;
1528 } else {
1529 len = 0;
1530 }
1531 }
1532 SCVAL(nameptr,0,len);
1533 p += len;
1534 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1535 break;
1536
1537 case SMB_FIND_EA_LIST:
1538 {
1539 struct ea_list *file_list = NULL;
1540 size_t ea_len = 0;
1541
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1543 if (!name_list) {
1544 return False;
1545 }
1546 if(requires_resume_key) {
1547 SIVAL(p,0,reskey);
1548 p += 4;
1549 }
1550 srv_put_dos_date2(p,0,create_date);
1551 srv_put_dos_date2(p,4,adate);
1552 srv_put_dos_date2(p,8,mdate);
1553 SIVAL(p,12,(uint32)file_size);
1554 SIVAL(p,16,(uint32)allocation_size);
1555 SSVAL(p,20,mode);
1556 p += 22; /* p now points to the EA area. */
1557
1558 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1559 name_list = ea_list_union(name_list, file_list, &ea_len);
1560
1561 /* We need to determine if this entry will fit in the space available. */
1562 /* Max string size is 255 bytes. */
1563 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1564 /* Move the dirptr back to prev_dirpos */
1565 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566 *out_of_space = True;
1567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568 return False; /* Not finished - just out of space */
1569 }
1570
1571 /* Push the ea_data followed by the name. */
1572 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1573 nameptr = p;
1574 len = srvstr_push(base_data, flags2,
1575 p + 1, fname, PTR_DIFF(end_data, p+1),
1576 STR_TERMINATE | STR_NOALIGN);
1577 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578 if (len > 2) {
1579 len -= 2;
1580 } else {
1581 len = 0;
1582 }
1583 } else {
1584 if (len > 1) {
1585 len -= 1;
1586 } else {
1587 len = 0;
1588 }
1589 }
1590 SCVAL(nameptr,0,len);
1591 p += len + 1;
1592 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1593 break;
1594 }
1595
1596 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1597 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1598 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1599 p += 4;
1600 SIVAL(p,0,reskey); p += 4;
1601 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1602 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1603 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1604 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1605 SOFF_T(p,0,file_size); p += 8;
1606 SOFF_T(p,0,allocation_size); p += 8;
1607 SIVAL(p,0,nt_extmode); p += 4;
1608 q = p; p += 4; /* q is placeholder for name length. */
1609 {
1610 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1611 SIVAL(p,0,ea_size); /* Extended attributes */
1612 p += 4;
1613 }
1614 /* Clear the short name buffer. This is
1615 * IMPORTANT as not doing so will trigger
1616 * a Win2k client bug. JRA.
1617 */
1618 if (!was_8_3 && check_mangled_names) {
1619 if (!name_to_8_3(fname,mangled_name,True,
1620 conn->params)) {
1621 /* Error - mangle failed ! */
1622 memset(mangled_name,'\0',12);
1623 }
1624 mangled_name[12] = 0;
1625 len = srvstr_push(base_data, flags2,
1626 p+2, mangled_name, 24,
1627 STR_UPPER|STR_UNICODE);
1628 if (len < 24) {
1629 memset(p + 2 + len,'\0',24 - len);
1630 }
1631 SSVAL(p, 0, len);
1632 } else {
1633 memset(p,'\0',26);
1634 }
1635 p += 2 + 24;
1636 len = srvstr_push(base_data, flags2, p,
1637 fname, PTR_DIFF(end_data, p),
1638 STR_TERMINATE_ASCII);
1639 SIVAL(q,0,len);
1640 p += len;
1641 SIVAL(p,0,0); /* Ensure any padding is null. */
1642 len = PTR_DIFF(p, pdata);
1643 len = (len + 3) & ~3;
1644 SIVAL(pdata,0,len);
1645 p = pdata + len;
1646 break;
1647
1648 case SMB_FIND_FILE_DIRECTORY_INFO:
1649 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1650 p += 4;
1651 SIVAL(p,0,reskey); p += 4;
1652 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1653 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1654 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1655 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1656 SOFF_T(p,0,file_size); p += 8;
1657 SOFF_T(p,0,allocation_size); p += 8;
1658 SIVAL(p,0,nt_extmode); p += 4;
1659 len = srvstr_push(base_data, flags2,
1660 p + 4, fname, PTR_DIFF(end_data, p+4),
1661 STR_TERMINATE_ASCII);
1662 SIVAL(p,0,len);
1663 p += 4 + len;
1664 SIVAL(p,0,0); /* Ensure any padding is null. */
1665 len = PTR_DIFF(p, pdata);
1666 len = (len + 3) & ~3;
1667 SIVAL(pdata,0,len);
1668 p = pdata + len;
1669 break;
1670
1671 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1672 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1673 p += 4;
1674 SIVAL(p,0,reskey); p += 4;
1675 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1676 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1677 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1678 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1679 SOFF_T(p,0,file_size); p += 8;
1680 SOFF_T(p,0,allocation_size); p += 8;
1681 SIVAL(p,0,nt_extmode); p += 4;
1682 q = p; p += 4; /* q is placeholder for name length. */
1683 {
1684 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1685 SIVAL(p,0,ea_size); /* Extended attributes */
1686 p +=4;
1687 }
1688 len = srvstr_push(base_data, flags2, p,
1689 fname, PTR_DIFF(end_data, p),
1690 STR_TERMINATE_ASCII);
1691 SIVAL(q, 0, len);
1692 p += len;
1693
1694 SIVAL(p,0,0); /* Ensure any padding is null. */
1695 len = PTR_DIFF(p, pdata);
1696 len = (len + 3) & ~3;
1697 SIVAL(pdata,0,len);
1698 p = pdata + len;
1699 break;
1700
1701 case SMB_FIND_FILE_NAMES_INFO:
1702 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1703 p += 4;
1704 SIVAL(p,0,reskey); p += 4;
1705 p += 4;
1706 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1707 acl on a dir (tridge) */
1708 len = srvstr_push(base_data, flags2, p,
1709 fname, PTR_DIFF(end_data, p),
1710 STR_TERMINATE_ASCII);
1711 SIVAL(p, -4, len);
1712 p += len;
1713 SIVAL(p,0,0); /* Ensure any padding is null. */
1714 len = PTR_DIFF(p, pdata);
1715 len = (len + 3) & ~3;
1716 SIVAL(pdata,0,len);
1717 p = pdata + len;
1718 break;
1719
1720 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1721 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1722 p += 4;
1723 SIVAL(p,0,reskey); p += 4;
1724 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1725 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1726 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1727 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1728 SOFF_T(p,0,file_size); p += 8;
1729 SOFF_T(p,0,allocation_size); p += 8;
1730 SIVAL(p,0,nt_extmode); p += 4;
1731 q = p; p += 4; /* q is placeholder for name length. */
1732 {
1733 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1734 SIVAL(p,0,ea_size); /* Extended attributes */
1735 p +=4;
1736 }
1737 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1738 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1739 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1740 len = srvstr_push(base_data, flags2, p,
1741 fname, PTR_DIFF(end_data, p),
1742 STR_TERMINATE_ASCII);
1743 SIVAL(q, 0, len);
1744 p += len;
1745 SIVAL(p,0,0); /* Ensure any padding is null. */
1746 len = PTR_DIFF(p, pdata);
1747 len = (len + 3) & ~3;
1748 SIVAL(pdata,0,len);
1749 p = pdata + len;
1750 break;
1751
1752 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1753 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1754 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1755 p += 4;
1756 SIVAL(p,0,reskey); p += 4;
1757 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1758 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1759 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1760 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1761 SOFF_T(p,0,file_size); p += 8;
1762 SOFF_T(p,0,allocation_size); p += 8;
1763 SIVAL(p,0,nt_extmode); p += 4;
1764 q = p; p += 4; /* q is placeholder for name length */
1765 {
1766 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1767 SIVAL(p,0,ea_size); /* Extended attributes */
1768 p +=4;
1769 }
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1773 */
1774 if (!was_8_3 && check_mangled_names) {
1775 if (!name_to_8_3(fname,mangled_name,True,
1776 conn->params)) {
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1779 }
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1784 SSVAL(p, 0, len);
1785 if (len < 24) {
1786 memset(p + 2 + len,'\0',24 - len);
1787 }
1788 SSVAL(p, 0, len);
1789 } else {
1790 memset(p,'\0',26);
1791 }
1792 p += 26;
1793 SSVAL(p,0,0); p += 2; /* Reserved ? */
1794 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1795 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1796 len = srvstr_push(base_data, flags2, p,
1797 fname, PTR_DIFF(end_data, p),
1798 STR_TERMINATE_ASCII);
1799 SIVAL(q,0,len);
1800 p += len;
1801 SIVAL(p,0,0); /* Ensure any padding is null. */
1802 len = PTR_DIFF(p, pdata);
1803 len = (len + 3) & ~3;
1804 SIVAL(pdata,0,len);
1805 p = pdata + len;
1806 break;
1807
1808 /* CIFS UNIX Extension. */
1809
1810 case SMB_FIND_FILE_UNIX:
1811 case SMB_FIND_FILE_UNIX_INFO2:
1812 p+= 4;
1813 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1814
1815 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1816
1817 if (info_level == SMB_FIND_FILE_UNIX) {
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1819 p = store_file_unix_basic(conn, p,
1820 NULL, &sbuf);
1821 len = srvstr_push(base_data, flags2, p,
1822 fname, PTR_DIFF(end_data, p),
1823 STR_TERMINATE);
1824 } else {
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1826 p = store_file_unix_basic_info2(conn, p,
1827 NULL, &sbuf);
1828 nameptr = p;
1829 p += 4;
1830 len = srvstr_push(base_data, flags2, p, fname,
1831 PTR_DIFF(end_data, p), 0);
1832 SIVAL(nameptr, 0, len);
1833 }
1834
1835 p += len;
1836 SIVAL(p,0,0); /* Ensure any padding is null. */
1837
1838 len = PTR_DIFF(p, pdata);
1839 len = (len + 3) & ~3;
1840 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1841 p = pdata + len;
1842 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1843
1844 break;
1845
1846 default:
1847 TALLOC_FREE(fname);
1848 return(False);
1849 }
1850
1851 TALLOC_FREE(fname);
1852 if (PTR_DIFF(p,pdata) > space_remaining) {
1853 /* Move the dirptr back to prev_dirpos */
1854 dptr_SeekDir(conn->dirptr, prev_dirpos);
1855 *out_of_space = True;
1856 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1857 return False; /* Not finished - just out of space */
1858 }
1859
1860 /* Setup the last entry pointer, as an offset from base_data */
1861 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1862 /* Advance the data pointer to the next slot */
1863 *ppdata = p;
1864
1865 return(found);
1866 }
1867
1868 /****************************************************************************
1869 Reply to a TRANS2_FINDFIRST.
1870 ****************************************************************************/
1871
1872 static void call_trans2findfirst(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
1873 struct smb_request *req,
1874 char **pparams, int total_params,
1875 char **ppdata, int total_data,
1876 unsigned int max_data_bytes)
1877 {
1878 /* We must be careful here that we don't return more than the
1879 allowed number of data bytes. If this means returning fewer than
1880 maxentries then so be it. We assume that the redirector has
1881 enough room for the fixed number of parameter bytes it has
1882 requested. */
1883 char *params = *pparams;
1884 char *pdata = *ppdata;
1885 char *data_end;
1886 uint32 dirtype;
1887 int maxentries;
1888 uint16 findfirst_flags;
1889 bool close_after_first;
1890 bool close_if_end;
1891 bool requires_resume_key;
1892 int info_level;
1893 char *directory = NULL;
1894 char *mask = NULL;
1895 char *p;
1896 int last_entry_off=0;
1897 int dptr_num = -1;
1898 int numentries = 0;
1899 int i;
1900 bool finished = False;
1901 bool dont_descend = False;
1902 bool out_of_space = False;
1903 int space_remaining;
1904 bool mask_contains_wcard = False;
1905 SMB_STRUCT_STAT sbuf;
1906 struct ea_list *ea_list = NULL;
1907 NTSTATUS ntstatus = NT_STATUS_OK;
1908 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1909 TALLOC_CTX *ctx = talloc_tos();
1910
1911 if (total_params < 13) {
1912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1913 return;
1914 }
1915
1916 dirtype = SVAL(params,0);
1917 maxentries = SVAL(params,2);
1918 findfirst_flags = SVAL(params,4);
1919 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1920 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1921 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1922 info_level = SVAL(params,6);
1923
1924 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1925 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1926 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1927 info_level, max_data_bytes));
1928
1929 if (!maxentries) {
1930 /* W2K3 seems to treat zero as 1. */
1931 maxentries = 1;
1932 }
1933
1934 switch (info_level) {
1935 case SMB_FIND_INFO_STANDARD:
1936 case SMB_FIND_EA_SIZE:
1937 case SMB_FIND_EA_LIST:
1938 case SMB_FIND_FILE_DIRECTORY_INFO:
1939 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1940 case SMB_FIND_FILE_NAMES_INFO:
1941 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1942 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1943 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1944 break;
1945 case SMB_FIND_FILE_UNIX:
1946 case SMB_FIND_FILE_UNIX_INFO2:
1947 /* Always use filesystem for UNIX mtime query. */
1948 ask_sharemode = false;
1949 if (!lp_unix_extensions()) {
1950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1951 return;
1952 }
1953 break;
1954 default:
1955 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1956 return;
1957 }
1958
1959 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1960 params+12, total_params - 12,
1961 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1962 if (!NT_STATUS_IS_OK(ntstatus)) {
1963 reply_nterror(req, ntstatus);
1964 return;
1965 }
1966
1967 ntstatus = resolve_dfspath_wcard(ctx, conn,
1968 req->flags2 & FLAGS2_DFS_PATHNAMES,
1969 directory,
1970 &directory,
1971 &mask_contains_wcard);
1972 if (!NT_STATUS_IS_OK(ntstatus)) {
1973 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1974 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1975 ERRSRV, ERRbadpath);
1976 return;
1977 }
1978 reply_nterror(req, ntstatus);
1979 return;
1980 }
1981
1982 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1983 if (!NT_STATUS_IS_OK(ntstatus)) {
1984 reply_nterror(req, ntstatus);
1985 return;
1986 }
1987
1988 ntstatus = check_name(conn, directory);
1989 if (!NT_STATUS_IS_OK(ntstatus)) {
1990 reply_nterror(req, ntstatus);
1991 return;
1992 }
1993
1994 p = strrchr_m(directory,'/');
1995 if(p == NULL) {
1996 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1997 if((directory[0] == '.') && (directory[1] == '\0')) {
1998 mask = talloc_strdup(ctx,"*");
1999 if (!mask) {
2000 reply_nterror(req, NT_STATUS_NO_MEMORY);
2001 return;
2002 }
2003 mask_contains_wcard = True;
2004 }
2005 directory = talloc_strdup(talloc_tos(), "./");
2006 if (!directory) {
2007 reply_nterror(req, NT_STATUS_NO_MEMORY);
2008 return;
2009 }
2010 } else {
2011 *p = 0;
2012 }
2013
2014 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2015
2016 if (info_level == SMB_FIND_EA_LIST) {
2017 uint32 ea_size;
2018
2019 if (total_data < 4) {
2020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2021 return;
2022 }
2023
2024 ea_size = IVAL(pdata,0);
2025 if (ea_size != total_data) {
2026 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2027 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2029 return;
2030 }
2031
2032 if (!lp_ea_support(SNUM(conn))) {
2033 reply_doserror(req, ERRDOS, ERReasnotsupported);
2034 return;
2035 }
2036
2037 /* Pull out the list of names. */
2038 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2039 if (!ea_list) {
2040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2041 return;
2042 }
2043 }
2044
2045 *ppdata = (char *)SMB_REALLOC(
2046 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2047 if(*ppdata == NULL ) {
2048 reply_nterror(req, NT_STATUS_NO_MEMORY);
2049 return;
2050 }
2051 pdata = *ppdata;
2052 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2053
2054 /* Realloc the params space */
2055 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2056 if (*pparams == NULL) {
2057 reply_nterror(req, NT_STATUS_NO_MEMORY);
2058 return;
2059 }
2060 params = *pparams;
2061
2062 /* Save the wildcard match and attribs we are using on this directory -
2063 needed as lanman2 assumes these are being saved between calls */
2064
2065 ntstatus = dptr_create(conn,
2066 directory,
2067 False,
2068 True,
2069 req->smbpid,
2070 mask,
2071 mask_contains_wcard,
2072 dirtype,
2073 &conn->dirptr);
2074
2075 if (!NT_STATUS_IS_OK(ntstatus)) {
2076 reply_nterror(req, ntstatus);
2077 return;
2078 }
2079
2080 dptr_num = dptr_dnum(conn->dirptr);
2081 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2082
2083 /* Initialize per TRANS2_FIND_FIRST operation data */
2084 dptr_init_search_op(conn->dirptr);
2085
2086 /* We don't need to check for VOL here as this is returned by
2087 a different TRANS2 call. */
2088
2089 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2090 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2091 dont_descend = True;
2092
2093 p = pdata;
2094 space_remaining = max_data_bytes;
2095 out_of_space = False;
2096
2097 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2098 bool got_exact_match = False;
2099
2100 /* this is a heuristic to avoid seeking the dirptr except when
2101 absolutely necessary. It allows for a filename of about 40 chars */
2102 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2103 out_of_space = True;
2104 finished = False;
2105 } else {
2106 finished = !get_lanman2_dir_entry(ctx,
2107 conn,
2108 req->flags2,
2109 mask,dirtype,info_level,
2110 requires_resume_key,dont_descend,
2111 ask_sharemode,
2112 &p,pdata,data_end,
2113 space_remaining, &out_of_space,
2114 &got_exact_match,
2115 &last_entry_off, ea_list);
2116 }
2117
2118 if (finished && out_of_space)
2119 finished = False;
2120
2121 if (!finished && !out_of_space)
2122 numentries++;
2123
2124 /*
2125 * As an optimisation if we know we aren't looking
2126 * for a wildcard name (ie. the name matches the wildcard exactly)
2127 * then we can finish on any (first) match.
2128 * This speeds up large directory searches. JRA.
2129 */
2130
2131 if(got_exact_match)
2132 finished = True;
2133
2134 /* Ensure space_remaining never goes -ve. */
2135 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2136 space_remaining = 0;
2137 out_of_space = true;
2138 } else {
2139 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2140 }
2141 }
2142
2143 /* Check if we can close the dirptr */
2144 if(close_after_first || (finished && close_if_end)) {
2145 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2146 dptr_close(&dptr_num);
2147 }
2148
2149 /*
2150 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2151 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2152 * the protocol level is less than NT1. Tested with smbclient. JRA.
2153 * This should fix the OS/2 client bug #2335.
2154 */
2155
2156 if(numentries == 0) {
2157 dptr_close(&dptr_num);
2158 if (Protocol < PROTOCOL_NT1) {
2159 reply_doserror(req, ERRDOS, ERRnofiles);
2160 return;
2161 } else {
2162 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2163 ERRDOS, ERRbadfile);
2164 return;
2165 }
2166 }
2167
2168 /* At this point pdata points to numentries directory entries. */
2169
2170 /* Set up the return parameter block */
2171 SSVAL(params,0,dptr_num);
2172 SSVAL(params,2,numentries);
2173 SSVAL(params,4,finished);
2174 SSVAL(params,6,0); /* Never an EA error */
2175 SSVAL(params,8,last_entry_off);
2176
2177 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2178 max_data_bytes);
2179
2180 if ((! *directory) && dptr_path(dptr_num)) {
2181 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2182 if (!directory) {
2183 reply_nterror(req, NT_STATUS_NO_MEMORY);
2184 }
2185 }
2186
2187 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2188 smb_fn_name(req->cmd),
2189 mask, directory, dirtype, numentries ) );
2190
2191 /*
2192 * Force a name mangle here to ensure that the
2193 * mask as an 8.3 name is top of the mangled cache.
2194 * The reasons for this are subtle. Don't remove
2195 * this code unless you know what you are doing
2196 * (see PR#13758). JRA.
2197 */
2198
2199 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2200 char mangled_name[13];
2201 name_to_8_3(mask, mangled_name, True, conn->params);
2202 }
2203
2204 return;
2205 }
2206
2207 /****************************************************************************
2208 Reply to a TRANS2_FINDNEXT.
2209 ****************************************************************************/
2210
2211 static void call_trans2findnext(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
2212 struct smb_request *req,
2213 char **pparams, int total_params,
2214 char **ppdata, int total_data,
2215 unsigned int max_data_bytes)
2216 {
2217 /* We must be careful here that we don't return more than the
2218 allowed number of data bytes. If this means returning fewer than
2219 maxentries then so be it. We assume that the redirector has
2220 enough room for the fixed number of parameter bytes it has
2221 requested. */
2222 char *params = *pparams;
2223 char *pdata = *ppdata;
2224 char *data_end;
2225 int dptr_num;
2226 int maxentries;
2227 uint16 info_level;
2228 uint32 resume_key;
2229 uint16 findnext_flags;
2230 bool close_after_request;
2231 bool close_if_end;
2232 bool requires_resume_key;
2233 bool continue_bit;
2234 bool mask_contains_wcard = False;
2235 char *resume_name = NULL;
2236 const char *mask = NULL;
2237 const char *directory = NULL;
2238 char *p = NULL;
2239 uint16 dirtype;
2240 int numentries = 0;
2241 int i, last_entry_off=0;
2242 bool finished = False;
2243 bool dont_descend = False;
2244 bool out_of_space = False;
2245 int space_remaining;
2246 struct ea_list *ea_list = NULL;
2247 NTSTATUS ntstatus = NT_STATUS_OK;
2248 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2249 TALLOC_CTX *ctx = talloc_tos();
2250
2251 if (total_params < 13) {
2252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2253 return;
2254 }
2255
2256 dptr_num = SVAL(params,0);
2257 maxentries = SVAL(params,2);
2258 info_level = SVAL(params,4);
2259 resume_key = IVAL(params,6);
2260 findnext_flags = SVAL(params,10);
2261 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2262 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2263 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2264 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2265
2266 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2267 params+12,
2268 total_params - 12, STR_TERMINATE, &ntstatus,
2269 &mask_contains_wcard);
2270 if (!NT_STATUS_IS_OK(ntstatus)) {
2271 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2272 complain (it thinks we're asking for the directory above the shared
2273 path or an invalid name). Catch this as the resume name is only compared, never used in
2274 a file access. JRA. */
2275 srvstr_pull_talloc(ctx, params, req->flags2,
2276 &resume_name, params+12,
2277 total_params - 12,
2278 STR_TERMINATE);
2279
2280 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2281 reply_nterror(req, ntstatus);
2282 return;
2283 }
2284 }
2285
2286 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2287 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2288 resume_key = %d resume name = %s continue=%d level = %d\n",
2289 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2290 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2291
2292 if (!maxentries) {
2293 /* W2K3 seems to treat zero as 1. */
2294 maxentries = 1;
2295 }
2296
2297 switch (info_level) {
2298 case SMB_FIND_INFO_STANDARD:
2299 case SMB_FIND_EA_SIZE:
2300 case SMB_FIND_EA_LIST:
2301 case SMB_FIND_FILE_DIRECTORY_INFO:
2302 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_NAMES_INFO:
2304 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2305 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2306 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2307 break;
2308 case SMB_FIND_FILE_UNIX:
2309 case SMB_FIND_FILE_UNIX_INFO2:
2310 /* Always use filesystem for UNIX mtime query. */
2311 ask_sharemode = false;
2312 if (!lp_unix_extensions()) {
2313 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2314 return;
2315 }
2316 break;
2317 default:
2318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2319 return;
2320 }
2321
2322 if (info_level == SMB_FIND_EA_LIST) {
2323 uint32 ea_size;
2324
2325 if (total_data < 4) {
2326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2327 return;
2328 }
2329
2330 ea_size = IVAL(pdata,0);
2331 if (ea_size != total_data) {
2332 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2333 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2335 return;
2336 }
2337
2338 if (!lp_ea_support(SNUM(conn))) {
2339 reply_doserror(req, ERRDOS, ERReasnotsupported);
2340 return;
2341 }
2342
2343 /* Pull out the list of names. */
2344 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2345 if (!ea_list) {
2346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2347 return;
2348 }
2349 }
2350
2351 *ppdata = (char *)SMB_REALLOC(
2352 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2353 if(*ppdata == NULL) {
2354 reply_nterror(req, NT_STATUS_NO_MEMORY);
2355 return;
2356 }
2357
2358 pdata = *ppdata;
2359 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2360
2361 /* Realloc the params space */
2362 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2363 if(*pparams == NULL ) {
2364 reply_nterror(req, NT_STATUS_NO_MEMORY);
2365 return;
2366 }
2367
2368 params = *pparams;
2369
2370 /* Check that the dptr is valid */
2371 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2372 reply_doserror(req, ERRDOS, ERRnofiles);
2373 return;
2374 }
2375
2376 string_set(&conn->dirpath,dptr_path(dptr_num));
2377
2378 /* Get the wildcard mask from the dptr */
2379 if((p = dptr_wcard(dptr_num))== NULL) {
2380 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2381 reply_doserror(req, ERRDOS, ERRnofiles);
2382 return;
2383 }
2384
2385 mask = p;
2386 directory = conn->dirpath;
2387
2388 /* Get the attr mask from the dptr */
2389 dirtype = dptr_attr(dptr_num);
2390
2391 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2392 dptr_num, mask, dirtype,
2393 (long)conn->dirptr,
2394 dptr_TellDir(conn->dirptr)));
2395
2396 /* Initialize per TRANS2_FIND_NEXT operation data */
2397 dptr_init_search_op(conn->dirptr);
2398
2399 /* We don't need to check for VOL here as this is returned by
2400 a different TRANS2 call. */
2401
2402 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2403 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2404 dont_descend = True;
2405
2406 p = pdata;
2407 space_remaining = max_data_bytes;
2408 out_of_space = False;
2409
2410 /*
2411 * Seek to the correct position. We no longer use the resume key but
2412 * depend on the last file name instead.
2413 */
2414
2415 if(*resume_name && !continue_bit) {
2416 SMB_STRUCT_STAT st;
2417
2418 long current_pos = 0;
2419 /*
2420 * Remember, name_to_8_3 is called by
2421 * get_lanman2_dir_entry(), so the resume name
2422 * could be mangled. Ensure we check the unmangled name.
2423 */
2424
2425 if (mangle_is_mangled(resume_name, conn->params)) {
2426 char *new_resume_name = NULL;
2427 mangle_lookup_name_from_8_3(ctx,
2428 resume_name,
2429 &new_resume_name,
2430 conn->params);
2431 if (new_resume_name) {
2432 resume_name = new_resume_name;
2433 }
2434 }
2435
2436 /*
2437 * Fix for NT redirector problem triggered by resume key indexes
2438 * changing between directory scans. We now return a resume key of 0
2439 * and instead look for the filename to continue from (also given
2440 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2441 * findfirst/findnext (as is usual) then the directory pointer
2442 * should already be at the correct place.
2443 */
2444
2445 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2446 } /* end if resume_name && !continue_bit */
2447
2448 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2449 bool got_exact_match = False;
2450
2451 /* this is a heuristic to avoid seeking the dirptr except when
2452 absolutely necessary. It allows for a filename of about 40 chars */
2453 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2454 out_of_space = True;
2455 finished = False;
2456 } else {
2457 finished = !get_lanman2_dir_entry(ctx,
2458 conn,
2459 req->flags2,
2460 mask,dirtype,info_level,
2461 requires_resume_key,dont_descend,
2462 ask_sharemode,
2463 &p,pdata,data_end,
2464 space_remaining, &out_of_space,
2465 &got_exact_match,
2466 &last_entry_off, ea_list);
2467 }
2468
2469 if (finished && out_of_space)
2470 finished = False;
2471
2472 if (!finished && !out_of_space)
2473 numentries++;
2474
2475 /*
2476 * As an optimisation if we know we aren't looking
2477 * for a wildcard name (ie. the name matches the wildcard exactly)
2478 * then we can finish on any (first) match.
2479 * This speeds up large directory searches. JRA.
2480 */
2481
2482 if(got_exact_match)
2483 finished = True;
2484
2485 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2486 }
2487
2488 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2489 smb_fn_name(req->cmd),
2490 mask, directory, dirtype, numentries ) );
2491
2492 /* Check if we can close the dirptr */
2493 if(close_after_request || (finished && close_if_end)) {
2494 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2495 dptr_close(&dptr_num); /* This frees up the saved mask */
2496 }
2497
2498 /* Set up the return parameter block */
2499 SSVAL(params,0,numentries);
2500 SSVAL(params,2,finished);
2501 SSVAL(params,4,0); /* Never an EA error */
2502 SSVAL(params,6,last_entry_off);
2503
2504 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2505 max_data_bytes);
2506
2507 return;
2508 }
2509
2510 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
/* [<][>][^][v][top][bottom][index][help] */
2511 {
2512 E_md4hash(lp_servicename(SNUM(conn)),objid);
2513 return objid;
2514 }
2515
2516 static void samba_extended_info_version(struct smb_extended_info *extended_info)
/* [<][>][^][v][top][bottom][index][help] */
2517 {
2518 SMB_ASSERT(extended_info != NULL);
2519
2520 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2521 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2522 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2523 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2524 #ifdef SAMBA_VERSION_REVISION
2525 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2526 #endif
2527 extended_info->samba_subversion = 0;
2528 #ifdef SAMBA_VERSION_RC_RELEASE
2529 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2530 #else
2531 #ifdef SAMBA_VERSION_PRE_RELEASE
2532 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2533 #endif
2534 #endif
2535 #ifdef SAMBA_VERSION_VENDOR_PATCH
2536 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2537 #endif
2538 extended_info->samba_gitcommitdate = 0;
2539 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2540 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2541 #endif
2542
2543 memset(extended_info->samba_version_string, 0,
2544 sizeof(extended_info->samba_version_string));
2545
2546 snprintf (extended_info->samba_version_string,
2547 sizeof(extended_info->samba_version_string),
2548 "%s", samba_version_string());
2549 }
2550
2551 /****************************************************************************
2552 Reply to a TRANS2_QFSINFO (query filesystem info).
2553 ****************************************************************************/
2554
2555 static void call_trans2qfsinfo(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
2556 struct smb_request *req,
2557 char **pparams, int total_params,
2558 char **ppdata, int total_data,
2559 unsigned int max_data_bytes)
2560 {
2561 char *pdata, *end_data;
2562 char *params = *pparams;
2563 uint16 info_level;
2564 int data_len, len;
2565 SMB_STRUCT_STAT st;
2566 const char *vname = volume_label(SNUM(conn));
2567 int snum = SNUM(conn);
2568 char *fstype = lp_fstype(SNUM(conn));
2569 uint32 additional_flags = 0;
2570
2571 if (total_params < 2) {
2572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2573 return;
2574 }
2575
2576 info_level = SVAL(params,0);
2577
2578 if (IS_IPC(conn)) {
2579 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2580 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2581 "info level (0x%x) on IPC$.\n",
2582 (unsigned int)info_level));
2583 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2584 return;
2585 }
2586 }
2587
2588 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2589 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2590 DEBUG(0,("call_trans2qfsinfo: encryption required "
2591 "and info level 0x%x sent.\n",
2592 (unsigned int)info_level));
2593 exit_server_cleanly("encryption required "
2594 "on connection");
2595 return;
2596 }
2597 }
2598
2599 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2600
2601 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2602 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2603 reply_doserror(req, ERRSRV, ERRinvdevice);
2604 return;
2605 }
2606
2607 *ppdata = (char *)SMB_REALLOC(
2608 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2609 if (*ppdata == NULL ) {
2610 reply_nterror(req, NT_STATUS_NO_MEMORY);
2611 return;
2612 }
2613
2614 pdata = *ppdata;
2615 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2616 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2617
2618 switch (info_level) {
2619 case SMB_INFO_ALLOCATION:
2620 {
2621 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2622 data_len = 18;
2623 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2624 reply_unixerror(req, ERRHRD, ERRgeneral);
2625 return;
2626 }
2627
2628 block_size = lp_block_size(snum);
2629 if (bsize < block_size) {
2630 uint64_t factor = block_size/bsize;
2631 bsize = block_size;
2632 dsize /= factor;
2633 dfree /= factor;
2634 }
2635 if (bsize > block_size) {
2636 uint64_t factor = bsize/block_size;
2637 bsize = block_size;
2638 dsize *= factor;
2639 dfree *= factor;
2640 }
2641 bytes_per_sector = 512;
2642 sectors_per_unit = bsize/bytes_per_sector;
2643
2644 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2645 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2646 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2647
2648 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2649 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2650 SIVAL(pdata,l1_cUnit,dsize);
2651 SIVAL(pdata,l1_cUnitAvail,dfree);
2652 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2653 break;
2654 }
2655
2656 case SMB_INFO_VOLUME:
2657 /* Return volume name */
2658 /*
2659 * Add volume serial number - hash of a combination of
2660 * the called hostname and the service name.
2661 */
2662 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2663 /*
2664 * Win2k3 and previous mess this up by sending a name length
2665 * one byte short. I believe only older clients (OS/2 Win9x) use
2666 * this call so try fixing this by adding a terminating null to
2667 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2668 */
2669 len = srvstr_push(
2670 pdata, req->flags2,
2671 pdata+l2_vol_szVolLabel, vname,
2672 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2673 STR_NOALIGN|STR_TERMINATE);
2674 SCVAL(pdata,l2_vol_cch,len);
2675 data_len = l2_vol_szVolLabel + len;
2676 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2677 (unsigned)st.st_ctime, len, vname));
2678 break;
2679
2680 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2681 case SMB_FS_ATTRIBUTE_INFORMATION:
2682
2683 additional_flags = 0;
2684 #if defined(HAVE_SYS_QUOTAS)
2685 additional_flags |= FILE_VOLUME_QUOTAS;
2686 #endif
2687
2688 if(lp_nt_acl_support(SNUM(conn))) {
2689 additional_flags |= FILE_PERSISTENT_ACLS;
2690 }
2691
2692 /* Capabilities are filled in at connection time through STATVFS call */
2693 additional_flags |= conn->fs_capabilities;
2694 additional_flags |= lp_parm_int(conn->params->service,
2695 "share", "fake_fscaps",
2696 0);
2697
2698 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2699 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2700 additional_flags); /* FS ATTRIBUTES */
2701
2702 SIVAL(pdata,4,255); /* Max filename component length */
2703 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2704 and will think we can't do long filenames */
2705 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2706 PTR_DIFF(end_data, pdata+12),
2707 STR_UNICODE);
2708 SIVAL(pdata,8,len);
2709 data_len = 12 + len;
2710 break;
2711
2712 case SMB_QUERY_FS_LABEL_INFO:
2713 case SMB_FS_LABEL_INFORMATION:
2714 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2715 PTR_DIFF(end_data, pdata+4), 0);
2716 data_len = 4 + len;
2717 SIVAL(pdata,0,len);
2718 break;
2719
2720 case SMB_QUERY_FS_VOLUME_INFO:
2721 case SMB_FS_VOLUME_INFORMATION:
2722
2723 /*
2724 * Add volume serial number - hash of a combination of
2725 * the called hostname and the service name.
2726 */
2727 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2728 (str_checksum(get_local_machine_name())<<16));
2729
2730 /* Max label len is 32 characters. */
2731 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2732 PTR_DIFF(end_data, pdata+18),
2733 STR_UNICODE);
2734 SIVAL(pdata,12,len);
2735 data_len = 18+len;
2736
2737 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2738 (int)strlen(vname),vname, lp_servicename(snum)));
2739 break;
2740
2741 case SMB_QUERY_FS_SIZE_INFO:
2742 case SMB_FS_SIZE_INFORMATION:
2743 {
2744 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2745 data_len = 24;
2746 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2747 reply_unixerror(req, ERRHRD, ERRgeneral);
2748 return;
2749 }
2750 block_size = lp_block_size(snum);
2751 if (bsize < block_size) {
2752 uint64_t factor = block_size/bsize;
2753 bsize = block_size;
2754 dsize /= factor;
2755 dfree /= factor;
2756 }
2757 if (bsize > block_size) {
2758 uint64_t factor = bsize/block_size;
2759 bsize = block_size;
2760 dsize *= factor;
2761 dfree *= factor;
2762 }
2763 bytes_per_sector = 512;
2764 sectors_per_unit = bsize/bytes_per_sector;
2765 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2766 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2767 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2768 SBIG_UINT(pdata,0,dsize);
2769 SBIG_UINT(pdata,8,dfree);
2770 SIVAL(pdata,16,sectors_per_unit);
2771 SIVAL(pdata,20,bytes_per_sector);
2772 break;
2773 }
2774
2775 case SMB_FS_FULL_SIZE_INFORMATION:
2776 {
2777 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2778 data_len = 32;
2779 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2780 reply_unixerror(req, ERRHRD, ERRgeneral);
2781 return;
2782 }
2783 block_size = lp_block_size(snum);
2784 if (bsize < block_size) {
2785 uint64_t factor = block_size/bsize;
2786 bsize = block_size;
2787 dsize /= factor;
2788 dfree /= factor;
2789 }
2790 if (bsize > block_size) {
2791 uint64_t factor = bsize/block_size;
2792 bsize = block_size;
2793 dsize *= factor;
2794 dfree *= factor;
2795 }
2796 bytes_per_sector = 512;
2797 sectors_per_unit = bsize/bytes_per_sector;
2798 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2799 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2800 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2801 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2802 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2803 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2804 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2805 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2806 break;
2807 }
2808
2809 case SMB_QUERY_FS_DEVICE_INFO:
2810 case SMB_FS_DEVICE_INFORMATION:
2811 data_len = 8;
2812 SIVAL(pdata,0,0); /* dev type */
2813 SIVAL(pdata,4,0); /* characteristics */
2814 break;
2815
2816 #ifdef HAVE_SYS_QUOTAS
2817 case SMB_FS_QUOTA_INFORMATION:
2818 /*
2819 * what we have to send --metze:
2820 *
2821 * Unknown1: 24 NULL bytes
2822 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2823 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2824 * Quota Flags: 2 byte :
2825 * Unknown3: 6 NULL bytes
2826 *
2827 * 48 bytes total
2828 *
2829 * details for Quota Flags:
2830 *
2831 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2832 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2833 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2834 * 0x0001 Enable Quotas: enable quota for this fs
2835 *
2836 */
2837 {
2838 /* we need to fake up a fsp here,
2839 * because its not send in this call
2840 */
2841 files_struct fsp;
2842 SMB_NTQUOTA_STRUCT quotas;
2843
2844 ZERO_STRUCT(fsp);
2845 ZERO_STRUCT(quotas);
2846
2847 fsp.conn = conn;
2848 fsp.fnum = -1;
2849
2850 /* access check */
2851 if (conn->server_info->utok.uid != 0) {
2852 DEBUG(0,("set_user_quota: access_denied "
2853 "service [%s] user [%s]\n",
2854 lp_servicename(SNUM(conn)),
2855 conn->server_info->unix_name));
2856 reply_doserror(req, ERRDOS, ERRnoaccess);
2857 return;
2858 }
2859
2860 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2861 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2862 reply_doserror(req, ERRSRV, ERRerror);
2863 return;
2864 }
2865
2866 data_len = 48;
2867
2868 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2869
2870 /* Unknown1 24 NULL bytes*/
2871 SBIG_UINT(pdata,0,(uint64_t)0);
2872 SBIG_UINT(pdata,8,(uint64_t)0);
2873 SBIG_UINT(pdata,16,(uint64_t)0);
2874
2875 /* Default Soft Quota 8 bytes */
2876 SBIG_UINT(pdata,24,quotas.softlim);
2877
2878 /* Default Hard Quota 8 bytes */
2879 SBIG_UINT(pdata,32,quotas.hardlim);
2880
2881 /* Quota flag 2 bytes */
2882 SSVAL(pdata,40,quotas.qflags);
2883
2884 /* Unknown3 6 NULL bytes */
2885 SSVAL(pdata,42,0);
2886 SIVAL(pdata,44,0);
2887
2888 break;
2889 }
2890 #endif /* HAVE_SYS_QUOTAS */
2891 case SMB_FS_OBJECTID_INFORMATION:
2892 {
2893 unsigned char objid[16];
2894 struct smb_extended_info extended_info;
2895 memcpy(pdata,create_volume_objectid(conn, objid),16);
2896 samba_extended_info_version (&extended_info);
2897 SIVAL(pdata,16,extended_info.samba_magic);
2898 SIVAL(pdata,20,extended_info.samba_version);
2899 SIVAL(pdata,24,extended_info.samba_subversion);
2900 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2901 memcpy(pdata+36,extended_info.samba_version_string,28);
2902 data_len = 64;
2903 break;
2904 }
2905
2906 /*
2907 * Query the version and capabilities of the CIFS UNIX extensions
2908 * in use.
2909 */
2910
2911 case SMB_QUERY_CIFS_UNIX_INFO:
2912 {
2913 bool large_write = lp_min_receive_file_size() &&
2914 !srv_is_signing_active();
2915 bool large_read = !srv_is_signing_active();
2916 int encrypt_caps = 0;
2917
2918 if (!lp_unix_extensions()) {
2919 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2920 return;
2921 }
2922
2923 switch (conn->encrypt_level) {
2924 case 0:
2925 encrypt_caps = 0;
2926 break;
2927 case 1:
2928 case Auto:
2929 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2930 break;
2931 case Required:
2932 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2933 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2934 large_write = false;
2935 large_read = false;
2936 break;
2937 }
2938
2939 data_len = 12;
2940 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2941 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2942
2943 /* We have POSIX ACLs, pathname, encryption,
2944 * large read/write, and locking capability. */
2945
2946 SBIG_UINT(pdata,4,((uint64_t)(
2947 CIFS_UNIX_POSIX_ACLS_CAP|
2948 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2949 CIFS_UNIX_FCNTL_LOCKS_CAP|
2950 CIFS_UNIX_EXTATTR_CAP|
2951 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2952 encrypt_caps|
2953 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2954 (large_write ?
2955 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2956 break;
2957 }
2958
2959 case SMB_QUERY_POSIX_FS_INFO:
2960 {
2961 int rc;
2962 vfs_statvfs_struct svfs;
2963
2964 if (!lp_unix_extensions()) {
2965 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2966 return;
2967 }
2968
2969 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2970
2971 if (!rc) {
2972 data_len = 56;
2973 SIVAL(pdata,0,svfs.OptimalTransferSize);
2974 SIVAL(pdata,4,svfs.BlockSize);
2975 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2976 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2977 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2978 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2979 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2980 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2981 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2982 #ifdef EOPNOTSUPP
2983 } else if (rc == EOPNOTSUPP) {
2984 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2985 return;
2986 #endif /* EOPNOTSUPP */
2987 } else {
2988 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2989 reply_doserror(req, ERRSRV, ERRerror);
2990 return;
2991 }
2992 break;
2993 }
2994
2995 case SMB_QUERY_POSIX_WHOAMI:
2996 {
2997 uint32_t flags = 0;
2998 uint32_t sid_bytes;
2999 int i;
3000
3001 if (!lp_unix_extensions()) {
3002 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3003 return;
3004 }
3005
3006 if (max_data_bytes < 40) {
3007 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3008 return;
3009 }
3010
3011 /* We ARE guest if global_sid_Builtin_Guests is
3012 * in our list of SIDs.
3013 */
3014 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3015 conn->server_info->ptok)) {
3016 flags |= SMB_WHOAMI_GUEST;
3017 }
3018
3019 /* We are NOT guest if global_sid_Authenticated_Users
3020 * is in our list of SIDs.
3021 */
3022 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3023 conn->server_info->ptok)) {
3024 flags &= ~SMB_WHOAMI_GUEST;
3025 }
3026
3027 /* NOTE: 8 bytes for UID/GID, irrespective of native
3028 * platform size. This matches
3029 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3030 */
3031 data_len = 4 /* flags */
3032 + 4 /* flag mask */
3033 + 8 /* uid */
3034 + 8 /* gid */
3035 + 4 /* ngroups */
3036 + 4 /* num_sids */
3037 + 4 /* SID bytes */
3038 + 4 /* pad/reserved */
3039 + (conn->server_info->utok.ngroups * 8)
3040 /* groups list */
3041 + (conn->server_info->ptok->num_sids *
3042 SID_MAX_SIZE)
3043 /* SID list */;
3044
3045 SIVAL(pdata, 0, flags);
3046 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3047 SBIG_UINT(pdata, 8,
3048 (uint64_t)conn->server_info->utok.uid);
3049 SBIG_UINT(pdata, 16,
3050 (uint64_t)conn->server_info->utok.gid);
3051
3052
3053 if (data_len >= max_data_bytes) {
3054 /* Potential overflow, skip the GIDs and SIDs. */
3055
3056 SIVAL(pdata, 24, 0); /* num_groups */
3057 SIVAL(pdata, 28, 0); /* num_sids */
3058 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3059 SIVAL(pdata, 36, 0); /* reserved */
3060
3061 data_len = 40;
3062 break;
3063 }
3064
3065 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3066 SIVAL(pdata, 28, conn->server_info->num_sids);
3067
3068 /* We walk the SID list twice, but this call is fairly
3069 * infrequent, and I don't expect that it's performance
3070 * sensitive -- jpeach
3071 */
3072 for (i = 0, sid_bytes = 0;
3073 i < conn->server_info->ptok->num_sids; ++i) {
3074 sid_bytes += ndr_size_dom_sid(
3075 &conn->server_info->ptok->user_sids[i],
3076 NULL,
3077 0);
3078 }
3079
3080 /* SID list byte count */
3081 SIVAL(pdata, 32, sid_bytes);
3082
3083 /* 4 bytes pad/reserved - must be zero */
3084 SIVAL(pdata, 36, 0);
3085 data_len = 40;
3086
3087 /* GID list */
3088 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3089 SBIG_UINT(pdata, data_len,
3090 (uint64_t)conn->server_info->utok.groups[i]);
3091 data_len += 8;
3092 }
3093
3094 /* SID list */
3095 for (i = 0;
3096 i < conn->server_info->ptok->num_sids; ++i) {
3097 int sid_len = ndr_size_dom_sid(
3098 &conn->server_info->ptok->user_sids[i],
3099 NULL,
3100 0);
3101
3102 sid_linearize(pdata + data_len, sid_len,
3103 &conn->server_info->ptok->user_sids[i]);
3104 data_len += sid_len;
3105 }
3106
3107 break;
3108 }
3109
3110 case SMB_MAC_QUERY_FS_INFO:
3111 /*
3112 * Thursby MAC extension... ONLY on NTFS filesystems
3113 * once we do streams then we don't need this
3114 */
3115 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3116 data_len = 88;
3117 SIVAL(pdata,84,0x100); /* Don't support mac... */
3118 break;
3119 }
3120 /* drop through */
3121 default:
3122 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3123 return;
3124 }
3125
3126
3127 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3128 max_data_bytes);
3129
3130 DEBUG( 4, ( "%s info_level = %d\n",
3131 smb_fn_name(req->cmd), info_level) );
3132
3133 return;
3134 }
3135
3136 /****************************************************************************
3137 Reply to a TRANS2_SETFSINFO (set filesystem info).
3138 ****************************************************************************/
3139
3140 static void call_trans2setfsinfo(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
3141 struct smb_request *req,
3142 char **pparams, int total_params,
3143 char **ppdata, int total_data,
3144 unsigned int max_data_bytes)
3145 {
3146 char *pdata = *ppdata;
3147 char *params = *pparams;
3148 uint16 info_level;
3149
3150 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3151
3152 /* */
3153 if (total_params < 4) {
3154 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3155 total_params));
3156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3157 return;
3158 }
3159
3160 info_level = SVAL(params,2);
3161
3162 if (IS_IPC(conn)) {
3163 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3164 info_level != SMB_SET_CIFS_UNIX_INFO) {
3165 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3166 "info level (0x%x) on IPC$.\n",
3167 (unsigned int)info_level));
3168 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3169 return;
3170 }
3171 }
3172
3173 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3174 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3175 DEBUG(0,("call_trans2setfsinfo: encryption required "
3176 "and info level 0x%x sent.\n",
3177 (unsigned int)info_level));
3178 exit_server_cleanly("encryption required "
3179 "on connection");
3180 return;
3181 }
3182 }
3183
3184 switch(info_level) {
3185 case SMB_SET_CIFS_UNIX_INFO:
3186 {
3187 uint16 client_unix_major;
3188 uint16 client_unix_minor;
3189 uint32 client_unix_cap_low;
3190 uint32 client_unix_cap_high;
3191
3192 if (!lp_unix_extensions()) {
3193 reply_nterror(req,
3194 NT_STATUS_INVALID_LEVEL);
3195 return;
3196 }
3197
3198 /* There should be 12 bytes of capabilities set. */
3199 if (total_data < 8) {
3200 reply_nterror(
3201 req,
3202 NT_STATUS_INVALID_PARAMETER);
3203 return;
3204 }
3205 client_unix_major = SVAL(pdata,0);
3206 client_unix_minor = SVAL(pdata,2);
3207 client_unix_cap_low = IVAL(pdata,4);
3208 client_unix_cap_high = IVAL(pdata,8);
3209 /* Just print these values for now. */
3210 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3211 cap_low = 0x%x, cap_high = 0x%x\n",
3212 (unsigned int)client_unix_major,
3213 (unsigned int)client_unix_minor,
3214 (unsigned int)client_unix_cap_low,
3215 (unsigned int)client_unix_cap_high ));
3216
3217 /* Here is where we must switch to posix pathname processing... */
3218 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3219 lp_set_posix_pathnames();
3220 mangle_change_to_posix();
3221 }
3222
3223 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3224 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3225 /* Client that knows how to do posix locks,
3226 * but not posix open/mkdir operations. Set a
3227 * default type for read/write checks. */
3228
3229 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3230
3231 }
3232 break;
3233 }
3234
3235 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3236 {
3237 NTSTATUS status;
3238 size_t param_len = 0;
3239 size_t data_len = total_data;
3240
3241 if (!lp_unix_extensions()) {
3242 reply_nterror(
3243 req,
3244 NT_STATUS_INVALID_LEVEL);
3245 return;
3246 }
3247
3248 if (lp_smb_encrypt(SNUM(conn)) == false) {
3249 reply_nterror(
3250 req,
3251 NT_STATUS_NOT_SUPPORTED);
3252 return;
3253 }
3254
3255 DEBUG( 4,("call_trans2setfsinfo: "
3256 "request transport encryption.\n"));
3257
3258 status = srv_request_encryption_setup(conn,
3259 (unsigned char **)ppdata,
3260 &data_len,
3261 (unsigned char **)pparams,
3262 ¶m_len);
3263
3264 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3265 !NT_STATUS_IS_OK(status)) {
3266 reply_nterror(req, status);
3267 return;
3268 }
3269
3270 send_trans2_replies(conn, req,
3271 *pparams,
3272 param_len,
3273 *ppdata,
3274 data_len,
3275 max_data_bytes);
3276
3277 if (NT_STATUS_IS_OK(status)) {
3278 /* Server-side transport
3279 * encryption is now *on*. */
3280 status = srv_encryption_start(conn);
3281 if (!NT_STATUS_IS_OK(status)) {
3282 exit_server_cleanly(
3283 "Failure in setting "
3284 "up encrypted transport");
3285 }
3286 }
3287 return;
3288 }
3289
3290 case SMB_FS_QUOTA_INFORMATION:
3291 {
3292 files_struct *fsp = NULL;
3293 SMB_NTQUOTA_STRUCT quotas;
3294
3295 ZERO_STRUCT(quotas);
3296
3297 /* access check */
3298 if ((conn->server_info->utok.uid != 0)
3299 ||!CAN_WRITE(conn)) {
3300 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3301 lp_servicename(SNUM(conn)),
3302 conn->server_info->unix_name));
3303 reply_doserror(req, ERRSRV, ERRaccess);
3304 return;
3305 }
3306
3307 /* note: normaly there're 48 bytes,
3308 * but we didn't use the last 6 bytes for now
3309 * --metze
3310 */
3311 fsp = file_fsp(req, SVAL(params,0));
3312
3313 if (!check_fsp_ntquota_handle(conn, req,
3314 fsp)) {
3315 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3316 reply_nterror(
3317 req, NT_STATUS_INVALID_HANDLE);
3318 return;
3319 }
3320
3321 if (total_data < 42) {
3322 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3323 total_data));
3324 reply_nterror(
3325 req,
3326 NT_STATUS_INVALID_PARAMETER);
3327 return;
3328 }
3329
3330 /* unknown_1 24 NULL bytes in pdata*/
3331
3332 /* the soft quotas 8 bytes (uint64_t)*/
3333 quotas.softlim = (uint64_t)IVAL(pdata,24);
3334 #ifdef LARGE_SMB_OFF_T
3335 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3336 #else /* LARGE_SMB_OFF_T */
3337 if ((IVAL(pdata,28) != 0)&&
3338 ((quotas.softlim != 0xFFFFFFFF)||
3339 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3340 /* more than 32 bits? */
3341 reply_nterror(
3342 req,
3343 NT_STATUS_INVALID_PARAMETER);
3344 return;
3345 }
3346 #endif /* LARGE_SMB_OFF_T */
3347
3348 /* the hard quotas 8 bytes (uint64_t)*/
3349 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3350 #ifdef LARGE_SMB_OFF_T
3351 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3352 #else /* LARGE_SMB_OFF_T */
3353 if ((IVAL(pdata,36) != 0)&&
3354 ((quotas.hardlim != 0xFFFFFFFF)||
3355 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3356 /* more than 32 bits? */
3357 reply_nterror(
3358 req,
3359 NT_STATUS_INVALID_PARAMETER);
3360 return;
3361 }
3362 #endif /* LARGE_SMB_OFF_T */
3363
3364 /* quota_flags 2 bytes **/
3365 quotas.qflags = SVAL(pdata,40);
3366
3367 /* unknown_2 6 NULL bytes follow*/
3368
3369 /* now set the quotas */
3370 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3371 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3372 reply_doserror(req, ERRSRV, ERRerror);
3373 return;
3374 }
3375
3376 break;
3377 }
3378 default:
3379 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3380 info_level));
3381 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3382 return;
3383 break;
3384 }
3385
3386 /*
3387 * sending this reply works fine,
3388 * but I'm not sure it's the same
3389 * like windows do...
3390 * --metze
3391 */
3392 reply_outbuf(req, 10, 0);
3393 }
3394
3395 #if defined(HAVE_POSIX_ACLS)
3396 /****************************************************************************
3397 Utility function to count the number of entries in a POSIX acl.
3398 ****************************************************************************/
3399
3400 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
/* [<][>][^][v][top][bottom][index][help] */
3401 {
3402 unsigned int ace_count = 0;
3403 int entry_id = SMB_ACL_FIRST_ENTRY;
3404 SMB_ACL_ENTRY_T entry;
3405
3406 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3407 /* get_next... */
3408 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3409 entry_id = SMB_ACL_NEXT_ENTRY;
3410 }
3411 ace_count++;
3412 }
3413 return ace_count;
3414 }
3415
3416 /****************************************************************************
3417 Utility function to marshall a POSIX acl into wire format.
3418 ****************************************************************************/
3419
3420 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
/* [<][>][^][v][top][bottom][index][help] */
3421 {
3422 int entry_id = SMB_ACL_FIRST_ENTRY;
3423 SMB_ACL_ENTRY_T entry;
3424
3425 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3426 SMB_ACL_TAG_T tagtype;
3427 SMB_ACL_PERMSET_T permset;
3428 unsigned char perms = 0;
3429 unsigned int own_grp;
3430
3431 /* get_next... */
3432 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3433 entry_id = SMB_ACL_NEXT_ENTRY;
3434 }
3435
3436 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3437 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3438 return False;
3439 }
3440
3441 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3442 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3443 return False;
3444 }
3445
3446 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3447 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3448 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3449
3450 SCVAL(pdata,1,perms);
3451
3452 switch (tagtype) {
3453 case SMB_ACL_USER_OBJ:
3454 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3455 own_grp = (unsigned int)pst->st_uid;
3456 SIVAL(pdata,2,own_grp);
3457 SIVAL(pdata,6,0);
3458 break;
3459 case SMB_ACL_USER:
3460 {
3461 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3462 if (!puid) {
3463 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3464 return False;
3465 }
3466 own_grp = (unsigned int)*puid;
3467 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3468 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3469 SIVAL(pdata,2,own_grp);
3470 SIVAL(pdata,6,0);
3471 break;
3472 }
3473 case SMB_ACL_GROUP_OBJ:
3474 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3475 own_grp = (unsigned int)pst->st_gid;
3476 SIVAL(pdata,2,own_grp);
3477 SIVAL(pdata,6,0);
3478 break;
3479 case SMB_ACL_GROUP:
3480 {
3481 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3482 if (!pgid) {
3483 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3484 return False;
3485 }
3486 own_grp = (unsigned int)*pgid;
3487 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3488 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3489 SIVAL(pdata,2,own_grp);
3490 SIVAL(pdata,6,0);
3491 break;
3492 }
3493 case SMB_ACL_MASK:
3494 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3495 SIVAL(pdata,2,0xFFFFFFFF);
3496 SIVAL(pdata,6,0xFFFFFFFF);
3497 break;
3498 case SMB_ACL_OTHER:
3499 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3500 SIVAL(pdata,2,0xFFFFFFFF);
3501 SIVAL(pdata,6,0xFFFFFFFF);
3502 break;
3503 default:
3504 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3505 return False;
3506 }
3507 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3508 }
3509
3510 return True;
3511 }
3512 #endif
3513
3514 /****************************************************************************
3515 Store the FILE_UNIX_BASIC info.
3516 ****************************************************************************/
3517
3518 static char *store_file_unix_basic(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
3519 char *pdata,
3520 files_struct *fsp,
3521 const SMB_STRUCT_STAT *psbuf)
3522 {
3523 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3524 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3525
3526 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3527 pdata += 8;
3528
3529 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3530 pdata += 8;
3531
3532 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3533 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3534 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3535 pdata += 24;
3536
3537 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3538 SIVAL(pdata,4,0);
3539 pdata += 8;
3540
3541 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3542 SIVAL(pdata,4,0);
3543 pdata += 8;
3544
3545 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3546 pdata += 4;
3547
3548 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3549 SIVAL(pdata,4,0);
3550 pdata += 8;
3551
3552 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3553 SIVAL(pdata,4,0);
3554 pdata += 8;
3555
3556 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3557 pdata += 8;
3558
3559 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3560 SIVAL(pdata,4,0);
3561 pdata += 8;
3562
3563 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3564 SIVAL(pdata,4,0);
3565 pdata += 8;
3566
3567 return pdata;
3568 }
3569
3570 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3571 * the chflags(2) (or equivalent) flags.
3572 *
3573 * XXX: this really should be behind the VFS interface. To do this, we would
3574 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3575 * Each VFS module could then implement its own mapping as appropriate for the
3576 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3577 */
3578 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3579 info2_flags_map[] =
3580 {
3581 #ifdef UF_NODUMP
3582 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3583 #endif
3584
3585 #ifdef UF_IMMUTABLE
3586 { UF_IMMUTABLE, EXT_IMMUTABLE },
3587 #endif
3588
3589 #ifdef UF_APPEND
3590 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3591 #endif
3592
3593 #ifdef UF_HIDDEN
3594 { UF_HIDDEN, EXT_HIDDEN },
3595 #endif
3596
3597 /* Do not remove. We need to guarantee that this array has at least one
3598 * entry to build on HP-UX.
3599 */
3600 { 0, 0 }
3601
3602 };
3603
3604 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
/* [<][>][^][v][top][bottom][index][help] */
3605 uint32 *smb_fflags, uint32 *smb_fmask)
3606 {
3607 #ifdef HAVE_STAT_ST_FLAGS
3608 int i;
3609
3610 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3611 *smb_fmask |= info2_flags_map[i].smb_fflag;
3612 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3613 *smb_fflags |= info2_flags_map[i].smb_fflag;
3614 }
3615 }
3616 #endif /* HAVE_STAT_ST_FLAGS */
3617 }
3618
3619 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
/* [<][>][^][v][top][bottom][index][help] */
3620 const uint32 smb_fflags,
3621 const uint32 smb_fmask,
3622 int *stat_fflags)
3623 {
3624 #ifdef HAVE_STAT_ST_FLAGS
3625 uint32 max_fmask = 0;
3626 int i;
3627
3628 *stat_fflags = psbuf->st_flags;
3629
3630 /* For each flags requested in smb_fmask, check the state of the
3631 * corresponding flag in smb_fflags and set or clear the matching
3632 * stat flag.
3633 */
3634
3635 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3636 max_fmask |= info2_flags_map[i].smb_fflag;
3637 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3638 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3639 *stat_fflags |= info2_flags_map[i].stat_fflag;
3640 } else {
3641 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3642 }
3643 }
3644 }
3645
3646 /* If smb_fmask is asking to set any bits that are not supported by
3647 * our flag mappings, we should fail.
3648 */
3649 if ((smb_fmask & max_fmask) != smb_fmask) {
3650 return False;
3651 }
3652
3653 return True;
3654 #else
3655 return False;
3656 #endif /* HAVE_STAT_ST_FLAGS */
3657 }
3658
3659
3660 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3661 * of file flags and birth (create) time.
3662 */
3663 static char *store_file_unix_basic_info2(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
3664 char *pdata,
3665 files_struct *fsp,
3666 const SMB_STRUCT_STAT *psbuf)
3667 {
3668 uint32 file_flags = 0;
3669 uint32 flags_mask = 0;
3670
3671 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3672
3673 /* Create (birth) time 64 bit */
3674 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, get_create_timespec(psbuf, False));
3675 pdata += 8;
3676
3677 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3678 SIVAL(pdata, 0, file_flags); /* flags */
3679 SIVAL(pdata, 4, flags_mask); /* mask */
3680 pdata += 8;
3681
3682 return pdata;
3683 }
3684
3685 static NTSTATUS marshall_stream_info(unsigned int num_streams,
/* [<][>][^][v][top][bottom][index][help] */
3686 const struct stream_struct *streams,
3687 char *data,
3688 unsigned int max_data_bytes,
3689 unsigned int *data_size)
3690 {
3691 unsigned int i;
3692 unsigned int ofs = 0;
3693
3694 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3695 unsigned int next_offset;
3696 size_t namelen;
3697 smb_ucs2_t *namebuf;
3698
3699 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3700 streams[i].name, &namelen) ||
3701 namelen <= 2)
3702 {
3703 return NT_STATUS_INVALID_PARAMETER;
3704 }
3705
3706 /*
3707 * name_buf is now null-terminated, we need to marshall as not
3708 * terminated
3709 */
3710
3711 namelen -= 2;
3712
3713 SIVAL(data, ofs+4, namelen);
3714 SOFF_T(data, ofs+8, streams[i].size);
3715 SOFF_T(data, ofs+16, streams[i].alloc_size);
3716 memcpy(data+ofs+24, namebuf, namelen);
3717 TALLOC_FREE(namebuf);
3718
3719 next_offset = ofs + 24 + namelen;
3720
3721 if (i == num_streams-1) {
3722 SIVAL(data, ofs, 0);
3723 }
3724 else {
3725 unsigned int align = ndr_align_size(next_offset, 8);
3726
3727 memset(data+next_offset, 0, align);
3728 next_offset += align;
3729
3730 SIVAL(data, ofs, next_offset - ofs);
3731 ofs = next_offset;
3732 }
3733
3734 ofs = next_offset;
3735 }
3736
3737 *data_size = ofs;
3738
3739 return NT_STATUS_OK;
3740 }
3741
3742 /****************************************************************************
3743 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3744 ****************************************************************************/
3745
3746 static void call_trans2qpipeinfo(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
3747 struct smb_request *req,
3748 unsigned int tran_call,
3749 char **pparams, int total_params,
3750 char **ppdata, int total_data,
3751 unsigned int max_data_bytes)
3752 {
3753 char *params = *pparams;
3754 char *pdata = *ppdata;
3755 unsigned int data_size = 0;
3756 unsigned int param_size = 2;
3757 uint16 info_level;
3758 files_struct *fsp;
3759
3760 if (!params) {
3761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3762 return;
3763 }
3764
3765 if (total_params < 4) {
3766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3767 return;
3768 }
3769
3770 fsp = file_fsp(req, SVAL(params,0));
3771 if (!fsp_is_np(fsp)) {
3772 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3773 return;
3774 }
3775
3776 info_level = SVAL(params,2);
3777
3778 *pparams = (char *)SMB_REALLOC(*pparams,2);
3779 if (*pparams == NULL) {
3780 reply_nterror(req, NT_STATUS_NO_MEMORY);
3781 return;
3782 }
3783 params = *pparams;
3784 SSVAL(params,0,0);
3785 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3786 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3787 if (*ppdata == NULL ) {
3788 reply_nterror(req, NT_STATUS_NO_MEMORY);
3789 return;
3790 }
3791 pdata = *ppdata;
3792
3793 switch (info_level) {
3794 case SMB_FILE_STANDARD_INFORMATION:
3795 memset(pdata,0,24);
3796 SOFF_T(pdata,0,4096LL);
3797 SIVAL(pdata,16,1);
3798 SIVAL(pdata,20,1);
3799 data_size = 24;
3800 break;
3801
3802 default:
3803 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3804 return;
3805 }
3806
3807 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3808 max_data_bytes);
3809
3810 return;
3811 }
3812
3813 /****************************************************************************
3814 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3815 file name or file id).
3816 ****************************************************************************/
3817
3818 static void call_trans2qfilepathinfo(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
3819 struct smb_request *req,
3820 unsigned int tran_call,
3821 char **pparams, int total_params,
3822 char **ppdata, int total_data,
3823 unsigned int max_data_bytes)
3824 {
3825 char *params = *pparams;
3826 char *pdata = *ppdata;
3827 char *dstart, *dend;
3828 uint16 info_level;
3829 int mode=0;
3830 int nlink;
3831 SMB_OFF_T file_size=0;
3832 uint64_t allocation_size=0;
3833 unsigned int data_size = 0;
3834 unsigned int param_size = 2;
3835 SMB_STRUCT_STAT sbuf;
3836 char *dos_fname = NULL;
3837 char *fname = NULL;
3838 char *fullpathname;
3839 char *base_name;
3840 char *p;
3841 SMB_OFF_T pos = 0;
3842 bool delete_pending = False;
3843 int len;
3844 time_t create_time, mtime, atime;
3845 struct timespec create_time_ts, mtime_ts, atime_ts;
3846 struct timespec write_time_ts;
3847 files_struct *fsp = NULL;
3848 struct file_id fileid;
3849 struct ea_list *ea_list = NULL;
3850 char *lock_data = NULL;
3851 bool ms_dfs_link = false;
3852 TALLOC_CTX *ctx = talloc_tos();
3853
3854 if (!params) {
3855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3856 return;
3857 }
3858
3859 ZERO_STRUCT(sbuf);
3860 ZERO_STRUCT(write_time_ts);
3861
3862 if (tran_call == TRANSACT2_QFILEINFO) {
3863 if (total_params < 4) {
3864 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3865 return;
3866 }
3867
3868 if (IS_IPC(conn)) {
3869 call_trans2qpipeinfo(conn, req, tran_call,
3870 pparams, total_params,
3871 ppdata, total_data,
3872 max_data_bytes);
3873 return;
3874 }
3875
3876 fsp = file_fsp(req, SVAL(params,0));
3877 info_level = SVAL(params,2);
3878
3879 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3880
3881 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3882 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3883 return;
3884 }
3885
3886 /* Initial check for valid fsp ptr. */
3887 if (!check_fsp_open(conn, req, fsp)) {
3888 return;
3889 }
3890
3891 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3892 if (!fname) {
3893 reply_nterror(req, NT_STATUS_NO_MEMORY);
3894 return;
3895 }
3896
3897 if(fsp->fake_file_handle) {
3898 /*
3899 * This is actually for the QUOTA_FAKE_FILE --metze
3900 */
3901
3902 /* We know this name is ok, it's already passed the checks. */
3903
3904 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3905 /*
3906 * This is actually a QFILEINFO on a directory
3907 * handle (returned from an NT SMB). NT5.0 seems
3908 * to do this call. JRA.
3909 */
3910
3911 if (INFO_LEVEL_IS_UNIX(info_level)) {
3912 /* Always do lstat for UNIX calls. */
3913 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3914 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3915 reply_unixerror(req,ERRDOS,ERRbadpath);
3916 return;
3917 }
3918 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3919 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3920 reply_unixerror(req, ERRDOS, ERRbadpath);
3921 return;
3922 }
3923
3924 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3925 get_file_infos(fileid, &delete_pending, &write_time_ts);
3926 } else {
3927 /*
3928 * Original code - this is an open file.
3929 */
3930 if (!check_fsp(conn, req, fsp)) {
3931 return;
3932 }
3933
3934 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3935 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3936 reply_unixerror(req, ERRDOS, ERRbadfid);
3937 return;
3938 }
3939 pos = fsp->fh->position_information;
3940 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3941 get_file_infos(fileid, &delete_pending, &write_time_ts);
3942 }
3943
3944 } else {
3945 NTSTATUS status = NT_STATUS_OK;
3946
3947 /* qpathinfo */
3948 if (total_params < 7) {
3949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3950 return;
3951 }
3952
3953 info_level = SVAL(params,0);
3954
3955 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3956
3957 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3958 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3959 return;
3960 }
3961
3962 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3963 total_params - 6,
3964 STR_TERMINATE, &status);
3965 if (!NT_STATUS_IS_OK(status)) {
3966 reply_nterror(req, status);
3967 return;
3968 }
3969
3970 status = resolve_dfspath(ctx,
3971 conn,
3972 req->flags2 & FLAGS2_DFS_PATHNAMES,
3973 fname,
3974 &fname);
3975 if (!NT_STATUS_IS_OK(status)) {
3976 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3977 reply_botherror(req,
3978 NT_STATUS_PATH_NOT_COVERED,
3979 ERRSRV, ERRbadpath);
3980 }
3981 reply_nterror(req, status);
3982 return;
3983 }
3984
3985 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3986 if (!NT_STATUS_IS_OK(status)) {
3987 reply_nterror(req, status);
3988 return;
3989 }
3990 status = check_name(conn, fname);
3991 if (!NT_STATUS_IS_OK(status)) {
3992 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3993 reply_nterror(req, status);
3994 return;
3995 }
3996
3997 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3998 && is_ntfs_stream_name(fname)) {
3999 char *base;
4000 SMB_STRUCT_STAT bsbuf;
4001
4002 status = split_ntfs_stream_name(talloc_tos(), fname,
4003 &base, NULL);
4004 if (!NT_STATUS_IS_OK(status)) {
4005 DEBUG(10, ("create_file_unixpath: "
4006 "split_ntfs_stream_name failed: %s\n",
4007 nt_errstr(status)));
4008 reply_nterror(req, status);
4009 return;
4010 }
4011
4012 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4013
4014 if (INFO_LEVEL_IS_UNIX(info_level)) {
4015 /* Always do lstat for UNIX calls. */
4016 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4017 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4018 reply_unixerror(req,ERRDOS,ERRbadpath);
4019 return;
4020 }
4021 } else {
4022 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4023 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4024 reply_unixerror(req,ERRDOS,ERRbadpath);
4025 return;
4026 }
4027 }
4028
4029 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4030 get_file_infos(fileid, &delete_pending, NULL);
4031 if (delete_pending) {
4032 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4033 return;
4034 }
4035 }
4036
4037 if (INFO_LEVEL_IS_UNIX(info_level)) {
4038 /* Always do lstat for UNIX calls. */
4039 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4040 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4041 reply_unixerror(req, ERRDOS, ERRbadpath);
4042 return;
4043 }
4044
4045 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4046 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4047
4048 if (!ms_dfs_link) {
4049 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4050 reply_unixerror(req, ERRDOS, ERRbadpath);
4051 return;
4052 }
4053 }
4054
4055 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4056 get_file_infos(fileid, &delete_pending, &write_time_ts);
4057 if (delete_pending) {
4058 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4059 return;
4060 }
4061 }
4062
4063 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4064 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4065 return;
4066 }
4067
4068 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4069 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4070
4071 p = strrchr_m(fname,'/');
4072 if (!p)
4073 base_name = fname;
4074 else
4075 base_name = p+1;
4076
4077 if (ms_dfs_link) {
4078 mode = dos_mode_msdfs(conn,fname,&sbuf);
4079 } else {
4080 mode = dos_mode(conn,fname,&sbuf);
4081 }
4082 if (!mode)
4083 mode = FILE_ATTRIBUTE_NORMAL;
4084
4085 nlink = sbuf.st_nlink;
4086
4087 if (nlink && (mode&aDIR)) {
4088 nlink = 1;
4089 }
4090
4091 if ((nlink > 0) && delete_pending) {
4092 nlink -= 1;
4093 }
4094
4095 fullpathname = fname;
4096 if (!(mode & aDIR))
4097 file_size = get_file_size_stat(&sbuf);
4098
4099 /* Pull out any data sent here before we realloc. */
4100 switch (info_level) {
4101 case SMB_INFO_QUERY_EAS_FROM_LIST:
4102 {
4103 /* Pull any EA list from the data portion. */
4104 uint32 ea_size;
4105
4106 if (total_data < 4) {
4107 reply_nterror(
4108 req, NT_STATUS_INVALID_PARAMETER);
4109 return;
4110 }
4111 ea_size = IVAL(pdata,0);
4112
4113 if (total_data > 0 && ea_size != total_data) {
4114 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4115 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4116 reply_nterror(
4117 req, NT_STATUS_INVALID_PARAMETER);
4118 return;
4119 }
4120
4121 if (!lp_ea_support(SNUM(conn))) {
4122 reply_doserror(req, ERRDOS,
4123 ERReasnotsupported);
4124 return;
4125 }
4126
4127 /* Pull out the list of names. */
4128 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4129 if (!ea_list) {
4130 reply_nterror(
4131 req, NT_STATUS_INVALID_PARAMETER);
4132 return;
4133 }
4134 break;
4135 }
4136
4137 case SMB_QUERY_POSIX_LOCK:
4138 {
4139 if (fsp == NULL || fsp->fh->fd == -1) {
4140 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4141 return;
4142 }
4143
4144 if (total_data != POSIX_LOCK_DATA_SIZE) {
4145 reply_nterror(
4146 req, NT_STATUS_INVALID_PARAMETER);
4147 return;
4148 }
4149
4150 /* Copy the lock range data. */
4151 lock_data = (char *)TALLOC_MEMDUP(
4152 ctx, pdata, total_data);
4153 if (!lock_data) {
4154 reply_nterror(req, NT_STATUS_NO_MEMORY);
4155 return;
4156 }
4157 }
4158 default:
4159 break;
4160 }
4161
4162 *pparams = (char *)SMB_REALLOC(*pparams,2);
4163 if (*pparams == NULL) {
4164 reply_nterror(req, NT_STATUS_NO_MEMORY);
4165 return;
4166 }
4167 params = *pparams;
4168 SSVAL(params,0,0);
4169 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4170 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4171 if (*ppdata == NULL ) {
4172 reply_nterror(req, NT_STATUS_NO_MEMORY);
4173 return;
4174 }
4175 pdata = *ppdata;
4176 dstart = pdata;
4177 dend = dstart + data_size - 1;
4178
4179 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4180 mtime_ts = get_mtimespec(&sbuf);
4181 atime_ts = get_atimespec(&sbuf);
4182
4183 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4184
4185 if (!fsp) {
4186 /* Do we have this path open ? */
4187 files_struct *fsp1;
4188 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4189 fsp1 = file_find_di_first(fileid);
4190 if (fsp1 && fsp1->initial_allocation_size) {
4191 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4192 }
4193 }
4194
4195 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4196 mtime_ts = write_time_ts;
4197 }
4198
4199 if (lp_dos_filetime_resolution(SNUM(conn))) {
4200 dos_filetime_timespec(&create_time_ts);
4201 dos_filetime_timespec(&mtime_ts);
4202 dos_filetime_timespec(&atime_ts);
4203 }
4204
4205 create_time = convert_timespec_to_time_t(create_time_ts);
4206 mtime = convert_timespec_to_time_t(mtime_ts);
4207 atime = convert_timespec_to_time_t(atime_ts);
4208
4209 /* NT expects the name to be in an exact form of the *full*
4210 filename. See the trans2 torture test */
4211 if (ISDOT(base_name)) {
4212 dos_fname = talloc_strdup(ctx, "\\");
4213 if (!dos_fname) {
4214 reply_nterror(req, NT_STATUS_NO_MEMORY);
4215 return;
4216 }
4217 } else {
4218 dos_fname = talloc_asprintf(ctx,
4219 "\\%s",
4220 fname);
4221 if (!dos_fname) {
4222 reply_nterror(req, NT_STATUS_NO_MEMORY);
4223 return;
4224 }
4225 string_replace(dos_fname, '/', '\\');
4226 }
4227
4228 switch (info_level) {
4229 case SMB_INFO_STANDARD:
4230 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4231 data_size = 22;
4232 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4233 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4234 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4235 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4236 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4237 SSVAL(pdata,l1_attrFile,mode);
4238 break;
4239
4240 case SMB_INFO_QUERY_EA_SIZE:
4241 {
4242 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4243 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4244 data_size = 26;
4245 srv_put_dos_date2(pdata,0,create_time);
4246 srv_put_dos_date2(pdata,4,atime);
4247 srv_put_dos_date2(pdata,8,mtime); /* write time */
4248 SIVAL(pdata,12,(uint32)file_size);
4249 SIVAL(pdata,16,(uint32)allocation_size);
4250 SSVAL(pdata,20,mode);
4251 SIVAL(pdata,22,ea_size);
4252 break;
4253 }
4254
4255 case SMB_INFO_IS_NAME_VALID:
4256 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4257 if (tran_call == TRANSACT2_QFILEINFO) {
4258 /* os/2 needs this ? really ?*/
4259 reply_doserror(req, ERRDOS, ERRbadfunc);
4260 return;
4261 }
4262 data_size = 0;
4263 param_size = 0;
4264 break;
4265
4266 case SMB_INFO_QUERY_EAS_FROM_LIST:
4267 {
4268 size_t total_ea_len = 0;
4269 struct ea_list *ea_file_list = NULL;
4270
4271 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4272
4273 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4274 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4275
4276 if (!ea_list || (total_ea_len > data_size)) {
4277 data_size = 4;
4278 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4279 break;
4280 }
4281
4282 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4283 break;
4284 }
4285
4286 case SMB_INFO_QUERY_ALL_EAS:
4287 {
4288 /* We have data_size bytes to put EA's into. */
4289 size_t total_ea_len = 0;
4290
4291 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4292
4293 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4294 if (!ea_list || (total_ea_len > data_size)) {
4295 data_size = 4;
4296 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4297 break;
4298 }
4299
4300 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4301 break;
4302 }
4303
4304 case SMB_FILE_BASIC_INFORMATION:
4305 case SMB_QUERY_FILE_BASIC_INFO:
4306
4307 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4308 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4309 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4310 } else {
4311 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4312 data_size = 40;
4313 SIVAL(pdata,36,0);
4314 }
4315 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4316 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4317 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4318 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4319 SIVAL(pdata,32,mode);
4320
4321 DEBUG(5,("SMB_QFBI - "));
4322 DEBUG(5,("create: %s ", ctime(&create_time)));
4323 DEBUG(5,("access: %s ", ctime(&atime)));
4324 DEBUG(5,("write: %s ", ctime(&mtime)));
4325 DEBUG(5,("change: %s ", ctime(&mtime)));
4326 DEBUG(5,("mode: %x\n", mode));
4327 break;
4328
4329 case SMB_FILE_STANDARD_INFORMATION:
4330 case SMB_QUERY_FILE_STANDARD_INFO:
4331
4332 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4333 data_size = 24;
4334 SOFF_T(pdata,0,allocation_size);
4335 SOFF_T(pdata,8,file_size);
4336 SIVAL(pdata,16,nlink);
4337 SCVAL(pdata,20,delete_pending?1:0);
4338 SCVAL(pdata,21,(mode&aDIR)?1:0);
4339 SSVAL(pdata,22,0); /* Padding. */
4340 break;
4341
4342 case SMB_FILE_EA_INFORMATION:
4343 case SMB_QUERY_FILE_EA_INFO:
4344 {
4345 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4346 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4347 data_size = 4;
4348 SIVAL(pdata,0,ea_size);
4349 break;
4350 }
4351
4352 /* Get the 8.3 name - used if NT SMB was negotiated. */
4353 case SMB_QUERY_FILE_ALT_NAME_INFO:
4354 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4355 {
4356 char mangled_name[13];
4357 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4358 if (!name_to_8_3(base_name,mangled_name,
4359 True,conn->params)) {
4360 reply_nterror(
4361 req,
4362 NT_STATUS_NO_MEMORY);
4363 }
4364 len = srvstr_push(dstart, req->flags2,
4365 pdata+4, mangled_name,
4366 PTR_DIFF(dend, pdata+4),
4367 STR_UNICODE);
4368 data_size = 4 + len;
4369 SIVAL(pdata,0,len);
4370 break;
4371 }
4372
4373 case SMB_QUERY_FILE_NAME_INFO:
4374 /*
4375 this must be *exactly* right for ACLs on mapped drives to work
4376 */
4377 len = srvstr_push(dstart, req->flags2,
4378 pdata+4, dos_fname,
4379 PTR_DIFF(dend, pdata+4),
4380 STR_UNICODE);
4381 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4382 data_size = 4 + len;
4383 SIVAL(pdata,0,len);
4384 break;
4385
4386 case SMB_FILE_ALLOCATION_INFORMATION:
4387 case SMB_QUERY_FILE_ALLOCATION_INFO:
4388 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4389 data_size = 8;
4390 SOFF_T(pdata,0,allocation_size);
4391 break;
4392
4393 case SMB_FILE_END_OF_FILE_INFORMATION:
4394 case SMB_QUERY_FILE_END_OF_FILEINFO:
4395 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4396 data_size = 8;
4397 SOFF_T(pdata,0,file_size);
4398 break;
4399
4400 case SMB_QUERY_FILE_ALL_INFO:
4401 case SMB_FILE_ALL_INFORMATION:
4402 {
4403 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4404 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4405 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4406 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4407 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4408 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4409 SIVAL(pdata,32,mode);
4410 SIVAL(pdata,36,0); /* padding. */
4411 pdata += 40;
4412 SOFF_T(pdata,0,allocation_size);
4413 SOFF_T(pdata,8,file_size);
4414 SIVAL(pdata,16,nlink);
4415 SCVAL(pdata,20,delete_pending);
4416 SCVAL(pdata,21,(mode&aDIR)?1:0);
4417 SSVAL(pdata,22,0);
4418 pdata += 24;
4419 SIVAL(pdata,0,ea_size);
4420 pdata += 4; /* EA info */
4421 len = srvstr_push(dstart, req->flags2,
4422 pdata+4, dos_fname,
4423 PTR_DIFF(dend, pdata+4),
4424 STR_UNICODE);
4425 SIVAL(pdata,0,len);
4426 pdata += 4 + len;
4427 data_size = PTR_DIFF(pdata,(*ppdata));
4428 break;
4429 }
4430 case SMB_FILE_INTERNAL_INFORMATION:
4431 /* This should be an index number - looks like
4432 dev/ino to me :-)
4433
4434 I think this causes us to fail the IFSKIT
4435 BasicFileInformationTest. -tpot */
4436
4437 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4438 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4439 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4440 data_size = 8;
4441 break;
4442
4443 case SMB_FILE_ACCESS_INFORMATION:
4444 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4445 if (fsp) {
4446 SIVAL(pdata,0,fsp->access_mask);
4447 } else {
4448 /* GENERIC_EXECUTE mapping from Windows */
4449 SIVAL(pdata,0,0x12019F);
4450 }
4451 data_size = 4;
4452 break;
4453
4454 case SMB_FILE_NAME_INFORMATION:
4455 /* Pathname with leading '\'. */
4456 {
4457 size_t byte_len;
4458 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4459 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4460 SIVAL(pdata,0,byte_len);
4461 data_size = 4 + byte_len;
4462 break;
4463 }
4464
4465 case SMB_FILE_DISPOSITION_INFORMATION:
4466 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4467 data_size = 1;
4468 SCVAL(pdata,0,delete_pending);
4469 break;
4470
4471 case SMB_FILE_POSITION_INFORMATION:
4472 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4473 data_size = 8;
4474 SOFF_T(pdata,0,pos);
4475 break;
4476
4477 case SMB_FILE_MODE_INFORMATION:
4478 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4479 SIVAL(pdata,0,mode);
4480 data_size = 4;
4481 break;
4482
4483 case SMB_FILE_ALIGNMENT_INFORMATION:
4484 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4485 SIVAL(pdata,0,0); /* No alignment needed. */
4486 data_size = 4;
4487 break;
4488
4489 /*
4490 * NT4 server just returns "invalid query" to this - if we try
4491 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4492 * want this. JRA.
4493 */
4494 /* The first statement above is false - verified using Thursby
4495 * client against NT4 -- gcolley.
4496 */
4497 case SMB_QUERY_FILE_STREAM_INFO:
4498 case SMB_FILE_STREAM_INFORMATION: {
4499 unsigned int num_streams;
4500 struct stream_struct *streams;
4501 NTSTATUS status;
4502
4503 DEBUG(10,("call_trans2qfilepathinfo: "
4504 "SMB_FILE_STREAM_INFORMATION\n"));
4505
4506 status = SMB_VFS_STREAMINFO(
4507 conn, fsp, fname, talloc_tos(),
4508 &num_streams, &streams);
4509
4510 if (!NT_STATUS_IS_OK(status)) {
4511 DEBUG(10, ("could not get stream info: %s\n",
4512 nt_errstr(status)));
4513 reply_nterror(req, status);
4514 return;
4515 }
4516
4517 status = marshall_stream_info(num_streams, streams,
4518 pdata, max_data_bytes,
4519 &data_size);
4520
4521 if (!NT_STATUS_IS_OK(status)) {
4522 DEBUG(10, ("marshall_stream_info failed: %s\n",
4523 nt_errstr(status)));
4524 reply_nterror(req, status);
4525 return;
4526 }
4527
4528 TALLOC_FREE(streams);
4529
4530 break;
4531 }
4532 case SMB_QUERY_COMPRESSION_INFO:
4533 case SMB_FILE_COMPRESSION_INFORMATION:
4534 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4535 SOFF_T(pdata,0,file_size);
4536 SIVAL(pdata,8,0); /* ??? */
4537 SIVAL(pdata,12,0); /* ??? */
4538 data_size = 16;
4539 break;
4540
4541 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4542 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4543 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4544 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4545 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4546 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4547 SOFF_T(pdata,32,allocation_size);
4548 SOFF_T(pdata,40,file_size);
4549 SIVAL(pdata,48,mode);
4550 SIVAL(pdata,52,0); /* ??? */
4551 data_size = 56;
4552 break;
4553
4554 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4555 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4556 SIVAL(pdata,0,mode);
4557 SIVAL(pdata,4,0);
4558 data_size = 8;
4559 break;
4560
4561 /*
4562 * CIFS UNIX Extensions.
4563 */
4564
4565 case SMB_QUERY_FILE_UNIX_BASIC:
4566
4567 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4568 data_size = PTR_DIFF(pdata,(*ppdata));
4569
4570 {
4571 int i;
4572 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4573
4574 for (i=0; i<100; i++)
4575 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4576 DEBUG(4,("\n"));
4577 }
4578
4579 break;
4580
4581 case SMB_QUERY_FILE_UNIX_INFO2:
4582
4583 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4584 data_size = PTR_DIFF(pdata,(*ppdata));
4585
4586 {
4587 int i;
4588 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4589
4590 for (i=0; i<100; i++)
4591 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4592 DEBUG(4,("\n"));
4593 }
4594
4595 break;
4596
4597 case SMB_QUERY_FILE_UNIX_LINK:
4598 {
4599 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4600
4601 if (!buffer) {
4602 reply_nterror(req, NT_STATUS_NO_MEMORY);
4603 return;
4604 }
4605
4606 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4607 #ifdef S_ISLNK
4608 if(!S_ISLNK(sbuf.st_mode)) {
4609 reply_unixerror(req, ERRSRV,
4610 ERRbadlink);
4611 return;
4612 }
4613 #else
4614 reply_unixerror(req, ERRDOS, ERRbadlink);
4615 return;
4616 #endif
4617 len = SMB_VFS_READLINK(conn,fullpathname,
4618 buffer, PATH_MAX);
4619 if (len == -1) {
4620 reply_unixerror(req, ERRDOS,
4621 ERRnoaccess);
4622 return;
4623 }
4624 buffer[len] = 0;
4625 len = srvstr_push(dstart, req->flags2,
4626 pdata, buffer,
4627 PTR_DIFF(dend, pdata),
4628 STR_TERMINATE);
4629 pdata += len;
4630 data_size = PTR_DIFF(pdata,(*ppdata));
4631
4632 break;
4633 }
4634
4635 #if defined(HAVE_POSIX_ACLS)
4636 case SMB_QUERY_POSIX_ACL:
4637 {
4638 SMB_ACL_T file_acl = NULL;
4639 SMB_ACL_T def_acl = NULL;
4640 uint16 num_file_acls = 0;
4641 uint16 num_def_acls = 0;
4642
4643 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4644 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4645 } else {
4646 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4647 }
4648
4649 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4650 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4651 fname ));
4652 reply_nterror(
4653 req,
4654 NT_STATUS_NOT_IMPLEMENTED);
4655 return;
4656 }
4657
4658 if (S_ISDIR(sbuf.st_mode)) {
4659 if (fsp && fsp->is_directory) {
4660 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4661 } else {
4662 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4663 }
4664 def_acl = free_empty_sys_acl(conn, def_acl);
4665 }
4666
4667 num_file_acls = count_acl_entries(conn, file_acl);
4668 num_def_acls = count_acl_entries(conn, def_acl);
4669
4670 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4671 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4672 data_size,
4673 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4674 SMB_POSIX_ACL_HEADER_SIZE) ));
4675 if (file_acl) {
4676 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4677 }
4678 if (def_acl) {
4679 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4680 }
4681 reply_nterror(
4682 req,
4683 NT_STATUS_BUFFER_TOO_SMALL);
4684 return;
4685 }
4686
4687 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4688 SSVAL(pdata,2,num_file_acls);
4689 SSVAL(pdata,4,num_def_acls);
4690 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4691 if (file_acl) {
4692 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4693 }
4694 if (def_acl) {
4695 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4696 }
4697 reply_nterror(
4698 req, NT_STATUS_INTERNAL_ERROR);
4699 return;
4700 }
4701 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4702 if (file_acl) {
4703 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4704 }
4705 if (def_acl) {
4706 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4707 }
4708 reply_nterror(
4709 req,
4710 NT_STATUS_INTERNAL_ERROR);
4711 return;
4712 }
4713
4714 if (file_acl) {
4715 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4716 }
4717 if (def_acl) {
4718 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4719 }
4720 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4721 break;
4722 }
4723 #endif
4724
4725
4726 case SMB_QUERY_POSIX_LOCK:
4727 {
4728 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4729 uint64_t count;
4730 uint64_t offset;
4731 uint32 lock_pid;
4732 enum brl_type lock_type;
4733
4734 if (total_data != POSIX_LOCK_DATA_SIZE) {
4735 reply_nterror(
4736 req, NT_STATUS_INVALID_PARAMETER);
4737 return;
4738 }
4739
4740 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4741 case POSIX_LOCK_TYPE_READ:
4742 lock_type = READ_LOCK;
4743 break;
4744 case POSIX_LOCK_TYPE_WRITE:
4745 lock_type = WRITE_LOCK;
4746 break;
4747 case POSIX_LOCK_TYPE_UNLOCK:
4748 default:
4749 /* There's no point in asking for an unlock... */
4750 reply_nterror(
4751 req,
4752 NT_STATUS_INVALID_PARAMETER);
4753 return;
4754 }
4755
4756 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4757 #if defined(HAVE_LONGLONG)
4758 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4759 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4760 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4761 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4762 #else /* HAVE_LONGLONG */
4763 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4764 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4765 #endif /* HAVE_LONGLONG */
4766
4767 status = query_lock(fsp,
4768 &lock_pid,
4769 &count,
4770 &offset,
4771 &lock_type,
4772 POSIX_LOCK);
4773
4774 if (ERROR_WAS_LOCK_DENIED(status)) {
4775 /* Here we need to report who has it locked... */
4776 data_size = POSIX_LOCK_DATA_SIZE;
4777
4778 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4779 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4780 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4781 #if defined(HAVE_LONGLONG)
4782 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4783 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4784 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4785 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4786 #else /* HAVE_LONGLONG */
4787 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4788 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4789 #endif /* HAVE_LONGLONG */
4790
4791 } else if (NT_STATUS_IS_OK(status)) {
4792 /* For success we just return a copy of what we sent
4793 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4794 data_size = POSIX_LOCK_DATA_SIZE;
4795 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4796 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4797 } else {
4798 reply_nterror(req, status);
4799 return;
4800 }
4801 break;
4802 }
4803
4804 default:
4805 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4806 return;
4807 }
4808
4809 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4810 max_data_bytes);
4811
4812 return;
4813 }
4814
4815 /****************************************************************************
4816 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4817 code.
4818 ****************************************************************************/
4819
4820 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
/* [<][>][^][v][top][bottom][index][help] */
4821 connection_struct *conn,
4822 const char *oldname_in,
4823 const char *newname_in)
4824 {
4825 SMB_STRUCT_STAT sbuf1, sbuf2;
4826 char *last_component_oldname = NULL;
4827 char *last_component_newname = NULL;
4828 char *oldname = NULL;
4829 char *newname = NULL;
4830 NTSTATUS status = NT_STATUS_OK;
4831
4832 ZERO_STRUCT(sbuf1);
4833 ZERO_STRUCT(sbuf2);
4834
4835 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4836 &last_component_oldname, &sbuf1);
4837 if (!NT_STATUS_IS_OK(status)) {
4838 return status;
4839 }
4840
4841 status = check_name(conn, oldname);
4842 if (!NT_STATUS_IS_OK(status)) {
4843 return status;
4844 }
4845
4846 /* source must already exist. */
4847 if (!VALID_STAT(sbuf1)) {
4848 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4849 }
4850
4851 status = unix_convert(ctx, conn, newname_in, False, &newname,
4852 &last_component_newname, &sbuf2);
4853 if (!NT_STATUS_IS_OK(status)) {
4854 return status;
4855 }
4856
4857 status = check_name(conn, newname);
4858 if (!NT_STATUS_IS_OK(status)) {
4859 return status;
4860 }
4861
4862 /* Disallow if newname already exists. */
4863 if (VALID_STAT(sbuf2)) {
4864 return NT_STATUS_OBJECT_NAME_COLLISION;
4865 }
4866
4867 /* No links from a directory. */
4868 if (S_ISDIR(sbuf1.st_mode)) {
4869 return NT_STATUS_FILE_IS_A_DIRECTORY;
4870 }
4871
4872 /* Ensure this is within the share. */
4873 status = check_reduced_name(conn, oldname);
4874 if (!NT_STATUS_IS_OK(status)) {
4875 return status;
4876 }
4877
4878 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4879
4880 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4881 status = map_nt_error_from_unix(errno);
4882 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4883 nt_errstr(status), newname, oldname));
4884 }
4885
4886 return status;
4887 }
4888
4889 /****************************************************************************
4890 Deal with setting the time from any of the setfilepathinfo functions.
4891 ****************************************************************************/
4892
4893 NTSTATUS smb_set_file_time(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
4894 files_struct *fsp,
4895 const char *fname,
4896 const SMB_STRUCT_STAT *psbuf,
4897 struct smb_file_time *ft,
4898 bool setting_write_time)
4899 {
4900 struct smb_file_time ft_stat;
4901 uint32 action =
4902 FILE_NOTIFY_CHANGE_LAST_ACCESS
4903 |FILE_NOTIFY_CHANGE_LAST_WRITE
4904 |FILE_NOTIFY_CHANGE_CREATION;
4905
4906 if (!VALID_STAT(*psbuf)) {
4907 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4908 }
4909
4910 /* get some defaults (no modifications) if any info is zero or -1. */
4911 if (null_timespec(ft->create_time)) {
4912 ft->create_time = get_create_timespec(psbuf, lp_fake_dir_create_times(SNUM(conn)));
4913 action &= ~FILE_NOTIFY_CHANGE_CREATION;
4914 }
4915
4916 if (null_timespec(ft->atime)) {
4917 ft->atime= get_atimespec(psbuf);
4918 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4919 }
4920
4921 if (null_timespec(ft->mtime)) {
4922 ft->mtime = get_mtimespec(psbuf);
4923 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4924 }
4925
4926 if (!setting_write_time) {
4927 /* ft->mtime comes from change time, not write time. */
4928 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4929 }
4930
4931 /* Ensure the resolution is the correct for
4932 * what we can store on this filesystem. */
4933
4934 round_timespec(conn->ts_res, &ft->create_time);
4935 round_timespec(conn->ts_res, &ft->atime);
4936 round_timespec(conn->ts_res, &ft->mtime);
4937
4938 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4939 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4940 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4941 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4942 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4943 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4944
4945 if (setting_write_time) {
4946 /*
4947 * This was a Windows setfileinfo on an open file.
4948 * NT does this a lot. We also need to
4949 * set the time here, as it can be read by
4950 * FindFirst/FindNext and with the patch for bug #2045
4951 * in smbd/fileio.c it ensures that this timestamp is
4952 * kept sticky even after a write. We save the request
4953 * away and will set it on file close and after a write. JRA.
4954 */
4955
4956 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4957 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4958
4959 if (fsp != NULL) {
4960 if (fsp->base_fsp) {
4961 set_sticky_write_time_fsp(fsp->base_fsp,
4962 ft->mtime);
4963 } else {
4964 set_sticky_write_time_fsp(fsp, ft->mtime);
4965 }
4966 } else {
4967 set_sticky_write_time_path(conn, fname,
4968 vfs_file_id_from_sbuf(conn, psbuf),
4969 ft->mtime);
4970 }
4971 }
4972
4973 ft_stat.create_time = get_create_timespec(psbuf,
4974 lp_fake_dir_create_times(SNUM(conn)));
4975 ft_stat.atime= get_atimespec(psbuf);
4976 ft_stat.mtime = get_mtimespec(psbuf);
4977
4978 round_timespec(conn->ts_res, &ft_stat.create_time);
4979 round_timespec(conn->ts_res, &ft_stat.atime);
4980 round_timespec(conn->ts_res, &ft_stat.mtime);
4981
4982 if (fsp && fsp->base_fsp) {
4983 fname = fsp->base_fsp->fsp_name;
4984 }
4985
4986 if (timespec_compare(&ft_stat.create_time, &ft->create_time) ||
4987 timespec_compare(&ft_stat.atime, &ft->atime) ||
4988 timespec_compare(&ft_stat.mtime, &ft->mtime)) {
4989 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4990 if(file_ntimes(conn, fname, ft)!=0) {
4991 return map_nt_error_from_unix(errno);
4992 }
4993 }
4994 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4995
4996 return NT_STATUS_OK;
4997 }
4998
4999 /****************************************************************************
5000 Deal with setting the dosmode from any of the setfilepathinfo functions.
5001 ****************************************************************************/
5002
5003 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5004 files_struct *fsp,
5005 const char *fname,
5006 SMB_STRUCT_STAT *psbuf,
5007 uint32 dosmode)
5008 {
5009 if (!VALID_STAT(*psbuf)) {
5010 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5011 }
5012
5013 if (fsp) {
5014 if (fsp->base_fsp) {
5015 fname = fsp->base_fsp->fsp_name;
5016 } else {
5017 fname = fsp->fsp_name;
5018 }
5019 }
5020
5021 if (dosmode) {
5022 if (S_ISDIR(psbuf->st_mode)) {
5023 dosmode |= aDIR;
5024 } else {
5025 dosmode &= ~aDIR;
5026 }
5027 }
5028
5029 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5030
5031 /* check the mode isn't different, before changing it */
5032 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5033
5034 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5035 fname, (unsigned int)dosmode ));
5036
5037 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5038 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5039 fname, strerror(errno)));
5040 return map_nt_error_from_unix(errno);
5041 }
5042 }
5043 return NT_STATUS_OK;
5044 }
5045
5046 /****************************************************************************
5047 Deal with setting the size from any of the setfilepathinfo functions.
5048 ****************************************************************************/
5049
5050 static NTSTATUS smb_set_file_size(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5051 struct smb_request *req,
5052 files_struct *fsp,
5053 const char *fname,
5054 SMB_STRUCT_STAT *psbuf,
5055 SMB_OFF_T size)
5056 {
5057 NTSTATUS status = NT_STATUS_OK;
5058 files_struct *new_fsp = NULL;
5059
5060 if (!VALID_STAT(*psbuf)) {
5061 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5062 }
5063
5064 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5065
5066 if (size == get_file_size_stat(psbuf)) {
5067 return NT_STATUS_OK;
5068 }
5069
5070 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5071 fname, (double)size ));
5072
5073 if (fsp && fsp->fh->fd != -1) {
5074 /* Handle based call. */
5075 if (vfs_set_filelen(fsp, size) == -1) {
5076 return map_nt_error_from_unix(errno);
5077 }
5078 trigger_write_time_update_immediate(fsp);
5079 return NT_STATUS_OK;
5080 }
5081
5082 status = SMB_VFS_CREATE_FILE(
5083 conn, /* conn */
5084 req, /* req */
5085 0, /* root_dir_fid */
5086 fname, /* fname */
5087 0, /* create_file_flags */
5088 FILE_WRITE_ATTRIBUTES, /* access_mask */
5089 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5090 FILE_SHARE_DELETE),
5091 FILE_OPEN, /* create_disposition*/
5092 0, /* create_options */
5093 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5094 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5095 0, /* allocation_size */
5096 NULL, /* sd */
5097 NULL, /* ea_list */
5098 &new_fsp, /* result */
5099 NULL, /* pinfo */
5100 psbuf); /* psbuf */
5101
5102 if (!NT_STATUS_IS_OK(status)) {
5103 /* NB. We check for open_was_deferred in the caller. */
5104 return status;
5105 }
5106
5107 if (vfs_set_filelen(new_fsp, size) == -1) {
5108 status = map_nt_error_from_unix(errno);
5109 close_file(req, new_fsp,NORMAL_CLOSE);
5110 return status;
5111 }
5112
5113 trigger_write_time_update_immediate(new_fsp);
5114 close_file(req, new_fsp,NORMAL_CLOSE);
5115 return NT_STATUS_OK;
5116 }
5117
5118 /****************************************************************************
5119 Deal with SMB_INFO_SET_EA.
5120 ****************************************************************************/
5121
5122 static NTSTATUS smb_info_set_ea(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5123 const char *pdata,
5124 int total_data,
5125 files_struct *fsp,
5126 const char *fname)
5127 {
5128 struct ea_list *ea_list = NULL;
5129 TALLOC_CTX *ctx = NULL;
5130 NTSTATUS status = NT_STATUS_OK;
5131
5132 if (total_data < 10) {
5133
5134 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5135 length. They seem to have no effect. Bug #3212. JRA */
5136
5137 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5138 /* We're done. We only get EA info in this call. */
5139 return NT_STATUS_OK;
5140 }
5141
5142 return NT_STATUS_INVALID_PARAMETER;
5143 }
5144
5145 if (IVAL(pdata,0) > total_data) {
5146 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5147 IVAL(pdata,0), (unsigned int)total_data));
5148 return NT_STATUS_INVALID_PARAMETER;
5149 }
5150
5151 ctx = talloc_tos();
5152 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5153 if (!ea_list) {
5154 return NT_STATUS_INVALID_PARAMETER;
5155 }
5156 status = set_ea(conn, fsp, fname, ea_list);
5157
5158 return status;
5159 }
5160
5161 /****************************************************************************
5162 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5163 ****************************************************************************/
5164
5165 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5166 const char *pdata,
5167 int total_data,
5168 files_struct *fsp,
5169 const char *fname,
5170 SMB_STRUCT_STAT *psbuf)
5171 {
5172 NTSTATUS status = NT_STATUS_OK;
5173 bool delete_on_close;
5174 uint32 dosmode = 0;
5175
5176 if (total_data < 1) {
5177 return NT_STATUS_INVALID_PARAMETER;
5178 }
5179
5180 if (fsp == NULL) {
5181 return NT_STATUS_INVALID_HANDLE;
5182 }
5183
5184 delete_on_close = (CVAL(pdata,0) ? True : False);
5185 dosmode = dos_mode(conn, fname, psbuf);
5186
5187 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5188 "delete_on_close = %u\n",
5189 fsp->fsp_name,
5190 (unsigned int)dosmode,
5191 (unsigned int)delete_on_close ));
5192
5193 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5194
5195 if (!NT_STATUS_IS_OK(status)) {
5196 return status;
5197 }
5198
5199 /* The set is across all open files on this dev/inode pair. */
5200 if (!set_delete_on_close(fsp, delete_on_close,
5201 &conn->server_info->utok)) {
5202 return NT_STATUS_ACCESS_DENIED;
5203 }
5204 return NT_STATUS_OK;
5205 }
5206
5207 /****************************************************************************
5208 Deal with SMB_FILE_POSITION_INFORMATION.
5209 ****************************************************************************/
5210
5211 static NTSTATUS smb_file_position_information(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5212 const char *pdata,
5213 int total_data,
5214 files_struct *fsp)
5215 {
5216 uint64_t position_information;
5217
5218 if (total_data < 8) {
5219 return NT_STATUS_INVALID_PARAMETER;
5220 }
5221
5222 if (fsp == NULL) {
5223 /* Ignore on pathname based set. */
5224 return NT_STATUS_OK;
5225 }
5226
5227 position_information = (uint64_t)IVAL(pdata,0);
5228 #ifdef LARGE_SMB_OFF_T
5229 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5230 #else /* LARGE_SMB_OFF_T */
5231 if (IVAL(pdata,4) != 0) {
5232 /* more than 32 bits? */
5233 return NT_STATUS_INVALID_PARAMETER;
5234 }
5235 #endif /* LARGE_SMB_OFF_T */
5236
5237 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5238 fsp->fsp_name, (double)position_information ));
5239 fsp->fh->position_information = position_information;
5240 return NT_STATUS_OK;
5241 }
5242
5243 /****************************************************************************
5244 Deal with SMB_FILE_MODE_INFORMATION.
5245 ****************************************************************************/
5246
5247 static NTSTATUS smb_file_mode_information(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5248 const char *pdata,
5249 int total_data)
5250 {
5251 uint32 mode;
5252
5253 if (total_data < 4) {
5254 return NT_STATUS_INVALID_PARAMETER;
5255 }
5256 mode = IVAL(pdata,0);
5257 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5258 return NT_STATUS_INVALID_PARAMETER;
5259 }
5260 return NT_STATUS_OK;
5261 }
5262
5263 /****************************************************************************
5264 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5265 ****************************************************************************/
5266
5267 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5268 struct smb_request *req,
5269 const char *pdata,
5270 int total_data,
5271 const char *fname)
5272 {
5273 char *link_target = NULL;
5274 const char *newname = fname;
5275 NTSTATUS status = NT_STATUS_OK;
5276 TALLOC_CTX *ctx = talloc_tos();
5277
5278 /* Set a symbolic link. */
5279 /* Don't allow this if follow links is false. */
5280
5281 if (total_data == 0) {
5282 return NT_STATUS_INVALID_PARAMETER;
5283 }
5284
5285 if (!lp_symlinks(SNUM(conn))) {
5286 return NT_STATUS_ACCESS_DENIED;
5287 }
5288
5289 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5290 total_data, STR_TERMINATE);
5291
5292 if (!link_target) {
5293 return NT_STATUS_INVALID_PARAMETER;
5294 }
5295
5296 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5297 newname, link_target ));
5298
5299 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5300 return map_nt_error_from_unix(errno);
5301 }
5302
5303 return NT_STATUS_OK;
5304 }
5305
5306 /****************************************************************************
5307 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5308 ****************************************************************************/
5309
5310 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5311 struct smb_request *req,
5312 const char *pdata, int total_data,
5313 const char *fname)
5314 {
5315 char *oldname = NULL;
5316 TALLOC_CTX *ctx = talloc_tos();
5317 NTSTATUS status = NT_STATUS_OK;
5318
5319 /* Set a hard link. */
5320 if (total_data == 0) {
5321 return NT_STATUS_INVALID_PARAMETER;
5322 }
5323
5324 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5325 total_data, STR_TERMINATE, &status);
5326 if (!NT_STATUS_IS_OK(status)) {
5327 return status;
5328 }
5329
5330 status = resolve_dfspath(ctx, conn,
5331 req->flags2 & FLAGS2_DFS_PATHNAMES,
5332 oldname,
5333 &oldname);
5334 if (!NT_STATUS_IS_OK(status)) {
5335 return status;
5336 }
5337
5338 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5339 fname, oldname));
5340
5341 return hardlink_internals(ctx, conn, oldname, fname);
5342 }
5343
5344 /****************************************************************************
5345 Deal with SMB_FILE_RENAME_INFORMATION.
5346 ****************************************************************************/
5347
5348 static NTSTATUS smb_file_rename_information(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5349 struct smb_request *req,
5350 const char *pdata,
5351 int total_data,
5352 files_struct *fsp,
5353 const char *fname)
5354 {
5355 bool overwrite;
5356 uint32 root_fid;
5357 uint32 len;
5358 char *newname = NULL;
5359 char *base_name = NULL;
5360 bool dest_has_wcard = False;
5361 SMB_STRUCT_STAT sbuf;
5362 char *newname_last_component = NULL;
5363 NTSTATUS status = NT_STATUS_OK;
5364 char *p;
5365 TALLOC_CTX *ctx = talloc_tos();
5366
5367 if (total_data < 13) {
5368 return NT_STATUS_INVALID_PARAMETER;
5369 }
5370
5371 ZERO_STRUCT(sbuf);
5372
5373 overwrite = (CVAL(pdata,0) ? True : False);
5374 root_fid = IVAL(pdata,4);
5375 len = IVAL(pdata,8);
5376
5377 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5378 return NT_STATUS_INVALID_PARAMETER;
5379 }
5380
5381 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5382 len, 0, &status,
5383 &dest_has_wcard);
5384 if (!NT_STATUS_IS_OK(status)) {
5385 return status;
5386 }
5387
5388 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5389 newname));
5390
5391 status = resolve_dfspath_wcard(ctx, conn,
5392 req->flags2 & FLAGS2_DFS_PATHNAMES,
5393 newname,
5394 &newname,
5395 &dest_has_wcard);
5396 if (!NT_STATUS_IS_OK(status)) {
5397 return status;
5398 }
5399
5400 /* Check the new name has no '/' characters. */
5401 if (strchr_m(newname, '/')) {
5402 return NT_STATUS_NOT_SUPPORTED;
5403 }
5404
5405 if (fsp && fsp->base_fsp) {
5406 /* newname must be a stream name. */
5407 if (newname[0] != ':') {
5408 return NT_STATUS_NOT_SUPPORTED;
5409 }
5410 base_name = talloc_asprintf(ctx, "%s%s",
5411 fsp->base_fsp->fsp_name,
5412 newname);
5413 if (!base_name) {
5414 return NT_STATUS_NO_MEMORY;
5415 }
5416 } else {
5417 /* newname must *not* be a stream name. */
5418 if (is_ntfs_stream_name(newname)) {
5419 return NT_STATUS_NOT_SUPPORTED;
5420 }
5421
5422 /* Create the base directory. */
5423 base_name = talloc_strdup(ctx, fname);
5424 if (!base_name) {
5425 return NT_STATUS_NO_MEMORY;
5426 }
5427 p = strrchr_m(base_name, '/');
5428 if (p) {
5429 p[1] = '\0';
5430 } else {
5431 base_name = talloc_strdup(ctx, "./");
5432 if (!base_name) {
5433 return NT_STATUS_NO_MEMORY;
5434 }
5435 }
5436 /* Append the new name. */
5437 base_name = talloc_asprintf_append(base_name,
5438 "%s",
5439 newname);
5440 if (!base_name) {
5441 return NT_STATUS_NO_MEMORY;
5442 }
5443
5444 status = unix_convert(ctx, conn, newname, False,
5445 &newname,
5446 &newname_last_component,
5447 &sbuf);
5448
5449 /* If an error we expect this to be
5450 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5451
5452 if (!NT_STATUS_IS_OK(status)
5453 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5454 status)) {
5455 return status;
5456 }
5457 }
5458
5459 if (fsp) {
5460 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5461 fsp->fnum, fsp->fsp_name, base_name ));
5462 status = rename_internals_fsp(conn, fsp, base_name,
5463 newname_last_component, 0,
5464 overwrite);
5465 } else {
5466 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5467 fname, base_name ));
5468 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5469 overwrite, False, dest_has_wcard,
5470 FILE_WRITE_ATTRIBUTES);
5471 }
5472
5473 return status;
5474 }
5475
5476 /****************************************************************************
5477 Deal with SMB_SET_POSIX_ACL.
5478 ****************************************************************************/
5479
5480 #if defined(HAVE_POSIX_ACLS)
5481 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5482 const char *pdata,
5483 int total_data,
5484 files_struct *fsp,
5485 const char *fname,
5486 SMB_STRUCT_STAT *psbuf)
5487 {
5488 uint16 posix_acl_version;
5489 uint16 num_file_acls;
5490 uint16 num_def_acls;
5491 bool valid_file_acls = True;
5492 bool valid_def_acls = True;
5493
5494 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5495 return NT_STATUS_INVALID_PARAMETER;
5496 }
5497 posix_acl_version = SVAL(pdata,0);
5498 num_file_acls = SVAL(pdata,2);
5499 num_def_acls = SVAL(pdata,4);
5500
5501 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5502 valid_file_acls = False;
5503 num_file_acls = 0;
5504 }
5505
5506 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5507 valid_def_acls = False;
5508 num_def_acls = 0;
5509 }
5510
5511 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5512 return NT_STATUS_INVALID_PARAMETER;
5513 }
5514
5515 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5516 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5517 return NT_STATUS_INVALID_PARAMETER;
5518 }
5519
5520 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5521 fname ? fname : fsp->fsp_name,
5522 (unsigned int)num_file_acls,
5523 (unsigned int)num_def_acls));
5524
5525 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5526 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5527 return map_nt_error_from_unix(errno);
5528 }
5529
5530 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5531 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5532 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5533 return map_nt_error_from_unix(errno);
5534 }
5535 return NT_STATUS_OK;
5536 }
5537 #endif
5538
5539 /****************************************************************************
5540 Deal with SMB_SET_POSIX_LOCK.
5541 ****************************************************************************/
5542
5543 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5544 struct smb_request *req,
5545 const char *pdata,
5546 int total_data,
5547 files_struct *fsp)
5548 {
5549 uint64_t count;
5550 uint64_t offset;
5551 uint32 lock_pid;
5552 bool blocking_lock = False;
5553 enum brl_type lock_type;
5554
5555 NTSTATUS status = NT_STATUS_OK;
5556
5557 if (fsp == NULL || fsp->fh->fd == -1) {
5558 return NT_STATUS_INVALID_HANDLE;
5559 }
5560
5561 if (total_data != POSIX_LOCK_DATA_SIZE) {
5562 return NT_STATUS_INVALID_PARAMETER;
5563 }
5564
5565 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5566 case POSIX_LOCK_TYPE_READ:
5567 lock_type = READ_LOCK;
5568 break;
5569 case POSIX_LOCK_TYPE_WRITE:
5570 /* Return the right POSIX-mappable error code for files opened read-only. */
5571 if (!fsp->can_write) {
5572 return NT_STATUS_INVALID_HANDLE;
5573 }
5574 lock_type = WRITE_LOCK;
5575 break;
5576 case POSIX_LOCK_TYPE_UNLOCK:
5577 lock_type = UNLOCK_LOCK;
5578 break;
5579 default:
5580 return NT_STATUS_INVALID_PARAMETER;
5581 }
5582
5583 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5584 blocking_lock = False;
5585 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5586 blocking_lock = True;
5587 } else {
5588 return NT_STATUS_INVALID_PARAMETER;
5589 }
5590
5591 if (!lp_blocking_locks(SNUM(conn))) {
5592 blocking_lock = False;
5593 }
5594
5595 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5596 #if defined(HAVE_LONGLONG)
5597 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5598 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5599 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5600 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5601 #else /* HAVE_LONGLONG */
5602 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5603 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5604 #endif /* HAVE_LONGLONG */
5605
5606 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5607 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5608 fsp->fsp_name,
5609 (unsigned int)lock_type,
5610 (unsigned int)lock_pid,
5611 (double)count,
5612 (double)offset ));
5613
5614 if (lock_type == UNLOCK_LOCK) {
5615 status = do_unlock(smbd_messaging_context(),
5616 fsp,
5617 lock_pid,
5618 count,
5619 offset,
5620 POSIX_LOCK);
5621 } else {
5622 uint32 block_smbpid;
5623
5624 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5625 fsp,
5626 lock_pid,
5627 count,
5628 offset,
5629 lock_type,
5630 POSIX_LOCK,
5631 blocking_lock,
5632 &status,
5633 &block_smbpid,
5634 NULL);
5635
5636 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5637 /*
5638 * A blocking lock was requested. Package up
5639 * this smb into a queued request and push it
5640 * onto the blocking lock queue.
5641 */
5642 if(push_blocking_lock_request(br_lck,
5643 req,
5644 fsp,
5645 -1, /* infinite timeout. */
5646 0,
5647 lock_pid,
5648 lock_type,
5649 POSIX_LOCK,
5650 offset,
5651 count,
5652 block_smbpid)) {
5653 TALLOC_FREE(br_lck);
5654 return status;
5655 }
5656 }
5657 TALLOC_FREE(br_lck);
5658 }
5659
5660 return status;
5661 }
5662
5663 /****************************************************************************
5664 Deal with SMB_INFO_STANDARD.
5665 ****************************************************************************/
5666
5667 static NTSTATUS smb_set_info_standard(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5668 const char *pdata,
5669 int total_data,
5670 files_struct *fsp,
5671 const char *fname,
5672 const SMB_STRUCT_STAT *psbuf)
5673 {
5674 struct smb_file_time ft;
5675 ZERO_STRUCT(ft);
5676
5677 if (total_data < 12) {
5678 return NT_STATUS_INVALID_PARAMETER;
5679 }
5680
5681 /* create time */
5682 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
5683
5684 /* access time */
5685 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
5686
5687 /* write time */
5688 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
5689
5690 DEBUG(10,("smb_set_info_standard: file %s\n",
5691 fname ? fname : fsp->fsp_name ));
5692
5693 return smb_set_file_time(conn,
5694 fsp,
5695 fname,
5696 psbuf,
5697 &ft,
5698 true);
5699 }
5700
5701 /****************************************************************************
5702 Deal with SMB_SET_FILE_BASIC_INFO.
5703 ****************************************************************************/
5704
5705 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5706 const char *pdata,
5707 int total_data,
5708 files_struct *fsp,
5709 const char *fname,
5710 SMB_STRUCT_STAT *psbuf)
5711 {
5712 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5713 struct timespec write_time;
5714 struct timespec changed_time;
5715 struct smb_file_time ft;
5716 uint32 dosmode = 0;
5717 NTSTATUS status = NT_STATUS_OK;
5718 bool setting_write_time = true;
5719
5720 ZERO_STRUCT(ft);
5721
5722 if (total_data < 36) {
5723 return NT_STATUS_INVALID_PARAMETER;
5724 }
5725
5726 /* Set the attributes */
5727 dosmode = IVAL(pdata,32);
5728 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5729 if (!NT_STATUS_IS_OK(status)) {
5730 return status;
5731 }
5732
5733 /* access time */
5734 ft.atime = interpret_long_date(pdata+8);
5735
5736 write_time = interpret_long_date(pdata+16);
5737 changed_time = interpret_long_date(pdata+24);
5738
5739 /* mtime */
5740 ft.mtime = timespec_min(&write_time, &changed_time);
5741
5742 /* create time */
5743 ft.create_time = interpret_long_date(pdata);
5744
5745 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5746 !null_timespec(write_time)) {
5747 ft.mtime = write_time;
5748 }
5749
5750 /* Prefer a defined time to an undefined one. */
5751 if (null_timespec(ft.mtime)) {
5752 if (null_timespec(write_time)) {
5753 ft.mtime = changed_time;
5754 setting_write_time = false;
5755 } else {
5756 ft.mtime = write_time;
5757 }
5758 }
5759
5760 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5761 fname ? fname : fsp->fsp_name ));
5762
5763 return smb_set_file_time(conn,
5764 fsp,
5765 fname,
5766 psbuf,
5767 &ft,
5768 setting_write_time);
5769 }
5770
5771 /****************************************************************************
5772 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5773 ****************************************************************************/
5774
5775 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5776 struct smb_request *req,
5777 const char *pdata,
5778 int total_data,
5779 files_struct *fsp,
5780 const char *fname,
5781 SMB_STRUCT_STAT *psbuf)
5782 {
5783 uint64_t allocation_size = 0;
5784 NTSTATUS status = NT_STATUS_OK;
5785 files_struct *new_fsp = NULL;
5786
5787 if (!VALID_STAT(*psbuf)) {
5788 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5789 }
5790
5791 if (total_data < 8) {
5792 return NT_STATUS_INVALID_PARAMETER;
5793 }
5794
5795 allocation_size = (uint64_t)IVAL(pdata,0);
5796 #ifdef LARGE_SMB_OFF_T
5797 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5798 #else /* LARGE_SMB_OFF_T */
5799 if (IVAL(pdata,4) != 0) {
5800 /* more than 32 bits? */
5801 return NT_STATUS_INVALID_PARAMETER;
5802 }
5803 #endif /* LARGE_SMB_OFF_T */
5804
5805 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5806 fname, (double)allocation_size ));
5807
5808 if (allocation_size) {
5809 allocation_size = smb_roundup(conn, allocation_size);
5810 }
5811
5812 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5813 fname, (double)allocation_size ));
5814
5815 if (fsp && fsp->fh->fd != -1) {
5816 /* Open file handle. */
5817 /* Only change if needed. */
5818 if (allocation_size != get_file_size_stat(psbuf)) {
5819 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5820 return map_nt_error_from_unix(errno);
5821 }
5822 }
5823 /* But always update the time. */
5824 /*
5825 * This is equivalent to a write. Ensure it's seen immediately
5826 * if there are no pending writes.
5827 */
5828 trigger_write_time_update_immediate(fsp);
5829 return NT_STATUS_OK;
5830 }
5831
5832 /* Pathname or stat or directory file. */
5833
5834 status = SMB_VFS_CREATE_FILE(
5835 conn, /* conn */
5836 req, /* req */
5837 0, /* root_dir_fid */
5838 fname, /* fname */
5839 0, /* create_file_flags */
5840 FILE_WRITE_DATA, /* access_mask */
5841 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5842 FILE_SHARE_DELETE),
5843 FILE_OPEN, /* create_disposition*/
5844 0, /* create_options */
5845 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5846 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5847 0, /* allocation_size */
5848 NULL, /* sd */
5849 NULL, /* ea_list */
5850 &new_fsp, /* result */
5851 NULL, /* pinfo */
5852 psbuf); /* psbuf */
5853
5854 if (!NT_STATUS_IS_OK(status)) {
5855 /* NB. We check for open_was_deferred in the caller. */
5856 return status;
5857 }
5858
5859 /* Only change if needed. */
5860 if (allocation_size != get_file_size_stat(psbuf)) {
5861 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5862 status = map_nt_error_from_unix(errno);
5863 close_file(req, new_fsp, NORMAL_CLOSE);
5864 return status;
5865 }
5866 }
5867
5868 /* Changing the allocation size should set the last mod time. */
5869 /*
5870 * This is equivalent to a write. Ensure it's seen immediately
5871 * if there are no pending writes.
5872 */
5873 trigger_write_time_update_immediate(new_fsp);
5874
5875 close_file(req, new_fsp, NORMAL_CLOSE);
5876 return NT_STATUS_OK;
5877 }
5878
5879 /****************************************************************************
5880 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5881 ****************************************************************************/
5882
5883 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5884 struct smb_request *req,
5885 const char *pdata,
5886 int total_data,
5887 files_struct *fsp,
5888 const char *fname,
5889 SMB_STRUCT_STAT *psbuf)
5890 {
5891 SMB_OFF_T size;
5892
5893 if (total_data < 8) {
5894 return NT_STATUS_INVALID_PARAMETER;
5895 }
5896
5897 size = IVAL(pdata,0);
5898 #ifdef LARGE_SMB_OFF_T
5899 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5900 #else /* LARGE_SMB_OFF_T */
5901 if (IVAL(pdata,4) != 0) {
5902 /* more than 32 bits? */
5903 return NT_STATUS_INVALID_PARAMETER;
5904 }
5905 #endif /* LARGE_SMB_OFF_T */
5906 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5907 "file %s to %.0f\n", fname, (double)size ));
5908
5909 return smb_set_file_size(conn, req,
5910 fsp,
5911 fname,
5912 psbuf,
5913 size);
5914 }
5915
5916 /****************************************************************************
5917 Allow a UNIX info mknod.
5918 ****************************************************************************/
5919
5920 static NTSTATUS smb_unix_mknod(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
5921 const char *pdata,
5922 int total_data,
5923 const char *fname,
5924 SMB_STRUCT_STAT *psbuf)
5925 {
5926 uint32 file_type = IVAL(pdata,56);
5927 #if defined(HAVE_MAKEDEV)
5928 uint32 dev_major = IVAL(pdata,60);
5929 uint32 dev_minor = IVAL(pdata,68);
5930 #endif
5931 SMB_DEV_T dev = (SMB_DEV_T)0;
5932 uint32 raw_unixmode = IVAL(pdata,84);
5933 NTSTATUS status;
5934 mode_t unixmode;
5935
5936 if (total_data < 100) {
5937 return NT_STATUS_INVALID_PARAMETER;
5938 }
5939
5940 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5941 if (!NT_STATUS_IS_OK(status)) {
5942 return status;
5943 }
5944
5945 #if defined(HAVE_MAKEDEV)
5946 dev = makedev(dev_major, dev_minor);
5947 #endif
5948
5949 switch (file_type) {
5950 #if defined(S_IFIFO)
5951 case UNIX_TYPE_FIFO:
5952 unixmode |= S_IFIFO;
5953 break;
5954 #endif
5955 #if defined(S_IFSOCK)
5956 case UNIX_TYPE_SOCKET:
5957 unixmode |= S_IFSOCK;
5958 break;
5959 #endif
5960 #if defined(S_IFCHR)
5961 case UNIX_TYPE_CHARDEV:
5962 unixmode |= S_IFCHR;
5963 break;
5964 #endif
5965 #if defined(S_IFBLK)
5966 case UNIX_TYPE_BLKDEV:
5967 unixmode |= S_IFBLK;
5968 break;
5969 #endif
5970 default:
5971 return NT_STATUS_INVALID_PARAMETER;
5972 }
5973
5974 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5975 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5976
5977 /* Ok - do the mknod. */
5978 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5979 return map_nt_error_from_unix(errno);
5980 }
5981
5982 /* If any of the other "set" calls fail we
5983 * don't want to end up with a half-constructed mknod.
5984 */
5985
5986 if (lp_inherit_perms(SNUM(conn))) {
5987 char *parent;
5988 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
5989 return NT_STATUS_NO_MEMORY;
5990 }
5991 inherit_access_posix_acl(conn, parent, fname, unixmode);
5992 TALLOC_FREE(parent);
5993 }
5994
5995 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5996 status = map_nt_error_from_unix(errno);
5997 SMB_VFS_UNLINK(conn,fname);
5998 return status;
5999 }
6000 return NT_STATUS_OK;
6001 }
6002
6003 /****************************************************************************
6004 Deal with SMB_SET_FILE_UNIX_BASIC.
6005 ****************************************************************************/
6006
6007 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
6008 struct smb_request *req,
6009 const char *pdata,
6010 int total_data,
6011 files_struct *fsp,
6012 const char *fname,
6013 SMB_STRUCT_STAT *psbuf)
6014 {
6015 struct smb_file_time ft;
6016 uint32 raw_unixmode;
6017 mode_t unixmode;
6018 SMB_OFF_T size = 0;
6019 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6020 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6021 NTSTATUS status = NT_STATUS_OK;
6022 bool delete_on_fail = False;
6023 enum perm_type ptype;
6024 files_struct *all_fsps = NULL;
6025 bool modify_mtime = true;
6026 struct file_id id;
6027
6028 ZERO_STRUCT(ft);
6029
6030 if (total_data < 100) {
6031 return NT_STATUS_INVALID_PARAMETER;
6032 }
6033
6034 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6035 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6036 size=IVAL(pdata,0); /* first 8 Bytes are size */
6037 #ifdef LARGE_SMB_OFF_T
6038 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6039 #else /* LARGE_SMB_OFF_T */
6040 if (IVAL(pdata,4) != 0) {
6041 /* more than 32 bits? */
6042 return NT_STATUS_INVALID_PARAMETER;
6043 }
6044 #endif /* LARGE_SMB_OFF_T */
6045 }
6046
6047 ft.atime = interpret_long_date(pdata+24); /* access_time */
6048 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6049 set_owner = (uid_t)IVAL(pdata,40);
6050 set_grp = (gid_t)IVAL(pdata,48);
6051 raw_unixmode = IVAL(pdata,84);
6052
6053 if (VALID_STAT(*psbuf)) {
6054 if (S_ISDIR(psbuf->st_mode)) {
6055 ptype = PERM_EXISTING_DIR;
6056 } else {
6057 ptype = PERM_EXISTING_FILE;
6058 }
6059 } else {
6060 ptype = PERM_NEW_FILE;
6061 }
6062
6063 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6064 if (!NT_STATUS_IS_OK(status)) {
6065 return status;
6066 }
6067
6068 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6069 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6070 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6071
6072 if (!VALID_STAT(*psbuf)) {
6073 /*
6074 * The only valid use of this is to create character and block
6075 * devices, and named pipes. This is deprecated (IMHO) and
6076 * a new info level should be used for mknod. JRA.
6077 */
6078
6079 status = smb_unix_mknod(conn,
6080 pdata,
6081 total_data,
6082 fname,
6083 psbuf);
6084 if (!NT_STATUS_IS_OK(status)) {
6085 return status;
6086 }
6087
6088 /* Ensure we don't try and change anything else. */
6089 raw_unixmode = SMB_MODE_NO_CHANGE;
6090 size = get_file_size_stat(psbuf);
6091 ft.atime = get_atimespec(psbuf);
6092 ft.mtime = get_mtimespec(psbuf);
6093 /*
6094 * We continue here as we might want to change the
6095 * owner uid/gid.
6096 */
6097 delete_on_fail = True;
6098 }
6099
6100 #if 1
6101 /* Horrible backwards compatibility hack as an old server bug
6102 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6103 * */
6104
6105 if (!size) {
6106 size = get_file_size_stat(psbuf);
6107 }
6108 #endif
6109
6110 /*
6111 * Deal with the UNIX specific mode set.
6112 */
6113
6114 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6115 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6116 (unsigned int)unixmode, fname ));
6117 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6118 return map_nt_error_from_unix(errno);
6119 }
6120 }
6121
6122 /*
6123 * Deal with the UNIX specific uid set.
6124 */
6125
6126 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6127 int ret;
6128
6129 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6130 (unsigned int)set_owner, fname ));
6131
6132 if (S_ISLNK(psbuf->st_mode)) {
6133 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6134 } else {
6135 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6136 }
6137
6138 if (ret != 0) {
6139 status = map_nt_error_from_unix(errno);
6140 if (delete_on_fail) {
6141 SMB_VFS_UNLINK(conn,fname);
6142 }
6143 return status;
6144 }
6145 }
6146
6147 /*
6148 * Deal with the UNIX specific gid set.
6149 */
6150
6151 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6152 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6153 (unsigned int)set_owner, fname ));
6154 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6155 status = map_nt_error_from_unix(errno);
6156 if (delete_on_fail) {
6157 SMB_VFS_UNLINK(conn,fname);
6158 }
6159 return status;
6160 }
6161 }
6162
6163 /* Deal with any size changes. */
6164
6165 status = smb_set_file_size(conn, req,
6166 fsp,
6167 fname,
6168 psbuf,
6169 size);
6170 if (!NT_STATUS_IS_OK(status)) {
6171 return status;
6172 }
6173
6174 /* Deal with any time changes. */
6175 id = vfs_file_id_from_sbuf(conn, psbuf);
6176 for(all_fsps = file_find_di_first(id); all_fsps;
6177 all_fsps = file_find_di_next(all_fsps)) {
6178 /*
6179 * We're setting the time explicitly for UNIX.
6180 * Cancel any pending changes over all handles.
6181 */
6182 all_fsps->update_write_time_on_close = false;
6183 TALLOC_FREE(all_fsps->update_write_time_event);
6184 }
6185
6186 /*
6187 * Override the "setting_write_time"
6188 * parameter here as it almost does what
6189 * we need. Just remember if we modified
6190 * mtime and send the notify ourselves.
6191 */
6192 if (null_timespec(ft.mtime)) {
6193 modify_mtime = false;
6194 }
6195
6196 status = smb_set_file_time(conn,
6197 fsp,
6198 fname,
6199 psbuf,
6200 &ft,
6201 false);
6202 if (modify_mtime) {
6203 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6204 FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
6205 }
6206 return status;
6207 }
6208
6209 /****************************************************************************
6210 Deal with SMB_SET_FILE_UNIX_INFO2.
6211 ****************************************************************************/
6212
6213 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
6214 struct smb_request *req,
6215 const char *pdata,
6216 int total_data,
6217 files_struct *fsp,
6218 const char *fname,
6219 SMB_STRUCT_STAT *psbuf)
6220 {
6221 NTSTATUS status;
6222 uint32 smb_fflags;
6223 uint32 smb_fmask;
6224
6225 if (total_data < 116) {
6226 return NT_STATUS_INVALID_PARAMETER;
6227 }
6228
6229 /* Start by setting all the fields that are common between UNIX_BASIC
6230 * and UNIX_INFO2.
6231 */
6232 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6233 fsp, fname, psbuf);
6234 if (!NT_STATUS_IS_OK(status)) {
6235 return status;
6236 }
6237
6238 smb_fflags = IVAL(pdata, 108);
6239 smb_fmask = IVAL(pdata, 112);
6240
6241 /* NB: We should only attempt to alter the file flags if the client
6242 * sends a non-zero mask.
6243 */
6244 if (smb_fmask != 0) {
6245 int stat_fflags = 0;
6246
6247 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6248 &stat_fflags)) {
6249 /* Client asked to alter a flag we don't understand. */
6250 return NT_STATUS_INVALID_PARAMETER;
6251 }
6252
6253 if (fsp && fsp->fh->fd != -1) {
6254 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6255 return NT_STATUS_NOT_SUPPORTED;
6256 } else {
6257 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6258 return map_nt_error_from_unix(errno);
6259 }
6260 }
6261 }
6262
6263 /* XXX: need to add support for changing the create_time here. You
6264 * can do this for paths on Darwin with setattrlist(2). The right way
6265 * to hook this up is probably by extending the VFS utimes interface.
6266 */
6267
6268 return NT_STATUS_OK;
6269 }
6270
6271 /****************************************************************************
6272 Create a directory with POSIX semantics.
6273 ****************************************************************************/
6274
6275 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
6276 struct smb_request *req,
6277 char **ppdata,
6278 int total_data,
6279 const char *fname,
6280 SMB_STRUCT_STAT *psbuf,
6281 int *pdata_return_size)
6282 {
6283 NTSTATUS status = NT_STATUS_OK;
6284 uint32 raw_unixmode = 0;
6285 uint32 mod_unixmode = 0;
6286 mode_t unixmode = (mode_t)0;
6287 files_struct *fsp = NULL;
6288 uint16 info_level_return = 0;
6289 int info;
6290 char *pdata = *ppdata;
6291
6292 if (total_data < 18) {
6293 return NT_STATUS_INVALID_PARAMETER;
6294 }
6295
6296 raw_unixmode = IVAL(pdata,8);
6297 /* Next 4 bytes are not yet defined. */
6298
6299 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6300 if (!NT_STATUS_IS_OK(status)) {
6301 return status;
6302 }
6303
6304 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6305
6306 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6307 fname, (unsigned int)unixmode ));
6308
6309 status = SMB_VFS_CREATE_FILE(
6310 conn, /* conn */
6311 req, /* req */
6312 0, /* root_dir_fid */
6313 fname, /* fname */
6314 0, /* create_file_flags */
6315 FILE_READ_ATTRIBUTES, /* access_mask */
6316 FILE_SHARE_NONE, /* share_access */
6317 FILE_CREATE, /* create_disposition*/
6318 FILE_DIRECTORY_FILE, /* create_options */
6319 mod_unixmode, /* file_attributes */
6320 0, /* oplock_request */
6321 0, /* allocation_size */
6322 NULL, /* sd */
6323 NULL, /* ea_list */
6324 &fsp, /* result */
6325 &info, /* pinfo */
6326 psbuf); /* psbuf */
6327
6328 if (NT_STATUS_IS_OK(status)) {
6329 close_file(req, fsp, NORMAL_CLOSE);
6330 }
6331
6332 info_level_return = SVAL(pdata,16);
6333
6334 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6335 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6336 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6337 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6338 } else {
6339 *pdata_return_size = 12;
6340 }
6341
6342 /* Realloc the data size */
6343 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6344 if (*ppdata == NULL) {
6345 *pdata_return_size = 0;
6346 return NT_STATUS_NO_MEMORY;
6347 }
6348 pdata = *ppdata;
6349
6350 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6351 SSVAL(pdata,2,0); /* No fnum. */
6352 SIVAL(pdata,4,info); /* Was directory created. */
6353
6354 switch (info_level_return) {
6355 case SMB_QUERY_FILE_UNIX_BASIC:
6356 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6357 SSVAL(pdata,10,0); /* Padding. */
6358 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6359 break;
6360 case SMB_QUERY_FILE_UNIX_INFO2:
6361 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6362 SSVAL(pdata,10,0); /* Padding. */
6363 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6364 break;
6365 default:
6366 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6367 SSVAL(pdata,10,0); /* Padding. */
6368 break;
6369 }
6370
6371 return status;
6372 }
6373
6374 /****************************************************************************
6375 Open/Create a file with POSIX semantics.
6376 ****************************************************************************/
6377
6378 static NTSTATUS smb_posix_open(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
6379 struct smb_request *req,
6380 char **ppdata,
6381 int total_data,
6382 const char *fname,
6383 SMB_STRUCT_STAT *psbuf,
6384 int *pdata_return_size)
6385 {
6386 bool extended_oplock_granted = False;
6387 char *pdata = *ppdata;
6388 uint32 flags = 0;
6389 uint32 wire_open_mode = 0;
6390 uint32 raw_unixmode = 0;
6391 uint32 mod_unixmode = 0;
6392 uint32 create_disp = 0;
6393 uint32 access_mask = 0;
6394 uint32 create_options = 0;
6395 NTSTATUS status = NT_STATUS_OK;
6396 mode_t unixmode = (mode_t)0;
6397 files_struct *fsp = NULL;
6398 int oplock_request = 0;
6399 int info = 0;
6400 uint16 info_level_return = 0;
6401
6402 if (total_data < 18) {
6403 return NT_STATUS_INVALID_PARAMETER;
6404 }
6405
6406 flags = IVAL(pdata,0);
6407 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6408 if (oplock_request) {
6409 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6410 }
6411
6412 wire_open_mode = IVAL(pdata,4);
6413
6414 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6415 return smb_posix_mkdir(conn, req,
6416 ppdata,
6417 total_data,
6418 fname,
6419 psbuf,
6420 pdata_return_size);
6421 }
6422
6423 switch (wire_open_mode & SMB_ACCMODE) {
6424 case SMB_O_RDONLY:
6425 access_mask = FILE_READ_DATA;
6426 break;
6427 case SMB_O_WRONLY:
6428 access_mask = FILE_WRITE_DATA;
6429 break;
6430 case SMB_O_RDWR:
6431 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6432 break;
6433 default:
6434 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6435 (unsigned int)wire_open_mode ));
6436 return NT_STATUS_INVALID_PARAMETER;
6437 }
6438
6439 wire_open_mode &= ~SMB_ACCMODE;
6440
6441 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6442 create_disp = FILE_CREATE;
6443 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6444 create_disp = FILE_OVERWRITE_IF;
6445 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6446 create_disp = FILE_OPEN_IF;
6447 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6448 create_disp = FILE_OPEN;
6449 } else {
6450 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6451 (unsigned int)wire_open_mode ));
6452 return NT_STATUS_INVALID_PARAMETER;
6453 }
6454
6455 raw_unixmode = IVAL(pdata,8);
6456 /* Next 4 bytes are not yet defined. */
6457
6458 status = unix_perms_from_wire(conn,
6459 psbuf,
6460 raw_unixmode,
6461 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6462 &unixmode);
6463
6464 if (!NT_STATUS_IS_OK(status)) {
6465 return status;
6466 }
6467
6468 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6469
6470 if (wire_open_mode & SMB_O_SYNC) {
6471 create_options |= FILE_WRITE_THROUGH;
6472 }
6473 if (wire_open_mode & SMB_O_APPEND) {
6474 access_mask |= FILE_APPEND_DATA;
6475 }
6476 if (wire_open_mode & SMB_O_DIRECT) {
6477 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6478 }
6479
6480 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6481 fname,
6482 (unsigned int)wire_open_mode,
6483 (unsigned int)unixmode ));
6484
6485 status = SMB_VFS_CREATE_FILE(
6486 conn, /* conn */
6487 req, /* req */
6488 0, /* root_dir_fid */
6489 fname, /* fname */
6490 0, /* create_file_flags */
6491 access_mask, /* access_mask */
6492 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6493 FILE_SHARE_DELETE),
6494 create_disp, /* create_disposition*/
6495 FILE_NON_DIRECTORY_FILE, /* create_options */
6496 mod_unixmode, /* file_attributes */
6497 oplock_request, /* oplock_request */
6498 0, /* allocation_size */
6499 NULL, /* sd */
6500 NULL, /* ea_list */
6501 &fsp, /* result */
6502 &info, /* pinfo */
6503 psbuf); /* psbuf */
6504
6505 if (!NT_STATUS_IS_OK(status)) {
6506 return status;
6507 }
6508
6509 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6510 extended_oplock_granted = True;
6511 }
6512
6513 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6514 extended_oplock_granted = True;
6515 }
6516
6517 info_level_return = SVAL(pdata,16);
6518
6519 /* Allocate the correct return size. */
6520
6521 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6522 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6523 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6524 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6525 } else {
6526 *pdata_return_size = 12;
6527 }
6528
6529 /* Realloc the data size */
6530 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6531 if (*ppdata == NULL) {
6532 close_file(req, fsp, ERROR_CLOSE);
6533 *pdata_return_size = 0;
6534 return NT_STATUS_NO_MEMORY;
6535 }
6536 pdata = *ppdata;
6537
6538 if (extended_oplock_granted) {
6539 if (flags & REQUEST_BATCH_OPLOCK) {
6540 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6541 } else {
6542 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6543 }
6544 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6545 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6546 } else {
6547 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6548 }
6549
6550 SSVAL(pdata,2,fsp->fnum);
6551 SIVAL(pdata,4,info); /* Was file created etc. */
6552
6553 switch (info_level_return) {
6554 case SMB_QUERY_FILE_UNIX_BASIC:
6555 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6556 SSVAL(pdata,10,0); /* padding. */
6557 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6558 break;
6559 case SMB_QUERY_FILE_UNIX_INFO2:
6560 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6561 SSVAL(pdata,10,0); /* padding. */
6562 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6563 break;
6564 default:
6565 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6566 SSVAL(pdata,10,0); /* padding. */
6567 break;
6568 }
6569 return NT_STATUS_OK;
6570 }
6571
6572 /****************************************************************************
6573 Delete a file with POSIX semantics.
6574 ****************************************************************************/
6575
6576 static NTSTATUS smb_posix_unlink(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
6577 struct smb_request *req,
6578 const char *pdata,
6579 int total_data,
6580 const char *fname,
6581 SMB_STRUCT_STAT *psbuf)
6582 {
6583 NTSTATUS status = NT_STATUS_OK;
6584 files_struct *fsp = NULL;
6585 uint16 flags = 0;
6586 char del = 1;
6587 int info = 0;
6588 int create_options = 0;
6589 int i;
6590 struct share_mode_lock *lck = NULL;
6591
6592 if (total_data < 2) {
6593 return NT_STATUS_INVALID_PARAMETER;
6594 }
6595
6596 flags = SVAL(pdata,0);
6597
6598 if (!VALID_STAT(*psbuf)) {
6599 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6600 }
6601
6602 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6603 !VALID_STAT_OF_DIR(*psbuf)) {
6604 return NT_STATUS_NOT_A_DIRECTORY;
6605 }
6606
6607 DEBUG(10,("smb_posix_unlink: %s %s\n",
6608 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6609 fname));
6610
6611 if (VALID_STAT_OF_DIR(*psbuf)) {
6612 create_options |= FILE_DIRECTORY_FILE;
6613 }
6614
6615 status = SMB_VFS_CREATE_FILE(
6616 conn, /* conn */
6617 req, /* req */
6618 0, /* root_dir_fid */
6619 fname, /* fname */
6620 0, /* create_file_flags */
6621 DELETE_ACCESS, /* access_mask */
6622 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6623 FILE_SHARE_DELETE),
6624 FILE_OPEN, /* create_disposition*/
6625 create_options, /* create_options */
6626 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6627 0, /* oplock_request */
6628 0, /* allocation_size */
6629 NULL, /* sd */
6630 NULL, /* ea_list */
6631 &fsp, /* result */
6632 &info, /* pinfo */
6633 psbuf); /* psbuf */
6634
6635 if (!NT_STATUS_IS_OK(status)) {
6636 return status;
6637 }
6638
6639 /*
6640 * Don't lie to client. If we can't really delete due to
6641 * non-POSIX opens return SHARING_VIOLATION.
6642 */
6643
6644 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6645 NULL);
6646 if (lck == NULL) {
6647 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6648 "lock for file %s\n", fsp->fsp_name));
6649 close_file(req, fsp, NORMAL_CLOSE);
6650 return NT_STATUS_INVALID_PARAMETER;
6651 }
6652
6653 /*
6654 * See if others still have the file open. If this is the case, then
6655 * don't delete. If all opens are POSIX delete we can set the delete
6656 * on close disposition.
6657 */
6658 for (i=0; i<lck->num_share_modes; i++) {
6659 struct share_mode_entry *e = &lck->share_modes[i];
6660 if (is_valid_share_mode_entry(e)) {
6661 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6662 continue;
6663 }
6664 /* Fail with sharing violation. */
6665 close_file(req, fsp, NORMAL_CLOSE);
6666 TALLOC_FREE(lck);
6667 return NT_STATUS_SHARING_VIOLATION;
6668 }
6669 }
6670
6671 /*
6672 * Set the delete on close.
6673 */
6674 status = smb_set_file_disposition_info(conn,
6675 &del,
6676 1,
6677 fsp,
6678 fname,
6679 psbuf);
6680
6681 if (!NT_STATUS_IS_OK(status)) {
6682 close_file(req, fsp, NORMAL_CLOSE);
6683 TALLOC_FREE(lck);
6684 return status;
6685 }
6686 TALLOC_FREE(lck);
6687 return close_file(req, fsp, NORMAL_CLOSE);
6688 }
6689
6690 /****************************************************************************
6691 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6692 ****************************************************************************/
6693
6694 static void call_trans2setfilepathinfo(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
6695 struct smb_request *req,
6696 unsigned int tran_call,
6697 char **pparams, int total_params,
6698 char **ppdata, int total_data,
6699 unsigned int max_data_bytes)
6700 {
6701 char *params = *pparams;
6702 char *pdata = *ppdata;
6703 uint16 info_level;
6704 SMB_STRUCT_STAT sbuf;
6705 char *fname = NULL;
6706 files_struct *fsp = NULL;
6707 NTSTATUS status = NT_STATUS_OK;
6708 int data_return_size = 0;
6709 TALLOC_CTX *ctx = talloc_tos();
6710
6711 if (!params) {
6712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6713 return;
6714 }
6715
6716 ZERO_STRUCT(sbuf);
6717
6718 if (tran_call == TRANSACT2_SETFILEINFO) {
6719 if (total_params < 4) {
6720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6721 return;
6722 }
6723
6724 fsp = file_fsp(req, SVAL(params,0));
6725 /* Basic check for non-null fsp. */
6726 if (!check_fsp_open(conn, req, fsp)) {
6727 return;
6728 }
6729 info_level = SVAL(params,2);
6730
6731 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6732 if (!fname) {
6733 reply_nterror(req, NT_STATUS_NO_MEMORY);
6734 return;
6735 }
6736
6737 if(fsp->is_directory || fsp->fh->fd == -1) {
6738 /*
6739 * This is actually a SETFILEINFO on a directory
6740 * handle (returned from an NT SMB). NT5.0 seems
6741 * to do this call. JRA.
6742 */
6743 if (INFO_LEVEL_IS_UNIX(info_level)) {
6744 /* Always do lstat for UNIX calls. */
6745 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6746 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6747 reply_unixerror(req,ERRDOS,ERRbadpath);
6748 return;
6749 }
6750 } else {
6751 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6752 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6753 reply_unixerror(req,ERRDOS,ERRbadpath);
6754 return;
6755 }
6756 }
6757 } else if (fsp->print_file) {
6758 /*
6759 * Doing a DELETE_ON_CLOSE should cancel a print job.
6760 */
6761 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6762 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6763
6764 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6765
6766 SSVAL(params,0,0);
6767 send_trans2_replies(conn, req, params, 2,
6768 *ppdata, 0,
6769 max_data_bytes);
6770 return;
6771 } else {
6772 reply_unixerror(req, ERRDOS, ERRbadpath);
6773 return;
6774 }
6775 } else {
6776 /*
6777 * Original code - this is an open file.
6778 */
6779 if (!check_fsp(conn, req, fsp)) {
6780 return;
6781 }
6782
6783 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6784 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6785 reply_unixerror(req, ERRDOS, ERRbadfid);
6786 return;
6787 }
6788 }
6789 } else {
6790 /* set path info */
6791 if (total_params < 7) {
6792 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6793 return;
6794 }
6795
6796 info_level = SVAL(params,0);
6797 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6798 total_params - 6, STR_TERMINATE,
6799 &status);
6800 if (!NT_STATUS_IS_OK(status)) {
6801 reply_nterror(req, status);
6802 return;
6803 }
6804
6805 status = resolve_dfspath(ctx, conn,
6806 req->flags2 & FLAGS2_DFS_PATHNAMES,
6807 fname,
6808 &fname);
6809 if (!NT_STATUS_IS_OK(status)) {
6810 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6811 reply_botherror(req,
6812 NT_STATUS_PATH_NOT_COVERED,
6813 ERRSRV, ERRbadpath);
6814 return;
6815 }
6816 reply_nterror(req, status);
6817 return;
6818 }
6819
6820 status = unix_convert(ctx, conn, fname, False,
6821 &fname, NULL, &sbuf);
6822 if (!NT_STATUS_IS_OK(status)) {
6823 reply_nterror(req, status);
6824 return;
6825 }
6826
6827 status = check_name(conn, fname);
6828 if (!NT_STATUS_IS_OK(status)) {
6829 reply_nterror(req, status);
6830 return;
6831 }
6832
6833 if (INFO_LEVEL_IS_UNIX(info_level)) {
6834 /*
6835 * For CIFS UNIX extensions the target name may not exist.
6836 */
6837
6838 /* Always do lstat for UNIX calls. */
6839 SMB_VFS_LSTAT(conn,fname,&sbuf);
6840
6841 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6842 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6843 reply_unixerror(req, ERRDOS, ERRbadpath);
6844 return;
6845 }
6846 }
6847
6848 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6849 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6850 return;
6851 }
6852
6853 if (!CAN_WRITE(conn)) {
6854 /* Allow POSIX opens. The open path will deny
6855 * any non-readonly opens. */
6856 if (info_level != SMB_POSIX_PATH_OPEN) {
6857 reply_doserror(req, ERRSRV, ERRaccess);
6858 return;
6859 }
6860 }
6861
6862 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6863 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6864
6865 /* Realloc the parameter size */
6866 *pparams = (char *)SMB_REALLOC(*pparams,2);
6867 if (*pparams == NULL) {
6868 reply_nterror(req, NT_STATUS_NO_MEMORY);
6869 return;
6870 }
6871 params = *pparams;
6872
6873 SSVAL(params,0,0);
6874
6875 switch (info_level) {
6876
6877 case SMB_INFO_STANDARD:
6878 {
6879 status = smb_set_info_standard(conn,
6880 pdata,
6881 total_data,
6882 fsp,
6883 fname,
6884 &sbuf);
6885 break;
6886 }
6887
6888 case SMB_INFO_SET_EA:
6889 {
6890 status = smb_info_set_ea(conn,
6891 pdata,
6892 total_data,
6893 fsp,
6894 fname);
6895 break;
6896 }
6897
6898 case SMB_SET_FILE_BASIC_INFO:
6899 case SMB_FILE_BASIC_INFORMATION:
6900 {
6901 status = smb_set_file_basic_info(conn,
6902 pdata,
6903 total_data,
6904 fsp,
6905 fname,
6906 &sbuf);
6907 break;
6908 }
6909
6910 case SMB_FILE_ALLOCATION_INFORMATION:
6911 case SMB_SET_FILE_ALLOCATION_INFO:
6912 {
6913 status = smb_set_file_allocation_info(conn, req,
6914 pdata,
6915 total_data,
6916 fsp,
6917 fname,
6918 &sbuf);
6919 break;
6920 }
6921
6922 case SMB_FILE_END_OF_FILE_INFORMATION:
6923 case SMB_SET_FILE_END_OF_FILE_INFO:
6924 {
6925 status = smb_set_file_end_of_file_info(conn, req,
6926 pdata,
6927 total_data,
6928 fsp,
6929 fname,
6930 &sbuf);
6931 break;
6932 }
6933
6934 case SMB_FILE_DISPOSITION_INFORMATION:
6935 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6936 {
6937 #if 0
6938 /* JRA - We used to just ignore this on a path ?
6939 * Shouldn't this be invalid level on a pathname
6940 * based call ?
6941 */
6942 if (tran_call != TRANSACT2_SETFILEINFO) {
6943 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6944 }
6945 #endif
6946 status = smb_set_file_disposition_info(conn,
6947 pdata,
6948 total_data,
6949 fsp,
6950 fname,
6951 &sbuf);
6952 break;
6953 }
6954
6955 case SMB_FILE_POSITION_INFORMATION:
6956 {
6957 status = smb_file_position_information(conn,
6958 pdata,
6959 total_data,
6960 fsp);
6961 break;
6962 }
6963
6964 /* From tridge Samba4 :
6965 * MODE_INFORMATION in setfileinfo (I have no
6966 * idea what "mode information" on a file is - it takes a value of 0,
6967 * 2, 4 or 6. What could it be?).
6968 */
6969
6970 case SMB_FILE_MODE_INFORMATION:
6971 {
6972 status = smb_file_mode_information(conn,
6973 pdata,
6974 total_data);
6975 break;
6976 }
6977
6978 /*
6979 * CIFS UNIX extensions.
6980 */
6981
6982 case SMB_SET_FILE_UNIX_BASIC:
6983 {
6984 status = smb_set_file_unix_basic(conn, req,
6985 pdata,
6986 total_data,
6987 fsp,
6988 fname,
6989 &sbuf);
6990 break;
6991 }
6992
6993 case SMB_SET_FILE_UNIX_INFO2:
6994 {
6995 status = smb_set_file_unix_info2(conn, req,
6996 pdata,
6997 total_data,
6998 fsp,
6999 fname,
7000 &sbuf);
7001 break;
7002 }
7003
7004 case SMB_SET_FILE_UNIX_LINK:
7005 {
7006 if (tran_call != TRANSACT2_SETPATHINFO) {
7007 /* We must have a pathname for this. */
7008 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7009 return;
7010 }
7011 status = smb_set_file_unix_link(conn, req, pdata,
7012 total_data, fname);
7013 break;
7014 }
7015
7016 case SMB_SET_FILE_UNIX_HLINK:
7017 {
7018 if (tran_call != TRANSACT2_SETPATHINFO) {
7019 /* We must have a pathname for this. */
7020 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7021 return;
7022 }
7023 status = smb_set_file_unix_hlink(conn, req,
7024 pdata, total_data,
7025 fname);
7026 break;
7027 }
7028
7029 case SMB_FILE_RENAME_INFORMATION:
7030 {
7031 status = smb_file_rename_information(conn, req,
7032 pdata, total_data,
7033 fsp, fname);
7034 break;
7035 }
7036
7037 #if defined(HAVE_POSIX_ACLS)
7038 case SMB_SET_POSIX_ACL:
7039 {
7040 status = smb_set_posix_acl(conn,
7041 pdata,
7042 total_data,
7043 fsp,
7044 fname,
7045 &sbuf);
7046 break;
7047 }
7048 #endif
7049
7050 case SMB_SET_POSIX_LOCK:
7051 {
7052 if (tran_call != TRANSACT2_SETFILEINFO) {
7053 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7054 return;
7055 }
7056 status = smb_set_posix_lock(conn, req,
7057 pdata, total_data, fsp);
7058 break;
7059 }
7060
7061 case SMB_POSIX_PATH_OPEN:
7062 {
7063 if (tran_call != TRANSACT2_SETPATHINFO) {
7064 /* We must have a pathname for this. */
7065 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7066 return;
7067 }
7068
7069 status = smb_posix_open(conn, req,
7070 ppdata,
7071 total_data,
7072 fname,
7073 &sbuf,
7074 &data_return_size);
7075 break;
7076 }
7077
7078 case SMB_POSIX_PATH_UNLINK:
7079 {
7080 if (tran_call != TRANSACT2_SETPATHINFO) {
7081 /* We must have a pathname for this. */
7082 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7083 return;
7084 }
7085
7086 status = smb_posix_unlink(conn, req,
7087 pdata,
7088 total_data,
7089 fname,
7090 &sbuf);
7091 break;
7092 }
7093
7094 default:
7095 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7096 return;
7097 }
7098
7099
7100 if (!NT_STATUS_IS_OK(status)) {
7101 if (open_was_deferred(req->mid)) {
7102 /* We have re-scheduled this call. */
7103 return;
7104 }
7105 if (blocking_lock_was_deferred(req->mid)) {
7106 /* We have re-scheduled this call. */
7107 return;
7108 }
7109 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7110 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7111 ERRSRV, ERRbadpath);
7112 return;
7113 }
7114 if (info_level == SMB_POSIX_PATH_OPEN) {
7115 reply_openerror(req, status);
7116 return;
7117 }
7118
7119 reply_nterror(req, status);
7120 return;
7121 }
7122
7123 SSVAL(params,0,0);
7124 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7125 max_data_bytes);
7126
7127 return;
7128 }
7129
7130 /****************************************************************************
7131 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7132 ****************************************************************************/
7133
7134 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
/* [<][>][^][v][top][bottom][index][help] */
7135 char **pparams, int total_params,
7136 char **ppdata, int total_data,
7137 unsigned int max_data_bytes)
7138 {
7139 char *params = *pparams;
7140 char *pdata = *ppdata;
7141 char *directory = NULL;
7142 SMB_STRUCT_STAT sbuf;
7143 NTSTATUS status = NT_STATUS_OK;
7144 struct ea_list *ea_list = NULL;
7145 TALLOC_CTX *ctx = talloc_tos();
7146
7147 if (!CAN_WRITE(conn)) {
7148 reply_doserror(req, ERRSRV, ERRaccess);
7149 return;
7150 }
7151
7152 if (total_params < 5) {
7153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7154 return;
7155 }
7156
7157 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7158 total_params - 4, STR_TERMINATE,
7159 &status);
7160 if (!NT_STATUS_IS_OK(status)) {
7161 reply_nterror(req, status);
7162 return;
7163 }
7164
7165 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7166
7167 status = resolve_dfspath(ctx,
7168 conn,
7169 req->flags2 & FLAGS2_DFS_PATHNAMES,
7170 directory,
7171 &directory);
7172 if (!NT_STATUS_IS_OK(status)) {
7173 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7174 reply_botherror(req,
7175 NT_STATUS_PATH_NOT_COVERED,
7176 ERRSRV, ERRbadpath);
7177 }
7178 reply_nterror(req, status);
7179 return;
7180 }
7181
7182 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7183 if (!NT_STATUS_IS_OK(status)) {
7184 reply_nterror(req, status);
7185 return;
7186 }
7187
7188 status = check_name(conn, directory);
7189 if (!NT_STATUS_IS_OK(status)) {
7190 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7191 reply_nterror(req, status);
7192 return;
7193 }
7194
7195 /* Any data in this call is an EA list. */
7196 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7197 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7198 return;
7199 }
7200
7201 /*
7202 * OS/2 workplace shell seems to send SET_EA requests of "null"
7203 * length (4 bytes containing IVAL 4).
7204 * They seem to have no effect. Bug #3212. JRA.
7205 */
7206
7207 if (total_data != 4) {
7208 if (total_data < 10) {
7209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7210 return;
7211 }
7212
7213 if (IVAL(pdata,0) > total_data) {
7214 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7215 IVAL(pdata,0), (unsigned int)total_data));
7216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7217 return;
7218 }
7219
7220 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7221 total_data - 4);
7222 if (!ea_list) {
7223 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7224 return;
7225 }
7226 }
7227 /* If total_data == 4 Windows doesn't care what values
7228 * are placed in that field, it just ignores them.
7229 * The System i QNTC IBM SMB client puts bad values here,
7230 * so ignore them. */
7231
7232 status = create_directory(conn, req, directory);
7233
7234 if (!NT_STATUS_IS_OK(status)) {
7235 reply_nterror(req, status);
7236 return;
7237 }
7238
7239 /* Try and set any given EA. */
7240 if (ea_list) {
7241 status = set_ea(conn, NULL, directory, ea_list);
7242 if (!NT_STATUS_IS_OK(status)) {
7243 reply_nterror(req, status);
7244 return;
7245 }
7246 }
7247
7248 /* Realloc the parameter and data sizes */
7249 *pparams = (char *)SMB_REALLOC(*pparams,2);
7250 if(*pparams == NULL) {
7251 reply_nterror(req, NT_STATUS_NO_MEMORY);
7252 return;
7253 }
7254 params = *pparams;
7255
7256 SSVAL(params,0,0);
7257
7258 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7259
7260 return;
7261 }
7262
7263 /****************************************************************************
7264 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7265 We don't actually do this - we just send a null response.
7266 ****************************************************************************/
7267
7268 static void call_trans2findnotifyfirst(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
7269 struct smb_request *req,
7270 char **pparams, int total_params,
7271 char **ppdata, int total_data,
7272 unsigned int max_data_bytes)
7273 {
7274 char *params = *pparams;
7275 uint16 info_level;
7276
7277 if (total_params < 6) {
7278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7279 return;
7280 }
7281
7282 info_level = SVAL(params,4);
7283 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7284
7285 switch (info_level) {
7286 case 1:
7287 case 2:
7288 break;
7289 default:
7290 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7291 return;
7292 }
7293
7294 /* Realloc the parameter and data sizes */
7295 *pparams = (char *)SMB_REALLOC(*pparams,6);
7296 if (*pparams == NULL) {
7297 reply_nterror(req, NT_STATUS_NO_MEMORY);
7298 return;
7299 }
7300 params = *pparams;
7301
7302 SSVAL(params,0,fnf_handle);
7303 SSVAL(params,2,0); /* No changes */
7304 SSVAL(params,4,0); /* No EA errors */
7305
7306 fnf_handle++;
7307
7308 if(fnf_handle == 0)
7309 fnf_handle = 257;
7310
7311 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7312
7313 return;
7314 }
7315
7316 /****************************************************************************
7317 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7318 changes). Currently this does nothing.
7319 ****************************************************************************/
7320
7321 static void call_trans2findnotifynext(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
7322 struct smb_request *req,
7323 char **pparams, int total_params,
7324 char **ppdata, int total_data,
7325 unsigned int max_data_bytes)
7326 {
7327 char *params = *pparams;
7328
7329 DEBUG(3,("call_trans2findnotifynext\n"));
7330
7331 /* Realloc the parameter and data sizes */
7332 *pparams = (char *)SMB_REALLOC(*pparams,4);
7333 if (*pparams == NULL) {
7334 reply_nterror(req, NT_STATUS_NO_MEMORY);
7335 return;
7336 }
7337 params = *pparams;
7338
7339 SSVAL(params,0,0); /* No changes */
7340 SSVAL(params,2,0); /* No EA errors */
7341
7342 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7343
7344 return;
7345 }
7346
7347 /****************************************************************************
7348 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7349 ****************************************************************************/
7350
7351 static void call_trans2getdfsreferral(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
7352 struct smb_request *req,
7353 char **pparams, int total_params,
7354 char **ppdata, int total_data,
7355 unsigned int max_data_bytes)
7356 {
7357 char *params = *pparams;
7358 char *pathname = NULL;
7359 int reply_size = 0;
7360 int max_referral_level;
7361 NTSTATUS status = NT_STATUS_OK;
7362 TALLOC_CTX *ctx = talloc_tos();
7363
7364 DEBUG(10,("call_trans2getdfsreferral\n"));
7365
7366 if (total_params < 3) {
7367 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7368 return;
7369 }
7370
7371 max_referral_level = SVAL(params,0);
7372
7373 if(!lp_host_msdfs()) {
7374 reply_doserror(req, ERRDOS, ERRbadfunc);
7375 return;
7376 }
7377
7378 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7379 total_params - 2, STR_TERMINATE);
7380 if (!pathname) {
7381 reply_nterror(req, NT_STATUS_NOT_FOUND);
7382 return;
7383 }
7384 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7385 ppdata,&status)) < 0) {
7386 reply_nterror(req, status);
7387 return;
7388 }
7389
7390 SSVAL(req->inbuf, smb_flg2,
7391 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7392 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7393
7394 return;
7395 }
7396
7397 #define LMCAT_SPL 0x53
7398 #define LMFUNC_GETJOBID 0x60
7399
7400 /****************************************************************************
7401 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7402 ****************************************************************************/
7403
7404 static void call_trans2ioctl(connection_struct *conn,
/* [<][>][^][v][top][bottom][index][help] */
7405 struct smb_request *req,
7406 char **pparams, int total_params,
7407 char **ppdata, int total_data,
7408 unsigned int max_data_bytes)
7409 {
7410 char *pdata = *ppdata;
7411 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7412
7413 /* check for an invalid fid before proceeding */
7414
7415 if (!fsp) {
7416 reply_doserror(req, ERRDOS, ERRbadfid);
7417 return;
7418 }
7419
7420 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7421 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7422 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7423 if (*ppdata == NULL) {
7424 reply_nterror(req, NT_STATUS_NO_MEMORY);
7425 return;
7426 }
7427 pdata = *ppdata;
7428
7429 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7430 CAN ACCEPT THIS IN UNICODE. JRA. */
7431
7432 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7433 srvstr_push(pdata, req->flags2, pdata + 2,
7434 global_myname(), 15,
7435 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7436 srvstr_push(pdata, req->flags2, pdata+18,
7437 lp_servicename(SNUM(conn)), 13,
7438 STR_ASCII|STR_TERMINATE); /* Service name */
7439 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7440 max_data_bytes);
7441 return;
7442 }
7443
7444 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7445 reply_doserror(req, ERRSRV, ERRerror);
7446 }
7447
7448 /****************************************************************************
7449 Reply to a SMBfindclose (stop trans2 directory search).
7450 ****************************************************************************/
7451
7452 void reply_findclose(struct smb_request *req)
/* [<][>][^][v][top][bottom][index][help] */
7453 {
7454 int dptr_num;
7455
7456 START_PROFILE(SMBfindclose);
7457
7458 if (req->wct < 1) {
7459 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7460 END_PROFILE(SMBfindclose);
7461 return;
7462 }
7463
7464 dptr_num = SVALS(req->vwv+0, 0);
7465
7466 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7467
7468 dptr_close(&dptr_num);
7469
7470 reply_outbuf(req, 0, 0);
7471
7472 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7473
7474 END_PROFILE(SMBfindclose);
7475 return;
7476 }
7477
7478 /****************************************************************************
7479 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7480 ****************************************************************************/
7481
7482 void reply_findnclose(struct smb_request *req)
/* [<][>][^][v][top][bottom][index][help] */
7483 {
7484 int dptr_num;
7485
7486 START_PROFILE(SMBfindnclose);
7487
7488 if (req->wct < 1) {
7489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7490 END_PROFILE(SMBfindnclose);
7491 return;
7492 }
7493
7494 dptr_num = SVAL(req->vwv+0, 0);
7495
7496 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7497
7498 /* We never give out valid handles for a
7499 findnotifyfirst - so any dptr_num is ok here.
7500 Just ignore it. */
7501
7502 reply_outbuf(req, 0, 0);
7503
7504 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7505
7506 END_PROFILE(SMBfindnclose);
7507 return;
7508 }
7509
7510 static void handle_trans2(connection_struct *conn, struct smb_request *req,
/* [<][>][^][v][top][bottom][index][help] */
7511 struct trans_state *state)
7512 {
7513 if (Protocol >= PROTOCOL_NT1) {
7514 req->flags2 |= 0x40; /* IS_LONG_NAME */
7515 SSVAL(req->inbuf,smb_flg2,req->flags2);
7516 }
7517
7518 if (conn->encrypt_level == Required && !req->encrypted) {
7519 if (state->call != TRANSACT2_QFSINFO &&
7520 state->call != TRANSACT2_SETFSINFO) {
7521 DEBUG(0,("handle_trans2: encryption required "
7522 "with call 0x%x\n",
7523 (unsigned int)state->call));
7524 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7525 return;
7526 }
7527 }
7528
7529 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7530
7531 /* Now we must call the relevant TRANS2 function */
7532 switch(state->call) {
7533 case TRANSACT2_OPEN:
7534 {
7535 START_PROFILE(Trans2_open);
7536 call_trans2open(conn, req,
7537 &state->param, state->total_param,
7538 &state->data, state->total_data,
7539 state->max_data_return);
7540 END_PROFILE(Trans2_open);
7541 break;
7542 }
7543
7544 case TRANSACT2_FINDFIRST:
7545 {
7546 START_PROFILE(Trans2_findfirst);
7547 call_trans2findfirst(conn, req,
7548 &state->param, state->total_param,
7549 &state->data, state->total_data,
7550 state->max_data_return);
7551 END_PROFILE(Trans2_findfirst);
7552 break;
7553 }
7554
7555 case TRANSACT2_FINDNEXT:
7556 {
7557 START_PROFILE(Trans2_findnext);
7558 call_trans2findnext(conn, req,
7559 &state->param, state->total_param,
7560 &state->data, state->total_data,
7561 state->max_data_return);
7562 END_PROFILE(Trans2_findnext);
7563 break;
7564 }
7565
7566 case TRANSACT2_QFSINFO:
7567 {
7568 START_PROFILE(Trans2_qfsinfo);
7569 call_trans2qfsinfo(conn, req,
7570 &state->param, state->total_param,
7571 &state->data, state->total_data,
7572 state->max_data_return);
7573 END_PROFILE(Trans2_qfsinfo);
7574 break;
7575 }
7576
7577 case TRANSACT2_SETFSINFO:
7578 {
7579 START_PROFILE(Trans2_setfsinfo);
7580 call_trans2setfsinfo(conn, req,
7581 &state->param, state->total_param,
7582 &state->data, state->total_data,
7583 state->max_data_return);
7584 END_PROFILE(Trans2_setfsinfo);
7585 break;
7586 }
7587
7588 case TRANSACT2_QPATHINFO:
7589 case TRANSACT2_QFILEINFO:
7590 {
7591 START_PROFILE(Trans2_qpathinfo);
7592 call_trans2qfilepathinfo(conn, req, state->call,
7593 &state->param, state->total_param,
7594 &state->data, state->total_data,
7595 state->max_data_return);
7596 END_PROFILE(Trans2_qpathinfo);
7597 break;
7598 }
7599
7600 case TRANSACT2_SETPATHINFO:
7601 case TRANSACT2_SETFILEINFO:
7602 {
7603 START_PROFILE(Trans2_setpathinfo);
7604 call_trans2setfilepathinfo(conn, req, state->call,
7605 &state->param, state->total_param,
7606 &state->data, state->total_data,
7607 state->max_data_return);
7608 END_PROFILE(Trans2_setpathinfo);
7609 break;
7610 }
7611
7612 case TRANSACT2_FINDNOTIFYFIRST:
7613 {
7614 START_PROFILE(Trans2_findnotifyfirst);
7615 call_trans2findnotifyfirst(conn, req,
7616 &state->param, state->total_param,
7617 &state->data, state->total_data,
7618 state->max_data_return);
7619 END_PROFILE(Trans2_findnotifyfirst);
7620 break;
7621 }
7622
7623 case TRANSACT2_FINDNOTIFYNEXT:
7624 {
7625 START_PROFILE(Trans2_findnotifynext);
7626 call_trans2findnotifynext(conn, req,
7627 &state->param, state->total_param,
7628 &state->data, state->total_data,
7629 state->max_data_return);
7630 END_PROFILE(Trans2_findnotifynext);
7631 break;
7632 }
7633
7634 case TRANSACT2_MKDIR:
7635 {
7636 START_PROFILE(Trans2_mkdir);
7637 call_trans2mkdir(conn, req,
7638 &state->param, state->total_param,
7639 &state->data, state->total_data,
7640 state->max_data_return);
7641 END_PROFILE(Trans2_mkdir);
7642 break;
7643 }
7644
7645 case TRANSACT2_GET_DFS_REFERRAL:
7646 {
7647 START_PROFILE(Trans2_get_dfs_referral);
7648 call_trans2getdfsreferral(conn, req,
7649 &state->param, state->total_param,
7650 &state->data, state->total_data,
7651 state->max_data_return);
7652 END_PROFILE(Trans2_get_dfs_referral);
7653 break;
7654 }
7655
7656 case TRANSACT2_IOCTL:
7657 {
7658 START_PROFILE(Trans2_ioctl);
7659 call_trans2ioctl(conn, req,
7660 &state->param, state->total_param,
7661 &state->data, state->total_data,
7662 state->max_data_return);
7663 END_PROFILE(Trans2_ioctl);
7664 break;
7665 }
7666
7667 default:
7668 /* Error in request */
7669 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7670 reply_doserror(req, ERRSRV,ERRerror);
7671 }
7672 }
7673
7674 /****************************************************************************
7675 Reply to a SMBtrans2.
7676 ****************************************************************************/
7677
7678 void reply_trans2(struct smb_request *req)
/* [<][>][^][v][top][bottom][index][help] */
7679 {
7680 connection_struct *conn = req->conn;
7681 unsigned int dsoff;
7682 unsigned int dscnt;
7683 unsigned int psoff;
7684 unsigned int pscnt;
7685 unsigned int tran_call;
7686 struct trans_state *state;
7687 NTSTATUS result;
7688
7689 START_PROFILE(SMBtrans2);
7690
7691 if (req->wct < 14) {
7692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7693 END_PROFILE(SMBtrans2);
7694 return;
7695 }
7696
7697 dsoff = SVAL(req->vwv+12, 0);
7698 dscnt = SVAL(req->vwv+11, 0);
7699 psoff = SVAL(req->vwv+10, 0);
7700 pscnt = SVAL(req->vwv+9, 0);
7701 tran_call = SVAL(req->vwv+14, 0);
7702
7703 result = allow_new_trans(conn->pending_trans, req->mid);
7704 if (!NT_STATUS_IS_OK(result)) {
7705 DEBUG(2, ("Got invalid trans2 request: %s\n",
7706 nt_errstr(result)));
7707 reply_nterror(req, result);
7708 END_PROFILE(SMBtrans2);
7709 return;
7710 }
7711
7712 if (IS_IPC(conn)) {
7713 switch (tran_call) {
7714 /* List the allowed trans2 calls on IPC$ */
7715 case TRANSACT2_OPEN:
7716 case TRANSACT2_GET_DFS_REFERRAL:
7717 case TRANSACT2_QFILEINFO:
7718 case TRANSACT2_QFSINFO:
7719 case TRANSACT2_SETFSINFO:
7720 break;
7721 default:
7722 reply_doserror(req, ERRSRV, ERRaccess);
7723 END_PROFILE(SMBtrans2);
7724 return;
7725 }
7726 }
7727
7728 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7729 DEBUG(0, ("talloc failed\n"));
7730 reply_nterror(req, NT_STATUS_NO_MEMORY);
7731 END_PROFILE(SMBtrans2);
7732 return;
7733 }
7734
7735 state->cmd = SMBtrans2;
7736
7737 state->mid = req->mid;
7738 state->vuid = req->vuid;
7739 state->setup_count = SVAL(req->vwv+13, 0);
7740 state->setup = NULL;
7741 state->total_param = SVAL(req->vwv+0, 0);
7742 state->param = NULL;
7743 state->total_data = SVAL(req->vwv+1, 0);
7744 state->data = NULL;
7745 state->max_param_return = SVAL(req->vwv+2, 0);
7746 state->max_data_return = SVAL(req->vwv+3, 0);
7747 state->max_setup_return = SVAL(req->vwv+4, 0);
7748 state->close_on_completion = BITSETW(req->vwv+5, 0);
7749 state->one_way = BITSETW(req->vwv+5, 1);
7750
7751 state->call = tran_call;
7752
7753 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7754 is so as a sanity check */
7755 if (state->setup_count != 1) {
7756 /*
7757 * Need to have rc=0 for ioctl to get job id for OS/2.
7758 * Network printing will fail if function is not successful.
7759 * Similar function in reply.c will be used if protocol
7760 * is LANMAN1.0 instead of LM1.2X002.
7761 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7762 * outbuf doesn't have to be set(only job id is used).
7763 */
7764 if ( (state->setup_count == 4)
7765 && (tran_call == TRANSACT2_IOCTL)
7766 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7767 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7768 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7769 } else {
7770 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7771 DEBUG(2,("Transaction is %d\n",tran_call));
7772 TALLOC_FREE(state);
7773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7774 END_PROFILE(SMBtrans2);
7775 return;
7776 }
7777 }
7778
7779 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7780 goto bad_param;
7781
7782 if (state->total_data) {
7783
7784 if (trans_oob(state->total_data, 0, dscnt)
7785 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7786 goto bad_param;
7787 }
7788
7789 /* Can't use talloc here, the core routines do realloc on the
7790 * params and data. */
7791 state->data = (char *)SMB_MALLOC(state->total_data);
7792 if (state->data == NULL) {
7793 DEBUG(0,("reply_trans2: data malloc fail for %u "
7794 "bytes !\n", (unsigned int)state->total_data));
7795 TALLOC_FREE(state);
7796 reply_nterror(req, NT_STATUS_NO_MEMORY);
7797 END_PROFILE(SMBtrans2);
7798 return;
7799 }
7800
7801 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7802 }
7803
7804 if (state->total_param) {
7805
7806 if (trans_oob(state->total_param, 0, pscnt)
7807 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7808 goto bad_param;
7809 }
7810
7811 /* Can't use talloc here, the core routines do realloc on the
7812 * params and data. */
7813 state->param = (char *)SMB_MALLOC(state->total_param);
7814 if (state->param == NULL) {
7815 DEBUG(0,("reply_trans: param malloc fail for %u "
7816 "bytes !\n", (unsigned int)state->total_param));
7817 SAFE_FREE(state->data);
7818 TALLOC_FREE(state);
7819 reply_nterror(req, NT_STATUS_NO_MEMORY);
7820 END_PROFILE(SMBtrans2);
7821 return;
7822 }
7823
7824 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7825 }
7826
7827 state->received_data = dscnt;
7828 state->received_param = pscnt;
7829
7830 if ((state->received_param == state->total_param) &&
7831 (state->received_data == state->total_data)) {
7832
7833 handle_trans2(conn, req, state);
7834
7835 SAFE_FREE(state->data);
7836 SAFE_FREE(state->param);
7837 TALLOC_FREE(state);
7838 END_PROFILE(SMBtrans2);
7839 return;
7840 }
7841
7842 DLIST_ADD(conn->pending_trans, state);
7843
7844 /* We need to send an interim response then receive the rest
7845 of the parameter/data bytes */
7846 reply_outbuf(req, 0, 0);
7847 show_msg((char *)req->outbuf);
7848 END_PROFILE(SMBtrans2);
7849 return;
7850
7851 bad_param:
7852
7853 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7854 SAFE_FREE(state->data);
7855 SAFE_FREE(state->param);
7856 TALLOC_FREE(state);
7857 END_PROFILE(SMBtrans2);
7858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7859 }
7860
7861
7862 /****************************************************************************
7863 Reply to a SMBtranss2
7864 ****************************************************************************/
7865
7866 void reply_transs2(struct smb_request *req)
/* [<][>][^][v][top][bottom][index][help] */
7867 {
7868 connection_struct *conn = req->conn;
7869 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7870 struct trans_state *state;
7871
7872 START_PROFILE(SMBtranss2);
7873
7874 show_msg((char *)req->inbuf);
7875
7876 if (req->wct < 8) {
7877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7878 END_PROFILE(SMBtranss2);
7879 return;
7880 }
7881
7882 for (state = conn->pending_trans; state != NULL;
7883 state = state->next) {
7884 if (state->mid == req->mid) {
7885 break;
7886 }
7887 }
7888
7889 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7891 END_PROFILE(SMBtranss2);
7892 return;
7893 }
7894
7895 /* Revise state->total_param and state->total_data in case they have
7896 changed downwards */
7897
7898 if (SVAL(req->vwv+0, 0) < state->total_param)
7899 state->total_param = SVAL(req->vwv+0, 0);
7900 if (SVAL(req->vwv+1, 0) < state->total_data)
7901 state->total_data = SVAL(req->vwv+1, 0);
7902
7903 pcnt = SVAL(req->vwv+2, 0);
7904 poff = SVAL(req->vwv+3, 0);
7905 pdisp = SVAL(req->vwv+4, 0);
7906
7907 dcnt = SVAL(req->vwv+5, 0);
7908 doff = SVAL(req->vwv+6, 0);
7909 ddisp = SVAL(req->vwv+7, 0);
7910
7911 state->received_param += pcnt;
7912 state->received_data += dcnt;
7913
7914 if ((state->received_data > state->total_data) ||
7915 (state->received_param > state->total_param))
7916 goto bad_param;
7917
7918 if (pcnt) {
7919 if (trans_oob(state->total_param, pdisp, pcnt)
7920 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7921 goto bad_param;
7922 }
7923 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7924 }
7925
7926 if (dcnt) {
7927 if (trans_oob(state->total_data, ddisp, dcnt)
7928 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7929 goto bad_param;
7930 }
7931 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7932 }
7933
7934 if ((state->received_param < state->total_param) ||
7935 (state->received_data < state->total_data)) {
7936 END_PROFILE(SMBtranss2);
7937 return;
7938 }
7939
7940 handle_trans2(conn, req, state);
7941
7942 DLIST_REMOVE(conn->pending_trans, state);
7943 SAFE_FREE(state->data);
7944 SAFE_FREE(state->param);
7945 TALLOC_FREE(state);
7946
7947 END_PROFILE(SMBtranss2);
7948 return;
7949
7950 bad_param:
7951
7952 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7953 DLIST_REMOVE(conn->pending_trans, state);
7954 SAFE_FREE(state->data);
7955 SAFE_FREE(state->param);
7956 TALLOC_FREE(state);
7957 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7958 END_PROFILE(SMBtranss2);
7959 return;
7960 }