diff options
author | Shirish Pargaonkar <shirishp@us.ibm.com> | 2007-10-03 14:22:19 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2007-10-03 14:22:19 -0400 |
commit | d0d66c443aefa51d5dbdd6a1d9b135a2a0e469cc (patch) | |
tree | e30ee8cac1bef527cbf9610a82c493e0002fd9c1 | |
parent | a8a11d399fc3c70f2aa645c7472235a06e8b8efa (diff) |
[CIFS] CIFS ACL support (part 2)
Signed-off-by: Shirish Pargaonkar <shirishp@us.ibm.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r-- | fs/cifs/cifsacl.c | 203 | ||||
-rw-r--r-- | fs/cifs/cifsacl.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 2 |
4 files changed, 151 insertions, 60 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 9b84f373af19..23bff0128e2a 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -24,48 +24,178 @@ | |||
24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
25 | #include "cifspdu.h" | 25 | #include "cifspdu.h" |
26 | #include "cifsglob.h" | 26 | #include "cifsglob.h" |
27 | #include "cifsacl.h" | ||
27 | #include "cifsproto.h" | 28 | #include "cifsproto.h" |
28 | #include "cifs_debug.h" | 29 | #include "cifs_debug.h" |
29 | #include "cifsacl.h" | ||
30 | 30 | ||
31 | /* security id for everyone */ | 31 | /* security id for everyone */ |
32 | static const struct cifs_sid sid_everyone = | 32 | static const struct cifs_sid sid_everyone = |
33 | {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; | 33 | {1, 1, {0, 0, 0, 0, 0, 0}, {}}; |
34 | /* group users */ | 34 | /* group users */ |
35 | static const struct cifs_sid sid_user = | 35 | static const struct cifs_sid sid_user = |
36 | {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}}; | 36 | {1, 2 , {0, 0, 0, 0, 0, 5}, {}}; |
37 | |||
38 | static void parse_ace(struct cifs_ace * pace, char * end_of_acl) | ||
39 | { | ||
40 | int i; | ||
41 | int num_subauth; | ||
42 | __u32 *psub_auth; | ||
43 | |||
44 | /* validate that we do not go past end of acl */ | ||
45 | if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) { | ||
46 | cERROR(1, ("ACL too small to parse ACE")); | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | num_subauth = cpu_to_le32(pace->num_subauth); | ||
51 | if (num_subauth) { | ||
52 | psub_auth = (__u32 *)((char *)pace + sizeof(struct cifs_ace)); | ||
53 | #ifdef CONFIG_CIFS_DEBUG2 | ||
54 | cFYI(1, ("ACE revision %d num_subauth %d", | ||
55 | pace->revision, pace->num_subauth)); | ||
56 | for (i = 0; i < num_subauth; ++i) { | ||
57 | cFYI(1, ("ACE sub_auth[%d]: 0x%x", i, | ||
58 | le32_to_cpu(psub_auth[i]))); | ||
59 | } | ||
60 | |||
61 | /* BB add length check to make sure that we do not have huge | ||
62 | num auths and therefore go off the end */ | ||
63 | |||
64 | cFYI(1, ("RID %d", le32_to_cpu(psub_auth[num_subauth-1]))); | ||
65 | #endif | ||
66 | } | ||
67 | |||
68 | return; | ||
69 | } | ||
70 | |||
71 | static void parse_ntace(struct cifs_ntace * pntace, char * end_of_acl) | ||
72 | { | ||
73 | /* validate that we do not go past end of acl */ | ||
74 | if (end_of_acl < (char *)pntace + sizeof(struct cifs_ntace)) { | ||
75 | cERROR(1, ("ACL too small to parse NT ACE")); | ||
76 | return; | ||
77 | } | ||
78 | |||
79 | #ifdef CONFIG_CIFS_DEBUG2 | ||
80 | cFYI(1, ("NTACE type %d flags 0x%x size %d, access Req 0x%x", | ||
81 | pntace->type, pntace->flags, pntace->size, | ||
82 | pntace->access_req)); | ||
83 | #endif | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | |||
88 | |||
89 | static void parse_dacl(struct cifs_acl * pdacl, char * end_of_acl) | ||
90 | { | ||
91 | int i; | ||
92 | int num_aces = 0; | ||
93 | int acl_size; | ||
94 | char *acl_base; | ||
95 | struct cifs_ntace **ppntace; | ||
96 | struct cifs_ace **ppace; | ||
97 | |||
98 | /* BB need to add parm so we can store the SID BB */ | ||
99 | |||
100 | /* validate that we do not go past end of acl */ | ||
101 | if (end_of_acl < (char *)pdacl + pdacl->size) { | ||
102 | cERROR(1, ("ACL too small to parse DACL")); | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | #ifdef CONFIG_CIFS_DEBUG2 | ||
107 | cFYI(1, ("DACL revision %d size %d num aces %d", | ||
108 | pdacl->revision, pdacl->size, pdacl->num_aces)); | ||
109 | #endif | ||
110 | |||
111 | acl_base = (char *)pdacl; | ||
112 | acl_size = sizeof(struct cifs_acl); | ||
113 | |||
114 | num_aces = cpu_to_le32(pdacl->num_aces); | ||
115 | if (num_aces > 0) { | ||
116 | ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *), | ||
117 | GFP_KERNEL); | ||
118 | ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), | ||
119 | GFP_KERNEL); | ||
120 | |||
121 | /* cifscred->cecount = pdacl->num_aces; | ||
122 | cifscred->ntaces = kmalloc(num_aces * | ||
123 | sizeof(struct cifs_ntace *), GFP_KERNEL); | ||
124 | cifscred->aces = kmalloc(num_aces * | ||
125 | sizeof(struct cifs_ace *), GFP_KERNEL);*/ | ||
126 | |||
127 | |||
128 | for (i = 0; i < num_aces; ++i) { | ||
129 | ppntace[i] = (struct cifs_ntace *) | ||
130 | (acl_base + acl_size); | ||
131 | ppace[i] = (struct cifs_ace *) ((char *)ppntace[i] + | ||
132 | sizeof(struct cifs_ntace)); | ||
133 | |||
134 | parse_ntace(ppntace[i], end_of_acl); | ||
135 | parse_ace(ppace[i], end_of_acl); | ||
136 | |||
137 | /* memcpy((void *)(&(cifscred->ntaces[i])), | ||
138 | (void *)ppntace[i], | ||
139 | sizeof(struct cifs_ntace)); | ||
140 | memcpy((void *)(&(cifscred->aces[i])), | ||
141 | (void *)ppace[i], | ||
142 | sizeof(struct cifs_ace)); */ | ||
143 | |||
144 | acl_base = (char *)ppntace[i]; | ||
145 | acl_size = cpu_to_le32(ppntace[i]->size); | ||
146 | } | ||
147 | |||
148 | kfree(ppace); | ||
149 | kfree(ppntace); | ||
150 | } | ||
151 | |||
152 | return; | ||
153 | } | ||
154 | |||
37 | 155 | ||
38 | static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | 156 | static int parse_sid(struct cifs_sid *psid, char *end_of_acl) |
39 | { | 157 | { |
158 | int i; | ||
159 | int num_subauth; | ||
160 | __u32 *psub_auth; | ||
161 | |||
40 | /* BB need to add parm so we can store the SID BB */ | 162 | /* BB need to add parm so we can store the SID BB */ |
41 | 163 | ||
42 | /* validate that we do not go past end of acl */ | 164 | /* validate that we do not go past end of acl */ |
43 | if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) { | 165 | if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) { |
44 | cERROR(1, ("ACL to small to parse SID")); | 166 | cERROR(1, ("ACL too small to parse SID")); |
45 | return -EINVAL; | 167 | return -EINVAL; |
46 | } | 168 | } |
169 | |||
170 | num_subauth = cpu_to_le32(psid->num_subauth); | ||
171 | if (num_subauth) { | ||
172 | psub_auth = (__u32 *)((char *)psid + sizeof(struct cifs_sid)); | ||
47 | #ifdef CONFIG_CIFS_DEBUG2 | 173 | #ifdef CONFIG_CIFS_DEBUG2 |
48 | cFYI(1, ("revision %d num_auth %d First subauth 0x%x", | 174 | cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x", |
49 | psid->revision, psid->num_subauth, psid->sub_auth[0])); | 175 | psid->revision, psid->num_subauth, psid->sub_auth[0])); |
50 | 176 | ||
51 | /* BB add length check to make sure that we do not have huge num auths | 177 | for (i = 0; i < num_subauth; ++i) { |
52 | and therefore go off the end */ | 178 | cFYI(1, ("SID sub_auth[%d]: 0x%x ", i, |
53 | cFYI(1, ("RID 0x%x", le32_to_cpu(psid->sub_auth[psid->num_subauth]))); | 179 | le32_to_cpu(psub_auth[i]))); |
180 | } | ||
181 | |||
182 | /* BB add length check to make sure that we do not have huge | ||
183 | num auths and therefore go off the end */ | ||
184 | cFYI(1, ("RID 0x%x", | ||
185 | le32_to_cpu(psid->sub_auth[psid->num_subauth]))); | ||
54 | #endif | 186 | #endif |
187 | } | ||
188 | |||
55 | return 0; | 189 | return 0; |
56 | } | 190 | } |
57 | 191 | ||
192 | |||
58 | /* Convert CIFS ACL to POSIX form */ | 193 | /* Convert CIFS ACL to POSIX form */ |
59 | int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) | 194 | int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) |
60 | { | 195 | { |
61 | int i, rc; | 196 | int rc; |
62 | int num_aces = 0; | ||
63 | int acl_size; | ||
64 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | 197 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
65 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ | 198 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ |
66 | struct cifs_ntace **ppntace; | ||
67 | struct cifs_ace **ppace; | ||
68 | char *acl_base; | ||
69 | char *end_of_acl = ((char *)pntsd) + acl_len; | 199 | char *end_of_acl = ((char *)pntsd) + acl_len; |
70 | 200 | ||
71 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + | 201 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + |
@@ -89,6 +219,8 @@ int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) | |||
89 | if (rc) | 219 | if (rc) |
90 | return rc; | 220 | return rc; |
91 | 221 | ||
222 | parse_dacl(dacl_ptr, end_of_acl); | ||
223 | |||
92 | /* cifscred->uid = owner_sid_ptr->rid; | 224 | /* cifscred->uid = owner_sid_ptr->rid; |
93 | cifscred->gid = group_sid_ptr->rid; | 225 | cifscred->gid = group_sid_ptr->rid; |
94 | memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr, | 226 | memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr, |
@@ -96,46 +228,5 @@ int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) | |||
96 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, | 228 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, |
97 | sizeof (struct cifs_sid)); */ | 229 | sizeof (struct cifs_sid)); */ |
98 | 230 | ||
99 | num_aces = cpu_to_le32(dacl_ptr->num_aces); | ||
100 | cFYI(1, ("num aces %d", num_aces)); | ||
101 | if (num_aces > 0) { | ||
102 | ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *), | ||
103 | GFP_KERNEL); | ||
104 | ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), | ||
105 | GFP_KERNEL); | ||
106 | |||
107 | /* cifscred->cecount = dacl_ptr->num_aces; | ||
108 | cifscred->ntaces = kmalloc(num_aces * | ||
109 | sizeof(struct cifs_ntace *), GFP_KERNEL); | ||
110 | cifscred->aces = kmalloc(num_aces * | ||
111 | sizeof(struct cifs_ace *), GFP_KERNEL);*/ | ||
112 | |||
113 | acl_base = (char *)dacl_ptr; | ||
114 | acl_size = sizeof(struct cifs_acl); | ||
115 | |||
116 | for (i = 0; i < num_aces; ++i) { | ||
117 | ppntace[i] = (struct cifs_ntace *) | ||
118 | (acl_base + acl_size); | ||
119 | ppace[i] = (struct cifs_ace *) | ||
120 | ((char *)ppntace[i] + | ||
121 | sizeof(struct cifs_ntace)); | ||
122 | |||
123 | /* memcpy((void *)(&(cifscred->ntaces[i])), | ||
124 | (void *)ntace_ptrptr[i], | ||
125 | sizeof(struct cifs_ntace)); | ||
126 | memcpy((void *)(&(cifscred->aces[i])), | ||
127 | (void *)ace_ptrptr[i], | ||
128 | sizeof(struct cifs_ace)); */ | ||
129 | |||
130 | acl_base = (char *)ppntace[i]; | ||
131 | acl_size = cpu_to_le32(ppntace[i]->size); | ||
132 | #ifdef CONFIG_CIFS_DEBUG2 | ||
133 | cFYI(1, ("ACE revision:%d", ppace[i]->revision)); | ||
134 | #endif | ||
135 | } | ||
136 | kfree(ppace); | ||
137 | kfree(ppntace); | ||
138 | } | ||
139 | |||
140 | return (0); | 231 | return (0); |
141 | } | 232 | } |
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index 5e7b56738cc5..bf297ea1905a 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h | |||
@@ -44,14 +44,14 @@ struct cifs_acl { | |||
44 | __u32 num_aces; | 44 | __u32 num_aces; |
45 | } __attribute__((packed)); | 45 | } __attribute__((packed)); |
46 | 46 | ||
47 | struct cifs_ntace { | 47 | struct cifs_ntace { /* first part of ACE which contains perms */ |
48 | __u8 type; | 48 | __u8 type; |
49 | __u8 flags; | 49 | __u8 flags; |
50 | __u16 size; | 50 | __u16 size; |
51 | __u32 access_req; | 51 | __u32 access_req; |
52 | } __attribute__((packed)); | 52 | } __attribute__((packed)); |
53 | 53 | ||
54 | struct cifs_ace { | 54 | struct cifs_ace { /* last part of ACE which includes user info */ |
55 | __u8 revision; /* revision level */ | 55 | __u8 revision; /* revision level */ |
56 | __u8 num_subauth; | 56 | __u8 num_subauth; |
57 | __u8 authority[6]; | 57 | __u8 authority[6]; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7dbb79b8dd50..001f0dc7e60d 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -310,7 +310,7 @@ extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, | |||
310 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 310 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
311 | extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key); | 311 | extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key); |
312 | #endif /* CIFS_WEAK_PW_HASH */ | 312 | #endif /* CIFS_WEAK_PW_HASH */ |
313 | extern int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len); | 313 | extern int parse_sec_desc(struct cifs_ntsd *, int); |
314 | extern int CIFSSMBCopy(int xid, | 314 | extern int CIFSSMBCopy(int xid, |
315 | struct cifsTconInfo *source_tcon, | 315 | struct cifsTconInfo *source_tcon, |
316 | const char *fromName, | 316 | const char *fromName, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a6ff324bc135..90b8f8d64d6e 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -34,10 +34,10 @@ | |||
34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
35 | #include "cifspdu.h" | 35 | #include "cifspdu.h" |
36 | #include "cifsglob.h" | 36 | #include "cifsglob.h" |
37 | #include "cifsacl.h" | ||
37 | #include "cifsproto.h" | 38 | #include "cifsproto.h" |
38 | #include "cifs_unicode.h" | 39 | #include "cifs_unicode.h" |
39 | #include "cifs_debug.h" | 40 | #include "cifs_debug.h" |
40 | #include "cifsacl.h" | ||
41 | 41 | ||
42 | #ifdef CONFIG_CIFS_POSIX | 42 | #ifdef CONFIG_CIFS_POSIX |
43 | static struct { | 43 | static struct { |