diff options
author | Ralph Boehme <slow@samba.org> | 2017-10-10 16:06:33 +0200 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2017-10-25 08:43:05 +0200 |
commit | 266a416d59b76864164ffd605a93cd03a37dd92a (patch) | |
tree | dfa49e74c61bf73112ba5d34284db508d9d45212 /source3/modules | |
parent | 0a620332b49fe74d47bb1bee16fb99fc6cf0eddf (diff) | |
download | samba-266a416d59b76864164ffd605a93cd03a37dd92a.tar.gz |
vfs_fruit: unpack AppleDouble xattr header if present
Bug: https://bugzilla.samba.org/show_bug.cgi?id=13076
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit fb137d6070c8cd872a66a4628b0e392cf40c180e)
Diffstat (limited to 'source3/modules')
-rw-r--r-- | source3/modules/vfs_fruit.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 3dcaa60d033..d6ecefb5e13 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -652,6 +652,141 @@ static bool ad_pack(struct adouble *ad) return true; } +static bool ad_unpack_xattrs(struct adouble *ad) +{ + struct ad_xattr_header *h = &ad->adx_header; + const char *p = ad->ad_data; + uint32_t hoff; + uint32_t i; + + if (ad_getentrylen(ad, ADEID_FINDERI) <= ADEDLEN_FINDERI) { + return true; + } + + /* 2 bytes padding */ + hoff = ad_getentryoff(ad, ADEID_FINDERI) + ADEDLEN_FINDERI + 2; + + h->adx_magic = RIVAL(p, hoff + 0); + h->adx_debug_tag = RIVAL(p, hoff + 4); /* Not used -> not checked */ + h->adx_total_size = RIVAL(p, hoff + 8); + h->adx_data_start = RIVAL(p, hoff + 12); + h->adx_data_length = RIVAL(p, hoff + 16); + h->adx_flags = RSVAL(p, hoff + 32); /* Not used -> not checked */ + h->adx_num_attrs = RSVAL(p, hoff + 34); + + if (h->adx_magic != AD_XATTR_HDR_MAGIC) { + DBG_ERR("Bad magic: 0x%" PRIx32 "\n", h->adx_magic); + return false; + } + + if (h->adx_total_size > ad_getentryoff(ad, ADEID_RFORK)) { + DBG_ERR("Bad total size: 0x%" PRIx32 "\n", h->adx_total_size); + return false; + } + if (h->adx_total_size > AD_XATTR_MAX_HDR_SIZE) { + DBG_ERR("Bad total size: 0x%" PRIx32 "\n", h->adx_total_size); + return false; + } + + if (h->adx_data_start < (hoff + AD_XATTR_HDR_SIZE)) { + DBG_ERR("Bad start: 0x%" PRIx32 "\n", h->adx_data_start); + return false; + } + + if ((h->adx_data_start + h->adx_data_length) < h->adx_data_start) { + DBG_ERR("Bad length: %" PRIu32 "\n", h->adx_data_length); + return false; + } + if ((h->adx_data_start + h->adx_data_length) > + ad->adx_header.adx_total_size) + { + DBG_ERR("Bad length: %" PRIu32 "\n", h->adx_data_length); + return false; + } + + if (h->adx_num_attrs > AD_XATTR_MAX_ENTRIES) { + DBG_ERR("Bad num xattrs: %" PRIu16 "\n", h->adx_num_attrs); + return false; + } + + if (h->adx_num_attrs == 0) { + return true; + } + + ad->adx_entries = talloc_zero_array( + ad, struct ad_xattr_entry, h->adx_num_attrs); + if (ad->adx_entries == NULL) { + return false; + } + + hoff += AD_XATTR_HDR_SIZE; + + for (i = 0; i < h->adx_num_attrs; i++) { + struct ad_xattr_entry *e = &ad->adx_entries[i]; + + hoff = (hoff + 3) & ~3; + + e->adx_offset = RIVAL(p, hoff + 0); + e->adx_length = RIVAL(p, hoff + 4); + e->adx_flags = RSVAL(p, hoff + 8); + e->adx_namelen = *(p + hoff + 10); + + if (e->adx_offset >= ad->adx_header.adx_total_size) { + DBG_ERR("Bad adx_offset: %" PRIx32 "\n", + e->adx_offset); + return false; + } + + if ((e->adx_offset + e->adx_length) < e->adx_offset) { + DBG_ERR("Bad adx_length: %" PRIx32 "\n", + e->adx_length); + return false; + } + + if ((e->adx_offset + e->adx_length) > + ad->adx_header.adx_total_size) + { + DBG_ERR("Bad adx_length: %" PRIx32 "\n", + e->adx_length); + return false; + } + + if (e->adx_namelen == 0) { + DBG_ERR("Bad adx_namelen: %" PRIx32 "\n", + e->adx_namelen); + return false; + } + if ((hoff + 11 + e->adx_namelen) < hoff + 11) { + DBG_ERR("Bad adx_namelen: %" PRIx32 "\n", + e->adx_namelen); + return false; + } + if ((hoff + 11 + e->adx_namelen) > + ad->adx_header.adx_data_start) + { + DBG_ERR("Bad adx_namelen: %" PRIx32 "\n", + e->adx_namelen); + return false; + } + + e->adx_name = talloc_strndup(ad->adx_entries, + p + hoff + 11, + e->adx_namelen); + if (e->adx_name == NULL) { + return false; + } + + DBG_DEBUG("xattr [%s] offset [0x%x] size [0x%x]\n", + e->adx_name, e->adx_offset, e->adx_length); + dump_data(10, (uint8_t *)(ad->ad_data + e->adx_offset), + e->adx_length); + + hoff += 11 + e->adx_namelen; + } + + return true; +} + /** * Unpack an AppleDouble blob into a struct adoble **/ @@ -661,6 +796,7 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries, size_t bufsize = talloc_get_size(ad->ad_data); size_t adentries, i; uint32_t eid, len, off; + bool ok; /* * The size of the buffer ad->ad_data is checked when read, so @@ -774,6 +910,11 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries, ad->ad_eid[eid].ade_len = len; } + ok = ad_unpack_xattrs(ad); + if (!ok) { + return false; + } + return true; } |