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