forked from namjaejeon/ksmbd
-
Notifications
You must be signed in to change notification settings - Fork 23
/
smbacl.h
307 lines (275 loc) · 8.64 KB
/
smbacl.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Copyright (c) International Business Machines Corp., 2007
* Author(s): Steve French ([email protected])
* Modified by Namjae Jeon ([email protected])
*/
#ifndef _SMBACL_H
#define _SMBACL_H
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/posix_acl.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
#include <linux/mnt_idmapping.h>
#endif
#include "mgmt/tree_connect.h"
#define NUM_AUTHS (6) /* number of authority fields */
#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
/*
* ACE types - see MS-DTYP 2.4.4.1
*/
enum {
ACCESS_ALLOWED,
ACCESS_DENIED,
};
/*
* Security ID types
*/
enum {
SIDOWNER = 1,
SIDGROUP,
SIDCREATOR_OWNER,
SIDCREATOR_GROUP,
SIDUNIX_USER,
SIDUNIX_GROUP,
SIDNFS_USER,
SIDNFS_GROUP,
SIDNFS_MODE,
};
/* Revision for ACLs */
#define SD_REVISION 1
/* Control flags for Security Descriptor */
#define OWNER_DEFAULTED 0x0001
#define GROUP_DEFAULTED 0x0002
#define DACL_PRESENT 0x0004
#define DACL_DEFAULTED 0x0008
#define SACL_PRESENT 0x0010
#define SACL_DEFAULTED 0x0020
#define DACL_TRUSTED 0x0040
#define SERVER_SECURITY 0x0080
#define DACL_AUTO_INHERIT_REQ 0x0100
#define SACL_AUTO_INHERIT_REQ 0x0200
#define DACL_AUTO_INHERITED 0x0400
#define SACL_AUTO_INHERITED 0x0800
#define DACL_PROTECTED 0x1000
#define SACL_PROTECTED 0x2000
#define RM_CONTROL_VALID 0x4000
#define SELF_RELATIVE 0x8000
/* ACE types - see MS-DTYP 2.4.4.1 */
#define ACCESS_ALLOWED_ACE_TYPE 0x00
#define ACCESS_DENIED_ACE_TYPE 0x01
#define SYSTEM_AUDIT_ACE_TYPE 0x02
#define SYSTEM_ALARM_ACE_TYPE 0x03
#define ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04
#define ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05
#define ACCESS_DENIED_OBJECT_ACE_TYPE 0x06
#define SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07
#define SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08
#define ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09
#define ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A
#define ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B
#define ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE 0x0C
#define SYSTEM_AUDIT_CALLBACK_ACE_TYPE 0x0D
#define SYSTEM_ALARM_CALLBACK_ACE_TYPE 0x0E /* Reserved */
#define SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F
#define SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 /* reserved */
#define SYSTEM_MANDATORY_LABEL_ACE_TYPE 0x11
#define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE 0x12
#define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 0x13
/* ACE flags */
#define OBJECT_INHERIT_ACE 0x01
#define CONTAINER_INHERIT_ACE 0x02
#define NO_PROPAGATE_INHERIT_ACE 0x04
#define INHERIT_ONLY_ACE 0x08
#define INHERITED_ACE 0x10
#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40
#define FAILED_ACCESS_ACE_FLAG 0x80
/*
* Maximum size of a string representation of a SID:
*
* The fields are unsigned values in decimal. So:
*
* u8: max 3 bytes in decimal
* u32: max 10 bytes in decimal
*
* "S-" + 3 bytes for version field + 15 for authority field + NULL terminator
*
* For authority field, max is when all 6 values are non-zero and it must be
* represented in hex. So "-0x" + 12 hex digits.
*
* Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
*/
#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
#define DOMAIN_USER_RID_LE cpu_to_le32(513)
struct ksmbd_conn;
struct smb_ntsd {
__le16 revision; /* revision level */
__le16 type;
__le32 osidoffset;
__le32 gsidoffset;
__le32 sacloffset;
__le32 dacloffset;
} __packed;
struct smb_sid {
__u8 revision; /* revision level */
__u8 num_subauth;
__u8 authority[NUM_AUTHS];
__le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
} __packed;
/* size of a struct cifs_sid, sans sub_auth array */
#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
struct smb_acl {
__le16 revision; /* revision level */
__le16 size;
__le32 num_aces;
} __packed;
struct smb_ace {
__u8 type;
__u8 flags;
__le16 size;
__le32 access_req;
struct smb_sid sid; /* ie UUID of user or group who gets these perms */
} __packed;
struct smb_fattr {
kuid_t cf_uid;
kgid_t cf_gid;
umode_t cf_mode;
__le32 daccess;
struct posix_acl *cf_acls;
struct posix_acl *cf_dacls;
};
struct posix_ace_state {
u32 allow;
u32 deny;
};
struct posix_user_ace_state {
union {
kuid_t uid;
kgid_t gid;
};
struct posix_ace_state perms;
};
struct posix_ace_state_array {
int n;
struct posix_user_ace_state aces[];
};
/*
* while processing the nfsv4 ace, this maintains the partial permissions
* calculated so far:
*/
struct posix_acl_state {
struct posix_ace_state owner;
struct posix_ace_state group;
struct posix_ace_state other;
struct posix_ace_state everyone;
struct posix_ace_state mask; /* deny unused in this case */
struct posix_ace_state_array *users;
struct posix_ace_state_array *groups;
};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
#else
int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
#endif
int acl_len, struct smb_fattr *fattr);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
int build_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
#else
int build_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
#endif
struct smb_ntsd *ppntsd, int ppntsd_size, int addition_info,
__u32 *secdesclen, struct smb_fattr *fattr);
int init_acl_state(struct posix_acl_state *state, int cnt);
void free_acl_state(struct posix_acl_state *state);
void posix_state_to_acl(struct posix_acl_state *state,
struct posix_acl_entry *pace);
int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid);
bool smb_inherit_flags(int flags, bool is_dir);
int smb_inherit_dacl(struct ksmbd_conn *conn, const struct path *path,
unsigned int uid, unsigned int gid);
int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
__le32 *pdaccess, int uid);
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
bool type_check, bool get_write);
void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid);
void ksmbd_init_domain(u32 *sub_auth);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
static inline uid_t posix_acl_uid_translate(struct mnt_idmap *idmap,
#else
static inline uid_t posix_acl_uid_translate(struct user_namespace *mnt_userns,
#endif
struct posix_acl_entry *pace)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
vfsuid_t vfsuid;
#else
kuid_t kuid;
#endif
/* If this is an idmapped mount, apply the idmapping. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 52) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
vfsuid = make_vfsuid(idmap, &init_user_ns, pace->e_uid);
#else
vfsuid = make_vfsuid(mnt_userns, &init_user_ns, pace->e_uid);
#endif
#else
kuid = mapped_kuid_fs(mnt_userns, &init_user_ns, pace->e_uid);
#endif
#else
kuid = kuid_into_mnt(mnt_userns, pace->e_uid);
#endif
/* Translate the kuid into a userspace id ksmbd would see. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
return from_kuid(&init_user_ns, vfsuid_into_kuid(vfsuid));
#else
return from_kuid(&init_user_ns, kuid);
#endif
#else
return from_kuid(&init_user_ns, pace->e_uid);
#endif
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
static inline gid_t posix_acl_gid_translate(struct mnt_idmap *idmap,
#else
static inline gid_t posix_acl_gid_translate(struct user_namespace *mnt_userns,
#endif
struct posix_acl_entry *pace)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
vfsgid_t vfsgid;
#else
kgid_t kgid;
#endif
/* If this is an idmapped mount, apply the idmapping. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 52) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
vfsgid = make_vfsgid(idmap, &init_user_ns, pace->e_gid);
#else
vfsgid = make_vfsgid(mnt_userns, &init_user_ns, pace->e_gid);
#endif
#else
kgid = mapped_kgid_fs(mnt_userns, &init_user_ns, pace->e_gid);
#endif
#else
kgid = kgid_into_mnt(mnt_userns, pace->e_gid);
#endif
/* Translate the kgid into a userspace id ksmbd would see. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
return from_kgid(&init_user_ns, vfsgid_into_kgid(vfsgid));
#else
return from_kgid(&init_user_ns, kgid);
#endif
#else
return from_kgid(&init_user_ns, pace->e_gid);
#endif
}
#endif /* _SMBACL_H */