2 Unix SMB/CIFS implementation.
4 Copyright (C) Jeremy Allison 2022
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "smbd/smbd.h"
22 #include "passdb/lookup_sid.h"
23 #include "librpc/gen_ndr/ndr_security.h"
24 #include "libcli/security/security.h"
27 * SMB2 POSIX create context return details.
29 ssize_t
smb2_posix_cc_info(
30 connection_struct
*conn
,
32 const SMB_STRUCT_STAT
*psbuf
,
33 const struct dom_sid
*owner
,
34 const struct dom_sid
*group
,
38 size_t owner_sid_size
= ndr_size_dom_sid(owner
, 0);
39 size_t group_sid_size
= ndr_size_dom_sid(group
, 0);
42 owner_sid_size
= ndr_size_dom_sid(owner
, 0);
43 if (b_size
+ owner_sid_size
< b_size
) {
46 b_size
+= owner_sid_size
;
48 group_sid_size
= ndr_size_dom_sid(group
, 0);
49 if (b_size
+ group_sid_size
< b_size
) {
52 b_size
+= group_sid_size
;
54 if (buflen
< b_size
) {
58 /* number of hard links */
59 PUSH_LE_U32(buf
, 0, psbuf
->st_ex_nlink
);
61 /* Reparse tag if FILE_FLAG_REPARSE is set, else zero. */
62 PUSH_LE_U32(buf
, 4, reparse_tag
);
65 * Remove type info from mode, leaving only the
66 * permissions and setuid/gid bits.
70 unix_perms_to_wire(psbuf
->st_ex_mode
& ~S_IFMT
));
75 /* Now add in the owner and group sids. */
76 sid_linearize(buf
, buflen
, owner
);
77 buf
+= owner_sid_size
;
78 buflen
-= owner_sid_size
;
80 sid_linearize(buf
, buflen
, group
);
86 * SMB2 POSIX info level.
88 ssize_t
store_smb2_posix_info(
89 connection_struct
*conn
,
90 const SMB_STRUCT_STAT
*psbuf
,
92 uint32_t dos_attributes
,
96 uint64_t file_id
= SMB_VFS_FS_FILE_ID(conn
, psbuf
);
97 struct dom_sid owner
= global_sid_NULL
;
98 struct dom_sid group
= global_sid_NULL
;
101 if (psbuf
->st_ex_uid
!= (uid_t
)-1) {
102 uid_to_sid(&owner
, psbuf
->st_ex_uid
);
104 if (psbuf
->st_ex_gid
!= (gid_t
)-1) {
105 gid_to_sid(&group
, psbuf
->st_ex_gid
);
108 cc_len
= smb2_posix_cc_info(
109 conn
, reparse_tag
, psbuf
, &owner
, &group
, NULL
, 0);
115 if (cc_len
+ 68 < 68) {
119 if (buflen
< cc_len
+ 68) {
125 /* Birth (creation) time. */
126 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
130 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
133 /* Last write time. */
134 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
138 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
142 /* File size 64 Bit */
143 SOFF_T(buf
,32, get_file_size_stat(psbuf
));
145 /* Number of bytes used on disk - 64 Bit */
146 SOFF_T(buf
,40,SMB_VFS_GET_ALLOC_SIZE(conn
,NULL
,psbuf
));
149 if (S_ISREG(psbuf
->st_ex_mode
)) {
150 PUSH_LE_U32(buf
, 48, dos_attributes
);
151 } else if (S_ISDIR(psbuf
->st_ex_mode
)) {
152 PUSH_LE_U32(buf
, 48, dos_attributes
|FILE_ATTRIBUTE_DIRECTORY
);
155 * All non-directory or regular files are reported
156 * as reparse points. Client may or may not be able
159 PUSH_LE_U32(buf
, 48, FILE_ATTRIBUTE_REPARSE_POINT
);
162 /* Add the inode and dev (16 bytes). */
163 PUSH_LE_U64(buf
, 52, file_id
);
164 PUSH_LE_U64(buf
, 60, psbuf
->st_ex_dev
);
167 * Append a POSIX create context (variable bytes).