4 * Copyright (C) Shirish Pargaonkar (shirishp@us.ibm.com) 2011
6 * Used to display a security descriptor including ACL of a file object
7 * that belongs to a share mounted using option cifsacl.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #endif /* HAVE_CONFIG_H */
38 #include <sys/xattr.h>
41 static const char *prog;
44 print_each_ace_mask(uint32_t mask)
46 if ((mask & ALL_READ_BITS) && ((mask & EREAD) != EREAD &&
47 (mask & OREAD) != OREAD && (mask & BREAD) != BREAD)) {
52 if ((mask & ALL_WRITE_BITS) && (mask & EWRITE) != EWRITE) {
57 if ((mask & EREAD) == EREAD || (mask & OREAD) == OREAD ||
58 (mask & BREAD) == BREAD)
60 if ((mask & EWRITE) == EWRITE)
62 if ((mask & EXEC) == EXEC)
64 if ((mask & DELETE) == DELETE)
66 if ((mask & WRITE_DAC) == WRITE_DAC)
68 if ((mask & WRITE_OWNER) == WRITE_OWNER)
73 print_ace_mask(uint32_t mask, int raw)
76 printf("0x%x\n", mask);
80 if (mask == FULL_CONTROL)
82 else if (mask == CHANGE)
84 else if (mask == DELETE)
86 else if (mask == EREAD)
88 else if (mask & DELDHLD)
91 print_each_ace_mask(mask);
98 print_ace_flags(uint8_t flags, int raw)
103 printf("0x%x", flags);
107 if (flags & OBJECT_INHERIT_FLAG) {
114 if (flags & CONTAINER_INHERIT_FLAG) {
121 if (flags & NO_PROPAGATE_INHERIT_FLAG) {
128 if (flags & INHERIT_ONLY_FLAG) {
135 if (flags & INHERITED_ACE_FLAG) {
148 print_ace_type(uint8_t acetype, int raw)
151 printf("0x%x", acetype);
162 case ACCESS_ALLOWED_OBJECT:
163 printf("OBJECT_ALLOWED");
165 case ACCESS_DENIED_OBJECT:
166 printf("OBJECT_DENIED");
175 print_sid(struct wbcDomainSid *sidptr, int raw)
179 int num_auth = MAX_NUM_AUTHS;
181 char *domain_name = NULL;
182 char *sidname = NULL;
183 enum wbcSidType sntype;
188 rc = wbcLookupSid(sidptr, &domain_name, &sidname, &sntype);
190 printf("%s", domain_name);
191 if (strlen(domain_name))
193 printf("%s", sidname);
198 num_auths = sidptr->num_auths;
200 printf("-%d", sidptr->sid_rev_num);
201 for (i = 0; i < num_auth; ++i)
202 if (sidptr->id_auth[i])
203 printf("-%d", sidptr->id_auth[i]);
204 for (i = 0; i < num_auths; i++)
205 printf("-%u", le32toh(sidptr->sub_auths[i]));
209 print_ace(struct cifs_ace *pace, char *end_of_acl, int raw)
211 /* validate that we do not go past end of acl */
213 if (le16toh(pace->size) < 16)
216 if (end_of_acl < (char *)pace + le16toh(pace->size))
220 print_sid((struct wbcDomainSid *)&pace->sid, raw);
222 print_ace_type(pace->type, raw);
224 print_ace_flags(pace->flags, raw);
226 print_ace_mask(pace->access_req, raw);
233 parse_dacl(struct cifs_ctrl_acl *pdacl, char *end_of_acl, int raw)
239 struct cifs_ace *pace;
244 if (end_of_acl < (char *)pdacl + le16toh(pdacl->size))
247 acl_base = (char *)pdacl;
248 acl_size = sizeof(struct cifs_ctrl_acl);
250 num_aces = le32toh(pdacl->num_aces);
252 for (i = 0; i < num_aces; ++i) {
253 pace = (struct cifs_ace *) (acl_base + acl_size);
254 print_ace(pace, end_of_acl, raw);
255 acl_base = (char *)pace;
256 acl_size = le16toh(pace->size);
264 parse_sid(struct wbcDomainSid *psid, char *end_of_acl, char *title, int raw)
266 if (end_of_acl < (char *)psid + 8)
270 printf("%s:", title);
271 print_sid((struct wbcDomainSid *)psid, raw);
278 parse_sec_desc(struct cifs_ntsd *pntsd, ssize_t acl_len, int raw)
282 char *end_of_acl = ((char *)pntsd) + acl_len;
283 struct wbcDomainSid *owner_sid_ptr, *group_sid_ptr;
284 struct cifs_ctrl_acl *dacl_ptr; /* no need for SACL ptr */
289 owner_sid_ptr = (struct wbcDomainSid *)((char *)pntsd +
290 le32toh(pntsd->osidoffset));
291 group_sid_ptr = (struct wbcDomainSid *)((char *)pntsd +
292 le32toh(pntsd->gsidoffset));
293 dacloffset = le32toh(pntsd->dacloffset);
294 dacl_ptr = (struct cifs_ctrl_acl *)((char *)pntsd + dacloffset);
295 printf("REVISION:0x%x\n", pntsd->revision);
296 printf("CONTROL:0x%x\n", pntsd->type);
298 rc = parse_sid(owner_sid_ptr, end_of_acl, "OWNER", raw);
302 rc = parse_sid(group_sid_ptr, end_of_acl, "GROUP", raw);
307 parse_dacl(dacl_ptr, end_of_acl, raw);
309 printf("No ACL\n"); /* BB grant all or default perms? */
315 getcifsacl_usage(void)
318 "%s: Display CIFS/NTFS ACL in a security descriptor of a file object\n",
320 fprintf(stderr, "Usage: %s [option] <file_name>\n", prog);
321 fprintf(stderr, "Valid options:\n");
322 fprintf(stderr, "\t-v Version of the program\n");
323 fprintf(stderr, "\n");
324 fprintf(stderr, "\t-r Display raw values of the ACE fields\n");
325 fprintf(stderr, "\nRefer to getcifsacl(1) manpage for details\n");
329 main(const int argc, char *const argv[])
333 size_t bufsize = BUFSIZE;
334 char *filename, *attrval;
336 prog = basename(argv[0]);
337 openlog(prog, 0, LOG_DAEMON);
339 while ((c = getopt_long(argc, argv, "r:v", NULL, NULL)) != -1) {
342 printf("Version: %s\n", VERSION);
352 if (raw && argc == 3)
362 if (bufsize >= XATTR_SIZE_MAX) {
363 printf("buffer to allocate exceeds max size of %d\n",
368 attrval = malloc(bufsize * sizeof(char));
370 printf("error allocating memory for attribute value buffer\n");
374 attrlen = getxattr(filename, ATTRNAME, attrval, bufsize);
376 if (errno == ERANGE) {
381 printf("getxattr error: %d\n", errno);
384 parse_sec_desc((struct cifs_ntsd *)attrval, attrlen, raw);