summaryrefslogtreecommitdiff
path: root/getcifsacl.c
diff options
context:
space:
mode:
Diffstat (limited to 'getcifsacl.c')
-rw-r--r--getcifsacl.c217
1 files changed, 157 insertions, 60 deletions
diff --git a/getcifsacl.c b/getcifsacl.c
index 89851f6..1c01062 100644
--- a/getcifsacl.c
+++ b/getcifsacl.c
@@ -47,6 +47,11 @@ static bool raw = false;
static void
print_each_ace_mask(uint32_t mask)
{
+ if ((mask & ALL_ACCESS_BITS) == ALL_ACCESS_BITS) {
+ printf("RWXDPO");
+ return;
+ }
+
if ((mask & ALL_READ_BITS) && ((mask & EREAD) != EREAD &&
(mask & OREAD) != OREAD && (mask & BREAD) != BREAD)) {
printf("0x%x", mask);
@@ -74,32 +79,48 @@ print_each_ace_mask(uint32_t mask)
}
static void
-print_ace_mask(uint32_t mask, int raw)
+print_ace_mask(uint32_t mask, int raw, ace_kinds ace_kind)
{
if (raw) {
printf("0x%x\n", mask);
return;
}
- if (mask == FULL_CONTROL)
- printf("FULL");
- else if (mask == CHANGE)
- printf("CHANGE");
- else if (mask == DELETE)
- printf("D");
- else if (mask == EREAD)
- printf("READ");
- else if (mask & DELDHLD)
- printf("0x%x", mask);
- else
- print_each_ace_mask(mask);
-
+ switch (ace_kind) {
+ case ACE_KIND_SACL:
+ if (mask == FULL_CONTROL)
+ printf("FULL");
+ else if (mask == CHANGE)
+ printf("CHANGE");
+ else if (mask == DELETE)
+ printf("D");
+ else if (mask == EREAD)
+ printf("READ");
+ else
+ print_each_ace_mask(mask);
+ break;
+ case ACE_KIND_DACL:
+ default:
+ if (mask == FULL_CONTROL)
+ printf("FULL");
+ else if (mask == CHANGE)
+ printf("CHANGE");
+ else if (mask == DELETE)
+ printf("D");
+ else if (mask == EREAD)
+ printf("READ");
+ else if (mask & DELDHLD)
+ printf("0x%x", mask);
+ else
+ print_each_ace_mask(mask);
+ break;
+ }
printf("\n");
return;
}
static void
-print_ace_flags(uint8_t flags, int raw)
+print_ace_flags(uint8_t flags, int raw, ace_kinds ace_kind)
{
bool mflags = false;
@@ -108,37 +129,54 @@ print_ace_flags(uint8_t flags, int raw)
return;
}
- if (flags & OBJECT_INHERIT_FLAG) {
- mflags = true;
- printf("OI");
- }
- if (flags & CONTAINER_INHERIT_FLAG) {
- if (mflags)
- printf("|");
- else
- mflags = true;
- printf("CI");
- }
- if (flags & NO_PROPAGATE_INHERIT_FLAG) {
- if (mflags)
- printf("|");
- else
+ switch (ace_kind) {
+ case ACE_KIND_SACL:
+ if (flags & SUCCESSFUL_ACCESS) {
mflags = true;
- printf("NP");
- }
- if (flags & INHERIT_ONLY_FLAG) {
- if (mflags)
- printf("|");
- else
- mflags = true;
- printf("IO");
- }
- if (flags & INHERITED_ACE_FLAG) {
- if (mflags)
- printf("|");
- else
+ printf("SA");
+ }
+ if (flags & FAILED_ACCESS) {
+ if (mflags)
+ printf("|");
+ else
+ mflags = true;
+ printf("FA");
+ }
+ break;
+ case ACE_KIND_DACL:
+ if (flags & OBJECT_INHERIT_FLAG) {
mflags = true;
- printf("I");
+ printf("OI");
+ }
+ if (flags & CONTAINER_INHERIT_FLAG) {
+ if (mflags)
+ printf("|");
+ else
+ mflags = true;
+ printf("CI");
+ }
+ if (flags & NO_PROPAGATE_INHERIT_FLAG) {
+ if (mflags)
+ printf("|");
+ else
+ mflags = true;
+ printf("NP");
+ }
+ if (flags & INHERIT_ONLY_FLAG) {
+ if (mflags)
+ printf("|");
+ else
+ mflags = true;
+ printf("IO");
+ }
+ if (flags & INHERITED_ACE_FLAG) {
+ if (mflags)
+ printf("|");
+ else
+ mflags = true;
+ printf("I");
+ }
+ break;
}
if (!mflags)
@@ -166,6 +204,27 @@ print_ace_type(uint8_t acetype, int raw)
case ACCESS_DENIED_OBJECT:
printf("OBJECT_DENIED");
break;
+ case SYSTEM_AUDIT:
+ printf("AUDIT");
+ break;
+ case SYSTEM_AUDIT_OBJECT:
+ printf("AUDIT_OBJECT");
+ break;
+ case SYSTEM_AUDIT_CALLBACK:
+ printf("AUDIT_CALLBACK");
+ break;
+ case SYSTEM_AUDIT_CALLBACK_OBJECT:
+ printf("AUDIT_CALLBACK_OBJECT");
+ break;
+ case SYSTEM_MANDATORY_LABEL:
+ printf("MANDATORY_LABEL");
+ break;
+ case SYSTEM_RESOURCE_ATTRIBUTE:
+ printf("RESOURCE_ATTRIBUTE");
+ break;
+ case SYSTEM_SCOPED_POLICY_ID:
+ printf("SCOPED_POLICY_ID");
+ break;
default:
printf("UNKNOWN");
break;
@@ -214,7 +273,7 @@ print_sid_raw:
}
static void
-print_ace(struct cifs_ace *pace, char *end_of_acl, int raw)
+print_ace(struct cifs_ace *pace, char *end_of_acl, int raw, ace_kinds ace_kind)
{
uint16_t size;
@@ -237,15 +296,15 @@ print_ace(struct cifs_ace *pace, char *end_of_acl, int raw)
printf(":");
print_ace_type(pace->type, raw);
printf("/");
- print_ace_flags(pace->flags, raw);
+ print_ace_flags(pace->flags, raw, ace_kind);
printf("/");
- print_ace_mask(le32toh(pace->access_req), raw);
+ print_ace_mask(le32toh(pace->access_req), raw, ace_kind);
return;
}
static void
-parse_dacl(struct cifs_ctrl_acl *pdacl, char *end_of_acl, int raw)
+ parse_acl(struct cifs_ctrl_acl *pacl, char *end_of_acl, int raw, ace_kinds ace_kind)
{
int i;
int num_aces = 0;
@@ -253,20 +312,20 @@ parse_dacl(struct cifs_ctrl_acl *pdacl, char *end_of_acl, int raw)
char *acl_base;
struct cifs_ace *pace;
- if (!pdacl)
+ if (!pacl)
return;
- if (end_of_acl < (char *)pdacl + le16toh(pdacl->size))
+ if (end_of_acl < (char *)pacl + le16toh(pacl->size))
return;
- acl_base = (char *)pdacl;
+ acl_base = (char *)pacl;
acl_size = sizeof(struct cifs_ctrl_acl);
- num_aces = le32toh(pdacl->num_aces);
+ num_aces = le32toh(pacl->num_aces);
if (num_aces > 0) {
for (i = 0; i < num_aces; ++i) {
pace = (struct cifs_ace *) (acl_base + acl_size);
- print_ace(pace, end_of_acl, raw);
+ print_ace(pace, end_of_acl, raw, ace_kind);
acl_base = (char *)pace;
acl_size = le16toh(pace->size);
}
@@ -293,10 +352,10 @@ static int
parse_sec_desc(struct cifs_ntsd *pntsd, ssize_t acl_len, int raw)
{
int rc;
- uint32_t dacloffset;
+ uint32_t dacloffset, sacloffset;
char *end_of_acl = ((char *)pntsd) + acl_len;
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
- struct cifs_ctrl_acl *dacl_ptr; /* no need for SACL ptr */
+ struct cifs_ctrl_acl *dacl_ptr, *sacl_ptr;
if (pntsd == NULL)
return -EIO;
@@ -307,6 +366,9 @@ parse_sec_desc(struct cifs_ntsd *pntsd, ssize_t acl_len, int raw)
le32toh(pntsd->gsidoffset));
dacloffset = le32toh(pntsd->dacloffset);
dacl_ptr = (struct cifs_ctrl_acl *)((char *)pntsd + dacloffset);
+ sacloffset = le32toh(pntsd->sacloffset);
+ sacl_ptr = (struct cifs_ctrl_acl *)((char *)pntsd + sacloffset);
+
printf("REVISION:0x%x\n", le16toh(pntsd->revision));
printf("CONTROL:0x%x\n", le16toh(pntsd->type));
@@ -318,10 +380,19 @@ parse_sec_desc(struct cifs_ntsd *pntsd, ssize_t acl_len, int raw)
if (rc)
return rc;
- if (dacloffset)
- parse_dacl(dacl_ptr, end_of_acl, raw);
- else
- printf("No ACL\n"); /* BB grant all or default perms? */
+ if (dacloffset) {
+ printf("DACL:\n");
+ parse_acl(dacl_ptr, end_of_acl, raw, ACE_KIND_DACL);
+ } else {
+ printf("No DACL\n"); /* BB grant all or default perms? */
+ }
+
+ if (sacloffset) {
+ printf("SACL:\n");
+ parse_acl(sacl_ptr, end_of_acl, raw, ACE_KIND_SACL);
+ } else {
+ printf("No SACL\n");
+ }
return 0;
}
@@ -351,6 +422,9 @@ getcifsacl(const char *filename)
size_t bufsize = BUFSIZE;
char *attrval;
int rc = 0;
+ /* use attribute name to fetch the whole descriptor */
+ char *attrname = ATTRNAME_NTSD_FULL;
+
cifsacl:
if (bufsize >= XATTR_SIZE_MAX) {
fprintf(stderr, "buffer to allocate exceeds max size of %d\n",
@@ -364,12 +438,35 @@ cifsacl:
exit(1);
}
- attrlen = getxattr(filename, ATTRNAME, attrval, bufsize);
+getxattr:
+ attrlen = getxattr(filename, attrname, attrval, bufsize);
if (attrlen == -1) {
if (errno == ERANGE) {
free(attrval);
bufsize += BUFSIZE;
goto cifsacl;
+ } else if (errno == EIO && !(strcmp(attrname, ATTRNAME_NTSD_FULL))) {
+ /*
+ * attempt to fetch SACL in addition to owner and DACL via
+ * ATTRNAME_NTSD_FULL, fall back to owner/DACL via
+ * ATTRNAME_ACL if not allowed
+ * CIFS client maps STATUS_PRIVILEGE_NOT_HELD to EIO
+ */
+ fprintf(stderr, "WARNING: Insufficient priviledges to fetch SACL for %s\n",
+ filename);
+ fprintf(stderr, " Fetching owner info and DACL only\n");
+ attrname = ATTRNAME_ACL;
+ goto getxattr;
+ } else if (errno == EOPNOTSUPP && !(strcmp(attrname, ATTRNAME_NTSD_FULL))) {
+ /*
+ * no support for fetching SACL, fall back to owner/DACL via
+ * ATTRNAME_ACL
+ */
+ fprintf(stderr, "WARNING: CIFS client does not support fetching SACL for %s\n",
+ filename);
+ fprintf(stderr, " Fetching owner info and DACL only\n");
+ attrname = ATTRNAME_ACL;
+ goto getxattr;
} else {
fprintf(stderr, "Failed to getxattr %s: %s\n", filename,
strerror(errno));