Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : SMB Extended attribute buffer handling 4 : Copyright (C) Jeremy Allison 2005-2013 5 : Copyright (C) Tim Prouty 2008 6 : 7 : This program is free software; you can redistribute it and/or modify 8 : it under the terms of the GNU General Public License as published by 9 : the Free Software Foundation; either version 3 of the License, or 10 : (at your option) any later version. 11 : 12 : This program is distributed in the hope that it will be useful, 13 : but WITHOUT ANY WARRANTY; without even the implied warranty of 14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 : GNU General Public License for more details. 16 : 17 : You should have received a copy of the GNU General Public License 18 : along with this program. If not, see <http://www.gnu.org/licenses/>. 19 : */ 20 : 21 : #include "includes.h" 22 : #include "lib/util_ea.h" 23 : 24 : /**************************************************************************** 25 : Read one EA list entry from the buffer. 26 : ****************************************************************************/ 27 : 28 4275 : struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used) 29 : { 30 4275 : struct ea_list *eal = talloc_zero(ctx, struct ea_list); 31 573 : uint16_t val_len; 32 573 : unsigned int namelen; 33 573 : size_t converted_size; 34 : 35 4275 : if (!eal) { 36 0 : return NULL; 37 : } 38 : 39 4275 : if (data_size < 6) { 40 8 : return NULL; 41 : } 42 : 43 4267 : eal->ea.flags = CVAL(pdata,0); 44 4267 : namelen = CVAL(pdata,1); 45 4267 : val_len = SVAL(pdata,2); 46 : 47 4267 : if (4 + namelen + 1 + val_len > data_size) { 48 0 : return NULL; 49 : } 50 : 51 : /* Ensure the name is null terminated. */ 52 4267 : if (pdata[namelen + 4] != '\0') { 53 0 : return NULL; 54 : } 55 4267 : if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) { 56 0 : DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s\n", 57 : strerror(errno))); 58 : } 59 4267 : if (!eal->ea.name) { 60 0 : return NULL; 61 : } 62 : 63 4267 : eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1); 64 4267 : if (!eal->ea.value.data) { 65 0 : return NULL; 66 : } 67 : 68 4267 : memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len); 69 : 70 : /* Ensure we're null terminated just in case we print the value. */ 71 4267 : eal->ea.value.data[val_len] = '\0'; 72 : /* But don't count the null. */ 73 4267 : eal->ea.value.length--; 74 : 75 4267 : if (pbytes_used) { 76 3770 : *pbytes_used = 4 + namelen + 1 + val_len; 77 : } 78 : 79 4267 : DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name)); 80 4267 : dump_data(10, eal->ea.value.data, eal->ea.value.length); 81 : 82 4267 : return eal; 83 : } 84 : 85 : /**************************************************************************** 86 : Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. 87 : ****************************************************************************/ 88 : 89 252 : struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) 90 : { 91 252 : struct ea_list *ea_list_head = NULL; 92 252 : size_t offset = 0; 93 : 94 252 : if (data_size < 4) { 95 0 : return NULL; 96 : } 97 : 98 497 : while (offset + 4 <= data_size) { 99 497 : size_t next_offset = IVAL(pdata,offset); 100 497 : struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL); 101 : 102 497 : if (!eal) { 103 0 : return NULL; 104 : } 105 : 106 497 : DLIST_ADD_END(ea_list_head, eal); 107 497 : if (next_offset == 0) { 108 249 : break; 109 : } 110 : 111 : /* Integer wrap protection for the increment. */ 112 245 : if (offset + next_offset < offset) { 113 0 : break; 114 : } 115 : 116 245 : offset += next_offset; 117 : 118 : /* Integer wrap protection for while loop. */ 119 245 : if (offset + 4 < offset) { 120 0 : break; 121 : } 122 : 123 : } 124 : 125 249 : return ea_list_head; 126 : }