s3: smbd: Make extract_snapshot_token() a wrapper for extract_snapshot_token_internal().
[Samba.git] / source3 / smbd / smb2_posix.c
blob7c56af917e4a7b14444215cd4851a943983cf2a2
1 /*
2 Unix SMB/CIFS implementation.
3 SMB2 POSIX code.
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/>.
20 #include "includes.h"
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,
31 uint32_t reparse_tag,
32 const SMB_STRUCT_STAT *psbuf,
33 const struct dom_sid *owner,
34 const struct dom_sid *group,
35 uint8_t *buf,
36 size_t buflen)
38 size_t owner_sid_size = ndr_size_dom_sid(owner, 0);
39 size_t group_sid_size = ndr_size_dom_sid(group, 0);
40 size_t b_size = 12;
42 owner_sid_size = ndr_size_dom_sid(owner, 0);
43 if (b_size + owner_sid_size < b_size) {
44 return -1;
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) {
50 return -1;
52 b_size += group_sid_size;
54 if (buflen < b_size) {
55 return 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.
68 PUSH_LE_U32(buf,
70 unix_perms_to_wire(psbuf->st_ex_mode & ~S_IFMT));
72 buf += 12;
73 buflen -= 12;
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);
82 return b_size;
86 * SMB2 POSIX info level.
88 ssize_t store_smb2_posix_info(
89 connection_struct *conn,
90 const SMB_STRUCT_STAT *psbuf,
91 uint32_t reparse_tag,
92 uint32_t dos_attributes,
93 uint8_t *buf,
94 size_t buflen)
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;
99 ssize_t cc_len;
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);
111 if (cc_len == -1) {
112 return -1;
115 if (cc_len + 68 < 68) {
116 return -1;
119 if (buflen < cc_len + 68) {
120 return cc_len + 68;
123 /* Timestamps. */
125 /* Birth (creation) time. */
126 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,
127 (char *)buf+0,
128 psbuf->st_ex_btime);
129 /* Access time. */
130 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,
131 (char *)buf+8,
132 psbuf->st_ex_atime);
133 /* Last write time. */
134 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,
135 (char *)buf+16,
136 psbuf->st_ex_mtime);
137 /* Change time. */
138 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,
139 (char *)buf+24,
140 psbuf->st_ex_ctime);
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));
148 /* DOS attributes */
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);
153 } else {
155 * All non-directory or regular files are reported
156 * as reparse points. Client may or may not be able
157 * to access these.
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).
169 smb2_posix_cc_info(
170 conn,
171 reparse_tag,
172 psbuf,
173 &owner,
174 &group,
175 buf + 68,
176 cc_len);
178 return cc_len + 68;