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 4271 : struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
29 : {
30 4271 : struct ea_list *eal = talloc_zero(ctx, struct ea_list);
31 : uint16_t val_len;
32 : unsigned int namelen;
33 : size_t converted_size;
34 :
35 4271 : if (!eal) {
36 0 : return NULL;
37 : }
38 :
39 4271 : if (data_size < 6) {
40 8 : return NULL;
41 : }
42 :
43 4263 : eal->ea.flags = CVAL(pdata,0);
44 4263 : namelen = CVAL(pdata,1);
45 4263 : val_len = SVAL(pdata,2);
46 :
47 4263 : if (4 + namelen + 1 + val_len > data_size) {
48 0 : return NULL;
49 : }
50 :
51 : /* Ensure the name is null terminated. */
52 4263 : if (pdata[namelen + 4] != '\0') {
53 0 : return NULL;
54 : }
55 4263 : 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",
57 : strerror(errno)));
58 : }
59 4263 : if (!eal->ea.name) {
60 0 : return NULL;
61 : }
62 :
63 4263 : eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
64 4263 : if (!eal->ea.value.data) {
65 0 : return NULL;
66 : }
67 :
68 4836 : 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 4263 : eal->ea.value.data[val_len] = '\0';
72 : /* But don't count the null. */
73 4263 : eal->ea.value.length--;
74 :
75 4263 : if (pbytes_used) {
76 3786 : *pbytes_used = 4 + namelen + 1 + val_len;
77 : }
78 :
79 4263 : DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
80 4263 : dump_data(10, eal->ea.value.data, eal->ea.value.length);
81 :
82 4263 : 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 236 : struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
90 : {
91 236 : struct ea_list *ea_list_head = NULL;
92 236 : size_t offset = 0;
93 :
94 236 : if (data_size < 4) {
95 0 : return NULL;
96 : }
97 :
98 700 : while (offset + 4 <= data_size) {
99 477 : size_t next_offset = IVAL(pdata,offset);
100 477 : struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL);
101 :
102 477 : if (!eal) {
103 0 : return NULL;
104 : }
105 :
106 477 : DLIST_ADD_END(ea_list_head, eal);
107 477 : if (next_offset == 0) {
108 233 : break;
109 : }
110 :
111 : /* Integer wrap protection for the increment. */
112 241 : if (offset + next_offset < offset) {
113 0 : break;
114 : }
115 :
116 241 : offset += next_offset;
117 :
118 : /* Integer wrap protection for while loop. */
119 241 : if (offset + 4 < offset) {
120 0 : break;
121 : }
122 :
123 : }
124 :
125 233 : return ea_list_head;
126 : }
|