2 Unix SMB/CIFS implementation.
4 routines for marshalling/unmarshalling cab structures
6 Copyright (C) Guenther Deschner 2016
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "librpc/gen_ndr/ndr_cab.h"
25 _PUBLIC_ void ndr_print_cf_time(struct ndr_print *ndr, const char *name, const struct cf_time *r)
27 uint8_t hour = 0, minute = 0, seconds = 0;
29 if (r == NULL) { ndr_print_null(ndr); return; }
31 minute = (r->time >> 5) & 0x3f;
32 seconds = (r->time << 1) & 0x3e;
33 s = talloc_asprintf(ndr, "%02d:%02d:%02d", hour, minute, seconds);
34 if (s == NULL) { return; }
35 ndr_print_string(ndr, "time", s);
39 _PUBLIC_ void ndr_print_cf_date(struct ndr_print *ndr, const char *name, const struct cf_date *r)
42 uint8_t month = 0, day = 0;
44 if (r == NULL) { ndr_print_null(ndr); return; }
45 year = (r->date >> 9);
47 month = (r->date >> 5 & 0xf);
48 day = (r->date & 0x1f);
49 s = talloc_asprintf(ndr, "%02d/%02d/%04d", day, month, year);
50 if (s == NULL) { return; }
51 ndr_print_string(ndr, "date", s);
55 uint32_t ndr_count_cfdata(const struct cab_file *r)
57 uint32_t count = 0, i;
59 for (i = 0; i < r->cfheader.cFolders; i++) {
60 if (count + r->cffolders[i].cCFData < count) {
64 count += r->cffolders[i].cCFData;
70 static uint32_t ndr_cab_compute_checksum(uint8_t *data, uint32_t length, uint32_t seed)
77 num_ulong = length / 4;
81 while (num_ulong-- > 0) {
83 ul |= (((uint32_t)(*pb++)) << 8);
84 ul |= (((uint32_t)(*pb++)) << 16);
85 ul |= (((uint32_t)(*pb++)) << 24);
94 ul |= (((uint32_t)(*pb++)) << 16);
96 ul |= (((uint32_t)(*pb++)) << 8);
108 uint32_t ndr_cab_generate_checksum(const struct CFDATA *r)
110 uint32_t csumPartial;
112 csumPartial = ndr_cab_compute_checksum(&r->ab[0], r->cbData, 0);
114 return ndr_cab_compute_checksum((uint8_t *)discard_const(&r->cbData),
115 sizeof(r->cbData) + sizeof(r->cbUncomp),
119 static bool ndr_size_cab_file(const struct cab_file *r, uint32_t *psize)
128 for (i = 0; i < r->cfheader.cFolders; i++) {
129 if (size + 8 < size) {
137 for (i = 0; i < r->cfheader.cFiles; i++) {
138 uint32_t cfsize = ndr_size_CFFILE(&r->cffiles[i], 0);
139 if (size + cfsize < size) {
147 for (i = 0; i < ndr_count_cfdata(r); i++) {
148 if (size + 8 < size) {
153 if (size + r->cfdata[i].cbData < size) {
157 size += r->cfdata[i].cbData;
164 enum cf_compress_type ndr_cab_get_compression(const struct cab_file *r)
166 if (r->cfheader.cFolders == 0) {
167 return CF_COMPRESS_NONE;
170 return r->cffolders[0].typeCompress;
173 _PUBLIC_ enum ndr_err_code ndr_push_cab_file(struct ndr_push *ndr, int ndr_flags, const struct cab_file *r)
175 uint32_t cntr_cffolders_0;
176 uint32_t cntr_cffiles_0;
177 uint32_t cntr_cfdata_0;
178 uint32_t cab_size = 0;
180 uint32_t _flags_save_STRUCT = ndr->flags;
181 ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
182 NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
183 if (ndr_flags & NDR_SCALARS) {
184 uint32_t next_offset = 0;
185 NDR_CHECK(ndr_push_align(ndr, 4));
186 NDR_CHECK(ndr_push_CFHEADER(ndr, NDR_SCALARS, &r->cfheader));
187 for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (r->cfheader.cFolders); cntr_cffolders_0++) {
188 NDR_CHECK(ndr_push_CFFOLDER(ndr, NDR_SCALARS, &r->cffolders[cntr_cffolders_0]));
190 for (cntr_cffiles_0 = 0; cntr_cffiles_0 < (r->cfheader.cFiles); cntr_cffiles_0++) {
191 uint32_t offset = ndr->offset + 4;
192 NDR_CHECK(ndr_push_CFFILE(ndr, NDR_SCALARS, &r->cffiles[cntr_cffiles_0]));
193 if (cntr_cffiles_0 > 0) {
194 next_offset += r->cffiles[cntr_cffiles_0 - 1].cbFile;
196 SIVAL(ndr->data, offset, next_offset);
199 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_count_cfdata(r)));
201 for (cntr_cfdata_0 = 0; cntr_cfdata_0 < (ndr_count_cfdata(r)); cntr_cfdata_0++) {
202 NDR_CHECK(ndr_push_CFDATA(ndr, NDR_SCALARS, &r->cfdata[cntr_cfdata_0]));
204 NDR_CHECK(ndr_push_trailer_align(ndr, 4));
206 if (ndr_flags & NDR_BUFFERS) {
208 ndr->flags = _flags_save_STRUCT;
211 if (ndr_size_cab_file(r, &cab_size) == false) {
212 return NDR_ERR_VALIDATE;
214 SIVAL(ndr->data, 8, cab_size);
216 return NDR_ERR_SUCCESS;
219 _PUBLIC_ enum ndr_err_code ndr_pull_cab_file(struct ndr_pull *ndr, int ndr_flags, struct cab_file *r)
221 uint32_t size_cffolders_0 = 0;
222 uint32_t cntr_cffolders_0;
223 TALLOC_CTX *_mem_save_cffolders_0 = NULL;
224 uint32_t size_cffiles_0 = 0;
225 uint32_t cntr_cffiles_0;
226 TALLOC_CTX *_mem_save_cffiles_0 = NULL;
227 uint32_t size_cfdata_0 = 0;
228 uint32_t cntr_cfdata_0;
229 TALLOC_CTX *_mem_save_cfdata_0 = NULL;
231 uint32_t _flags_save_STRUCT = ndr->flags;
232 ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
233 NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
234 if (ndr_flags & NDR_SCALARS) {
235 NDR_CHECK(ndr_pull_align(ndr, 4));
236 NDR_CHECK(ndr_pull_CFHEADER(ndr, NDR_SCALARS, &r->cfheader));
237 size_cffolders_0 = r->cfheader.cFolders;
238 NDR_PULL_ALLOC_N(ndr, r->cffolders, size_cffolders_0);
239 _mem_save_cffolders_0 = NDR_PULL_GET_MEM_CTX(ndr);
240 NDR_PULL_SET_MEM_CTX(ndr, r->cffolders, 0);
241 for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (size_cffolders_0); cntr_cffolders_0++) {
242 NDR_CHECK(ndr_pull_CFFOLDER(ndr, NDR_SCALARS, &r->cffolders[cntr_cffolders_0]));
244 NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cffolders_0, 0);
245 size_cffiles_0 = r->cfheader.cFiles;
246 NDR_PULL_ALLOC_N(ndr, r->cffiles, size_cffiles_0);
247 _mem_save_cffiles_0 = NDR_PULL_GET_MEM_CTX(ndr);
248 NDR_PULL_SET_MEM_CTX(ndr, r->cffiles, 0);
249 for (cntr_cffiles_0 = 0; cntr_cffiles_0 < (size_cffiles_0); cntr_cffiles_0++) {
250 NDR_CHECK(ndr_pull_CFFILE(ndr, NDR_SCALARS, &r->cffiles[cntr_cffiles_0]));
252 NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cffiles_0, 0);
254 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->cfdata_count));
256 r->cfdata_count = ndr_count_cfdata(r);
258 size_cfdata_0 = r->cfdata_count;
259 NDR_PULL_ALLOC_N(ndr, r->cfdata, size_cfdata_0);
260 _mem_save_cfdata_0 = NDR_PULL_GET_MEM_CTX(ndr);
261 NDR_PULL_SET_MEM_CTX(ndr, r->cfdata, 0);
262 for (cntr_cfdata_0 = 0; cntr_cfdata_0 < (size_cfdata_0); cntr_cfdata_0++) {
263 NDR_CHECK(ndr_pull_CFDATA(ndr, NDR_SCALARS, &r->cfdata[cntr_cfdata_0]));
265 NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cfdata_0, 0);
266 NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
268 if (ndr_flags & NDR_BUFFERS) {
270 ndr->flags = _flags_save_STRUCT;
272 return NDR_ERR_SUCCESS;