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"));
98 /* if the two SIDs (roughly equivalent to a UUID for a user or group) are
99 the same returns 1, if they do not match returns 0 */
100 int compare_sids(struct cifs_sid
*ctsid
, struct cifs_sid
*cwsid
)
103 int num_subauth
, num_sat
, num_saw
;
105 if ((!ctsid
) || (!cwsid
))
108 /* compare the revision */
109 if (ctsid
->revision
!= cwsid
->revision
)
112 /* compare all of the six auth values */
113 for (i
= 0; i
< 6; ++i
) {
114 if (ctsid
->authority
[i
] != cwsid
->authority
[i
])
118 /* compare all of the subauth values if any */
119 num_sat
= ctsid
->num_subauth
;
120 num_saw
= cwsid
->num_subauth
;
121 num_subauth
= num_sat
< num_saw
? num_sat
: num_saw
;
123 for (i
= 0; i
< num_subauth
; ++i
) {
124 if (ctsid
->sub_auth
[i
] != cwsid
->sub_auth
[i
])
129 return (1); /* sids compare/match */
133 static void parse_ace(struct cifs_ace
*pace
, char *end_of_acl
)
137 /* validate that we do not go past end of acl */
139 /* XXX this if statement can be removed
140 if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) {
141 cERROR(1, ("ACL too small to parse ACE"));
145 num_subauth
= pace
->num_subauth
;
147 #ifdef CONFIG_CIFS_DEBUG2
149 cFYI(1, ("ACE revision %d num_subauth %d",
150 pace
->revision
, pace
->num_subauth
));
151 for (i
= 0; i
< num_subauth
; ++i
) {
152 cFYI(1, ("ACE sub_auth[%d]: 0x%x", i
,
153 le32_to_cpu(pace
->sub_auth
[i
])));
156 /* BB add length check to make sure that we do not have huge
157 num auths and therefore go off the end */
159 cFYI(1, ("RID %d", le32_to_cpu(pace
->sub_auth
[num_subauth
-1])));
166 static void parse_ntace(struct cifs_ntace
*pntace
, char *end_of_acl
)
168 /* validate that we do not go past end of acl */
169 if (end_of_acl
< (char *)pntace
+ sizeof(struct cifs_ntace
)) {
170 cERROR(1, ("ACL too small to parse NT ACE"));
174 #ifdef CONFIG_CIFS_DEBUG2
175 cFYI(1, ("NTACE type %d flags 0x%x size %d, access Req 0x%x",
176 pntace
->type
, pntace
->flags
, pntace
->size
,
177 pntace
->access_req
));
184 static void parse_dacl(struct cifs_acl
*pdacl
, char *end_of_acl
,
185 struct cifs_sid
*pownersid
, struct cifs_sid
*pgrpsid
)
191 struct cifs_ntace
**ppntace
;
192 struct cifs_ace
**ppace
;
194 /* BB need to add parm so we can store the SID BB */
196 /* validate that we do not go past end of acl */
197 if (end_of_acl
< (char *)pdacl
+ le16_to_cpu(pdacl
->size
)) {
198 cERROR(1, ("ACL too small to parse DACL"));
202 #ifdef CONFIG_CIFS_DEBUG2
203 cFYI(1, ("DACL revision %d size %d num aces %d",
204 le16_to_cpu(pdacl
->revision
), le16_to_cpu(pdacl
->size
),
205 le32_to_cpu(pdacl
->num_aces
)));
208 acl_base
= (char *)pdacl
;
209 acl_size
= sizeof(struct cifs_acl
);
211 num_aces
= le32_to_cpu(pdacl
->num_aces
);
213 ppntace
= kmalloc(num_aces
* sizeof(struct cifs_ntace
*),
215 ppace
= kmalloc(num_aces
* sizeof(struct cifs_ace
*),
218 /* cifscred->cecount = pdacl->num_aces;
219 cifscred->ntaces = kmalloc(num_aces *
220 sizeof(struct cifs_ntace *), GFP_KERNEL);
221 cifscred->aces = kmalloc(num_aces *
222 sizeof(struct cifs_ace *), GFP_KERNEL);*/
224 for (i
= 0; i
< num_aces
; ++i
) {
225 ppntace
[i
] = (struct cifs_ntace
*)
226 (acl_base
+ acl_size
);
227 ppace
[i
] = (struct cifs_ace
*) ((char *)ppntace
[i
] +
228 sizeof(struct cifs_ntace
));
230 parse_ntace(ppntace
[i
], end_of_acl
);
231 if (end_of_acl
< ((char *)ppace
[i
] +
232 (le16_to_cpu(ppntace
[i
]->size
) -
233 sizeof(struct cifs_ntace
)))) {
234 cERROR(1, ("ACL too small to parse ACE"));
237 parse_ace(ppace
[i
], end_of_acl
);
239 /* memcpy((void *)(&(cifscred->ntaces[i])),
241 sizeof(struct cifs_ntace));
242 memcpy((void *)(&(cifscred->aces[i])),
244 sizeof(struct cifs_ace)); */
246 acl_base
= (char *)ppntace
[i
];
247 acl_size
= le16_to_cpu(ppntace
[i
]->size
);
258 static int parse_sid(struct cifs_sid
*psid
, char *end_of_acl
)
261 /* BB need to add parm so we can store the SID BB */
263 /* validate that we do not go past end of acl */
264 if (end_of_acl
< (char *)psid
+ sizeof(struct cifs_sid
)) {
265 cERROR(1, ("ACL too small to parse SID"));
269 if (psid
->num_subauth
) {
270 #ifdef CONFIG_CIFS_DEBUG2
272 cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x",
273 psid
->revision
, psid
->num_subauth
, psid
->sub_auth
[0]));
275 for (i
= 0; i
< psid
->num_subauth
; i
++) {
276 cFYI(1, ("SID sub_auth[%d]: 0x%x ", i
,
277 le32_to_cpu(psid
->sub_auth
[i
])));
280 /* BB add length check to make sure that we do not have huge
281 num auths and therefore go off the end */
283 le32_to_cpu(psid
->sub_auth
[psid
->num_subauth
-1])));
291 /* Convert CIFS ACL to POSIX form */
292 int parse_sec_desc(struct cifs_ntsd
*pntsd
, int acl_len
)
295 struct cifs_sid
*owner_sid_ptr
, *group_sid_ptr
;
296 struct cifs_acl
*dacl_ptr
; /* no need for SACL ptr */
297 char *end_of_acl
= ((char *)pntsd
) + acl_len
;
299 owner_sid_ptr
= (struct cifs_sid
*)((char *)pntsd
+
300 le32_to_cpu(pntsd
->osidoffset
));
301 group_sid_ptr
= (struct cifs_sid
*)((char *)pntsd
+
302 le32_to_cpu(pntsd
->gsidoffset
));
303 dacl_ptr
= (struct cifs_acl
*)((char *)pntsd
+
304 le32_to_cpu(pntsd
->dacloffset
));
305 #ifdef CONFIG_CIFS_DEBUG2
306 cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x "
307 "sacloffset 0x%x dacloffset 0x%x",
308 pntsd
->revision
, pntsd
->type
, le32_to_cpu(pntsd
->osidoffset
),
309 le32_to_cpu(pntsd
->gsidoffset
),
310 le32_to_cpu(pntsd
->sacloffset
),
311 le32_to_cpu(pntsd
->dacloffset
)));
313 rc
= parse_sid(owner_sid_ptr
, end_of_acl
);
317 rc
= parse_sid(group_sid_ptr
, end_of_acl
);
321 parse_dacl(dacl_ptr
, end_of_acl
, owner_sid_ptr
, group_sid_ptr
);
323 /* cifscred->uid = owner_sid_ptr->rid;
324 cifscred->gid = group_sid_ptr->rid;
325 memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
326 sizeof (struct cifs_sid));
327 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
328 sizeof (struct cifs_sid)); */
333 #endif /* CONFIG_CIFS_EXPERIMENTAL */