struct security_descriptor *get_xattr_sd( int fd ) { struct security_descriptor *sd; char buffer[XATTR_SIZE_MAX]; int n; n = xattr_fget( fd, WINE_XATTR_SD, buffer, sizeof(buffer) ); if (n == -1 || n < 2 + sizeof(struct security_descriptor)) return NULL; /* validate that we can handle the descriptor */ if (buffer[0] != SECURITY_DESCRIPTOR_REVISION || buffer[1] != 0 || !sd_is_valid( (struct security_descriptor *)&buffer[2], n - 2 )) return NULL; sd = mem_alloc( n - 2 ); if (sd) memcpy( sd, &buffer[2], n - 2 ); return sd; }
/* return object attributes from the current request */ const struct object_attributes *get_req_object_attributes( const struct security_descriptor **sd, struct unicode_str *name, struct object **root ) { static const struct object_attributes empty_attributes; const struct object_attributes *attr = get_req_data(); data_size_t size = get_req_data_size(); if (root) *root = NULL; if (!size) { *sd = NULL; name->len = 0; return &empty_attributes; } if ((size < sizeof(*attr)) || (size - sizeof(*attr) < attr->sd_len) || (size - sizeof(*attr) - attr->sd_len < attr->name_len)) { set_error( STATUS_ACCESS_VIOLATION ); return NULL; } if (attr->sd_len && !sd_is_valid( (const struct security_descriptor *)(attr + 1), attr->sd_len )) { set_error( STATUS_INVALID_SECURITY_DESCR ); return NULL; } if ((attr->name_len & (sizeof(WCHAR) - 1)) || attr->name_len >= 65534) { set_error( STATUS_OBJECT_NAME_INVALID ); return NULL; } if (root && attr->rootdir && attr->name_len) { if (!(*root = get_directory_obj( current->process, attr->rootdir ))) return NULL; } *sd = attr->sd_len ? (const struct security_descriptor *)(attr + 1) : NULL; name->len = attr->name_len; name->str = (const WCHAR *)(attr + 1) + attr->sd_len / sizeof(WCHAR); return attr; }
struct security_descriptor *get_xattr_acls( int fd, const SID *user, const SID *group ) { int dacl_size = sizeof(ACL), n; int offset, type, flags, mask, rev, ia, sa; char buffer[XATTR_SIZE_MAX + 1], *p, *ptr; struct security_descriptor *sd; ACL *dacl; n = xattr_fget( fd, XATTR_USER_PREFIX "wine.acl", buffer, sizeof(buffer) - 1 ); if (n == -1) return NULL; buffer[n] = 0; /* ensure NULL terminated buffer for string functions */ p = buffer; do { int sub_authority_count = 0; if (sscanf(p, "%x,%x,%x,S-%u-%d%n", &type, &flags, &mask, &rev, &ia, &offset) != 5) return NULL; p += offset; while (sscanf(p, "-%u%n", &sa, &offset) == 1) { p += offset; sub_authority_count++; } if (*p == ';') p++; else if (*p) return NULL; /* verify that the SubAuthorityCount does not exceed the maximum permitted value */ if (sub_authority_count > SID_MAX_SUB_AUTHORITIES) continue; switch (type) { case ACCESS_DENIED_ACE_TYPE: dacl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority[sub_authority_count]); break; case ACCESS_ALLOWED_ACE_TYPE: dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority[sub_authority_count]); break; default: continue; } } while (*p); n = sizeof(struct security_descriptor) + FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) + FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]) + dacl_size; sd = mem_alloc( n ); if (!sd) return NULL; sd->control = SE_DACL_PRESENT; sd->owner_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]); sd->group_len = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]); sd->sacl_len = 0; sd->dacl_len = dacl_size; ptr = (char *)(sd + 1); memcpy( ptr, user, sd->owner_len ); ptr += sd->owner_len; memcpy( ptr, group, sd->group_len ); ptr += sd->group_len; dacl = (ACL *)ptr; dacl->AclRevision = ACL_REVISION; dacl->Sbz1 = 0; dacl->AclSize = dacl_size; dacl->AceCount = 0; dacl->Sbz2 = 0; ptr = (char *)(dacl + 1); p = buffer; do { char sid_buffer[sizeof(SID) + sizeof(ULONG) * SID_MAX_SUB_AUTHORITIES]; SID *sid = (SID *)sid_buffer; int sub_authority_count = 0; if (sscanf(p, "%x,%x,%x,S-%u-%d%n", &type, &flags, &mask, &rev, &ia, &offset) != 5) goto err; p += offset; while (sscanf(p, "-%u%n", &sa, &offset) == 1) { p += offset; if (sub_authority_count < SID_MAX_SUB_AUTHORITIES) sid->SubAuthority[sub_authority_count] = sa; sub_authority_count++; } if (*p == ';') p++; else if (*p) goto err; if (sub_authority_count > SID_MAX_SUB_AUTHORITIES) continue; sid->Revision = rev; sid->IdentifierAuthority.Value[0] = 0; sid->IdentifierAuthority.Value[1] = 0; sid->IdentifierAuthority.Value[2] = HIBYTE(HIWORD(ia)); sid->IdentifierAuthority.Value[3] = LOBYTE(HIWORD(ia)); sid->IdentifierAuthority.Value[4] = HIBYTE(LOWORD(ia)); sid->IdentifierAuthority.Value[5] = LOBYTE(LOWORD(ia)); sid->SubAuthorityCount = sub_authority_count; /* Handle the specific ACE */ switch (type) { case ACCESS_DENIED_ACE_TYPE: { ACCESS_DENIED_ACE *ada = (ACCESS_DENIED_ACE *)ptr; ada->Header.AceType = type; ada->Header.AceFlags = flags; ada->Header.AceSize = FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]); ada->Mask = mask; memcpy( &ada->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) ); } break; case ACCESS_ALLOWED_ACE_TYPE: { ACCESS_ALLOWED_ACE *aaa = (ACCESS_ALLOWED_ACE *)ptr; aaa->Header.AceType = type; aaa->Header.AceFlags = flags; aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]); aaa->Mask = mask; memcpy( &aaa->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) ); } break; default: continue; } ptr = (char *)ace_next( (ACE_HEADER *)ptr ); dacl->AceCount++; } while (*p); if (sd_is_valid( sd, n )) return sd; err: free( sd ); return NULL; }