4 * Copyright (C) International Business Machines Corp., 2007
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for mapping CIFS/NTFS ACLs
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "cifsproto.h"
29 #include "cifs_debug.h"
32 #ifdef CONFIG_CIFS_EXPERIMENTAL
34 static struct cifs_wksid wksidarr
[NUM_WK_SIDS
] = {
35 {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
36 {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
37 {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
38 {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
39 {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(544), 0, 0, 0} }, "root"},
40 {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(545), 0, 0, 0} }, "users"},
41 {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"}
45 /* security id for everyone */
46 static const struct cifs_sid sid_everyone
=
47 {1, 1, {0, 0, 0, 0, 0, 0}, {} };
49 static const struct cifs_sid sid_user
=
50 {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
53 int match_sid(struct cifs_sid
*ctsid
)
56 int num_subauth
, num_sat
, num_saw
;
57 struct cifs_sid
*cwsid
;
62 for (i
= 0; i
< NUM_WK_SIDS
; ++i
) {
63 cwsid
= &(wksidarr
[i
].cifssid
);
65 /* compare the revision */
66 if (ctsid
->revision
!= cwsid
->revision
)
69 /* compare all of the six auth values */
70 for (j
= 0; j
< 6; ++j
) {
71 if (ctsid
->authority
[j
] != cwsid
->authority
[j
])
75 continue; /* all of the auth values did not match */
77 /* compare all of the subauth values if any */
78 num_sat
= ctsid
->num_subauth
;
79 num_saw
= cwsid
->num_subauth
;
80 num_subauth
= num_sat
< num_saw
? num_sat
: num_saw
;
82 for (j
= 0; j
< num_subauth
; ++j
) {
83 if (ctsid
->sub_auth
[j
] != cwsid
->sub_auth
[j
])
87 continue; /* all sub_auth values do not match */
90 cFYI(1, ("matching sid: %s\n", wksidarr
[i
].sidname
));
91 return (0); /* sids compare/match */
94 cFYI(1, ("No matching sid"));
99 int compare_sids(struct cifs_sid
*ctsid
, struct cifs_sid
*cwsid
)
102 int num_subauth
, num_sat
, num_saw
;
104 if ((!ctsid
) || (!cwsid
))
107 /* compare the revision */
108 if (ctsid
->revision
!= cwsid
->revision
)
111 /* compare all of the six auth values */
112 for (i
= 0; i
< 6; ++i
) {
113 if (ctsid
->authority
[i
] != cwsid
->authority
[i
])
117 /* compare all of the subauth values if any */
118 num_sat
= cpu_to_le32(ctsid
->num_subauth
);
119 num_saw
= cpu_to_le32(cwsid
->num_subauth
);
120 num_subauth
= num_sat
< num_saw
? num_sat
: num_saw
;
122 for (i
= 0; i
< num_subauth
; ++i
) {
123 if (ctsid
->sub_auth
[i
] != cwsid
->sub_auth
[i
])
128 return (0); /* sids compare/match */
132 static void parse_ace(struct cifs_ace
*pace
, char *end_of_acl
)
136 /* validate that we do not go past end of acl */
138 /* XXX this if statement can be removed
139 if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) {
140 cERROR(1, ("ACL too small to parse ACE"));
144 num_subauth
= pace
->num_subauth
;
146 #ifdef CONFIG_CIFS_DEBUG2
148 cFYI(1, ("ACE revision %d num_subauth %d",
149 pace
->revision
, pace
->num_subauth
));
150 for (i
= 0; i
< num_subauth
; ++i
) {
151 cFYI(1, ("ACE sub_auth[%d]: 0x%x", i
,
152 le32_to_cpu(pace
->sub_auth
[i
])));
155 /* BB add length check to make sure that we do not have huge
156 num auths and therefore go off the end */
158 cFYI(1, ("RID %d", le32_to_cpu(pace
->sub_auth
[num_subauth
-1])));
165 static void parse_ntace(struct cifs_ntace
*pntace
, char *end_of_acl
)
167 /* validate that we do not go past end of acl */
168 if (end_of_acl
< (char *)pntace
+ sizeof(struct cifs_ntace
)) {
169 cERROR(1, ("ACL too small to parse NT ACE"));
173 #ifdef CONFIG_CIFS_DEBUG2
174 cFYI(1, ("NTACE type %d flags 0x%x size %d, access Req 0x%x",
175 pntace
->type
, pntace
->flags
, pntace
->size
,
176 pntace
->access_req
));
183 static void parse_dacl(struct cifs_acl
*pdacl
, char *end_of_acl
)
189 struct cifs_ntace
**ppntace
;
190 struct cifs_ace
**ppace
;
192 /* BB need to add parm so we can store the SID BB */
194 /* validate that we do not go past end of acl */
195 if (end_of_acl
< (char *)pdacl
+ le16_to_cpu(pdacl
->size
)) {
196 cERROR(1, ("ACL too small to parse DACL"));
200 #ifdef CONFIG_CIFS_DEBUG2
201 cFYI(1, ("DACL revision %d size %d num aces %d",
202 le16_to_cpu(pdacl
->revision
), le16_to_cpu(pdacl
->size
),
203 le32_to_cpu(pdacl
->num_aces
)));
206 acl_base
= (char *)pdacl
;
207 acl_size
= sizeof(struct cifs_acl
);
209 num_aces
= cpu_to_le32(pdacl
->num_aces
);
211 ppntace
= kmalloc(num_aces
* sizeof(struct cifs_ntace
*),
213 ppace
= kmalloc(num_aces
* sizeof(struct cifs_ace
*),
216 /* cifscred->cecount = pdacl->num_aces;
217 cifscred->ntaces = kmalloc(num_aces *
218 sizeof(struct cifs_ntace *), GFP_KERNEL);
219 cifscred->aces = kmalloc(num_aces *
220 sizeof(struct cifs_ace *), GFP_KERNEL);*/
223 for (i
= 0; i
< num_aces
; ++i
) {
224 ppntace
[i
] = (struct cifs_ntace
*)
225 (acl_base
+ acl_size
);
226 ppace
[i
] = (struct cifs_ace
*) ((char *)ppntace
[i
] +
227 sizeof(struct cifs_ntace
));
229 parse_ntace(ppntace
[i
], end_of_acl
);
230 if (end_of_acl
< ((char *)ppace
[i
] +
231 (le16_to_cpu(ppntace
[i
]->size
) -
232 sizeof(struct cifs_ntace
)))) {
233 cERROR(1, ("ACL too small to parse ACE"));
236 parse_ace(ppace
[i
], end_of_acl
);
238 /* memcpy((void *)(&(cifscred->ntaces[i])),
240 sizeof(struct cifs_ntace));
241 memcpy((void *)(&(cifscred->aces[i])),
243 sizeof(struct cifs_ace)); */
245 acl_base
= (char *)ppntace
[i
];
246 acl_size
= le16_to_cpu(ppntace
[i
]->size
);
257 static int parse_sid(struct cifs_sid
*psid
, char *end_of_acl
)
260 /* BB need to add parm so we can store the SID BB */
262 /* validate that we do not go past end of acl */
263 if (end_of_acl
< (char *)psid
+ sizeof(struct cifs_sid
)) {
264 cERROR(1, ("ACL too small to parse SID"));
268 if (psid
->num_subauth
) {
269 #ifdef CONFIG_CIFS_DEBUG2
271 cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x",
272 psid
->revision
, psid
->num_subauth
, psid
->sub_auth
[0]));
274 for (i
= 0; i
< psid
->num_subauth
; i
++) {
275 cFYI(1, ("SID sub_auth[%d]: 0x%x ", i
,
276 le32_to_cpu(psid
->sub_auth
[i
])));
279 /* BB add length check to make sure that we do not have huge
280 num auths and therefore go off the end */
282 le32_to_cpu(psid
->sub_auth
[psid
->num_subauth
-1])));
290 /* Convert CIFS ACL to POSIX form */
291 int parse_sec_desc(struct cifs_ntsd
*pntsd
, int acl_len
)
294 struct cifs_sid
*owner_sid_ptr
, *group_sid_ptr
;
295 struct cifs_acl
*dacl_ptr
; /* no need for SACL ptr */
296 char *end_of_acl
= ((char *)pntsd
) + acl_len
;
298 owner_sid_ptr
= (struct cifs_sid
*)((char *)pntsd
+
299 le32_to_cpu(pntsd
->osidoffset
));
300 group_sid_ptr
= (struct cifs_sid
*)((char *)pntsd
+
301 le32_to_cpu(pntsd
->gsidoffset
));
302 dacl_ptr
= (struct cifs_acl
*)((char *)pntsd
+
303 le32_to_cpu(pntsd
->dacloffset
));
304 #ifdef CONFIG_CIFS_DEBUG2
305 cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x "
306 "sacloffset 0x%x dacloffset 0x%x",
307 pntsd
->revision
, pntsd
->type
, le32_to_cpu(pntsd
->osidoffset
),
308 le32_to_cpu(pntsd
->gsidoffset
),
309 le32_to_cpu(pntsd
->sacloffset
),
310 le32_to_cpu(pntsd
->dacloffset
)));
312 rc
= parse_sid(owner_sid_ptr
, end_of_acl
);
316 rc
= parse_sid(group_sid_ptr
, end_of_acl
);
320 parse_dacl(dacl_ptr
, end_of_acl
);
322 /* cifscred->uid = owner_sid_ptr->rid;
323 cifscred->gid = group_sid_ptr->rid;
324 memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
325 sizeof (struct cifs_sid));
326 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
327 sizeof (struct cifs_sid)); */
332 #endif /* CONFIG_CIFS_EXPERIMENTAL */