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
;