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 */
37 #include <sys/xattr.h>
39 #include "idmap_plugin.h"
41 static void *plugin_handle;
42 static bool plugin_loaded;
45 print_each_ace_mask(uint32_t mask)
47 if ((mask & ALL_READ_BITS) && ((mask & EREAD) != EREAD &&
48 (mask & OREAD) != OREAD && (mask & BREAD) != BREAD)) {
53 if ((mask & ALL_WRITE_BITS) && (mask & EWRITE) != EWRITE) {
58 if ((mask & EREAD) == EREAD || (mask & OREAD) == OREAD ||
59 (mask & BREAD) == BREAD)
61 if ((mask & EWRITE) == EWRITE)
63 if ((mask & EXEC) == EXEC)
65 if ((mask & DELETE) == DELETE)
67 if ((mask & WRITE_DAC) == WRITE_DAC)
69 if ((mask & WRITE_OWNER) == WRITE_OWNER)
74 print_ace_mask(uint32_t mask, int raw)
77 printf("0x%x\n", mask);
81 if (mask == FULL_CONTROL)
83 else if (mask == CHANGE)
85 else if (mask == DELETE)
87 else if (mask == EREAD)
89 else if (mask & DELDHLD)
92 print_each_ace_mask(mask);
99 print_ace_flags(uint8_t flags, int raw)
104 printf("0x%x", flags);
108 if (flags & OBJECT_INHERIT_FLAG) {
112 if (flags & CONTAINER_INHERIT_FLAG) {
119 if (flags & NO_PROPAGATE_INHERIT_FLAG) {
126 if (flags & INHERIT_ONLY_FLAG) {
133 if (flags & INHERITED_ACE_FLAG) {
146 print_ace_type(uint8_t acetype, int raw)
149 printf("0x%x", acetype);
160 case ACCESS_ALLOWED_OBJECT:
161 printf("OBJECT_ALLOWED");
163 case ACCESS_DENIED_OBJECT:
164 printf("OBJECT_DENIED");
173 print_sid(struct cifs_sid *csid, int raw)
177 unsigned long long id_auth_val;
179 if (raw || !plugin_loaded)
182 rc = sid_to_str(plugin_handle, csid, &name);
191 printf("S-%hhu", csid->revision);
193 id_auth_val = (unsigned long long)csid->authority[5];
194 id_auth_val += (unsigned long long)csid->authority[4] << 8;
195 id_auth_val += (unsigned long long)csid->authority[3] << 16;
196 id_auth_val += (unsigned long long)csid->authority[2] << 24;
197 id_auth_val += (unsigned long long)csid->authority[1] << 32;
198 id_auth_val += (unsigned long long)csid->authority[0] << 40;
201 * MS-DTYP states that if the authority is >= 2^32, then it should be
202 * expressed as a hex value.
204 if (id_auth_val <= UINT_MAX)
205 printf("-%llu", id_auth_val);
207 printf("-0x%llx", id_auth_val);
209 for (i = 0; i < csid->num_subauth; i++)
210 printf("-%u", le32toh(csid->sub_auth[i]));
214 print_ace(struct cifs_ace *pace, char *end_of_acl, int raw)
218 /* make sure we can safely get to "size" */
219 if (end_of_acl < (char *)pace + offsetof(struct cifs_ace, size) + 1)
222 size = le16toh(pace->size);
224 /* 16 == size of cifs_ace when cifs_sid has no subauths */
228 /* validate that we do not go past end of acl */
229 if (end_of_acl < (char *)pace + size)
233 print_sid((struct cifs_sid *)&pace->sid, raw);
235 print_ace_type(pace->type, raw);
237 print_ace_flags(pace->flags, raw);
239 print_ace_mask(le32toh(pace->access_req), raw);
245 parse_dacl(struct cifs_ctrl_acl *pdacl, char *end_of_acl, int raw)
251 struct cifs_ace *pace;
256 if (end_of_acl < (char *)pdacl + le16toh(pdacl->size))
259 acl_base = (char *)pdacl;
260 acl_size = sizeof(struct cifs_ctrl_acl);
262 num_aces = le32toh(pdacl->num_aces);
264 for (i = 0; i < num_aces; ++i) {
265 pace = (struct cifs_ace *) (acl_base + acl_size);
266 print_ace(pace, end_of_acl, raw);
267 acl_base = (char *)pace;
268 acl_size = le16toh(pace->size);
276 parse_sid(struct cifs_sid *psid, char *end_of_acl, char *title, int raw)
278 if (end_of_acl < (char *)psid + 8)
282 printf("%s:", title);
283 print_sid((struct cifs_sid *)psid, raw);
290 parse_sec_desc(struct cifs_ntsd *pntsd, ssize_t acl_len, int raw)
294 char *end_of_acl = ((char *)pntsd) + acl_len;
295 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
296 struct cifs_ctrl_acl *dacl_ptr; /* no need for SACL ptr */
301 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
302 le32toh(pntsd->osidoffset));
303 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
304 le32toh(pntsd->gsidoffset));
305 dacloffset = le32toh(pntsd->dacloffset);
306 dacl_ptr = (struct cifs_ctrl_acl *)((char *)pntsd + dacloffset);
307 printf("REVISION:0x%x\n", le16toh(pntsd->revision));
308 printf("CONTROL:0x%x\n", le16toh(pntsd->type));
310 rc = parse_sid(owner_sid_ptr, end_of_acl, "OWNER", raw);
314 rc = parse_sid(group_sid_ptr, end_of_acl, "GROUP", raw);
319 parse_dacl(dacl_ptr, end_of_acl, raw);
321 printf("No ACL\n"); /* BB grant all or default perms? */
327 getcifsacl_usage(const char *prog)
330 "%s: Display CIFS/NTFS ACL in a security descriptor of a file object\n",
332 fprintf(stderr, "Usage: %s [option] <file_name>\n", prog);
333 fprintf(stderr, "Valid options:\n");
334 fprintf(stderr, "\t-v Version of the program\n");
335 fprintf(stderr, "\n");
336 fprintf(stderr, "\t-r Display raw values of the ACE fields\n");
337 fprintf(stderr, "\nRefer to getcifsacl(1) manpage for details\n");
341 main(const int argc, char *const argv[])
346 size_t bufsize = BUFSIZE;
347 char *filename, *attrval;
349 while ((c = getopt_long(argc, argv, "r:v", NULL, NULL)) != -1) {
352 printf("Version: %s\n", VERSION);
362 if (raw && argc == 3)
367 getcifsacl_usage(basename(argv[0]));
371 if (!raw && !plugin_loaded) {
372 ret = init_plugin(&plugin_handle);
374 printf("WARNING: unable to initialize idmapping plugin: %s\n",
377 plugin_loaded = true;
381 if (bufsize >= XATTR_SIZE_MAX) {
382 printf("buffer to allocate exceeds max size of %d\n",
388 attrval = malloc(bufsize * sizeof(char));
390 printf("error allocating memory for attribute value buffer\n");
395 attrlen = getxattr(filename, ATTRNAME, attrval, bufsize);
397 if (errno == ERANGE) {
402 printf("getxattr error: %d\n", errno);
405 parse_sec_desc((struct cifs_ntsd *)attrval, attrlen, raw);
410 exit_plugin(plugin_handle);