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) {
82 ul
= (uint32_t)(*pb
++);
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);
98 ul
|= (uint32_t)(*pb
++);
108 uint32_t ndr_cab_generate_checksum(const struct CFDATA
*r
)
110 uint32_t csumPartial
;
112 csumPartial
= ndr_cab_compute_checksum(&r
->ab
.data
[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 _PUBLIC_
enum ndr_err_code
ndr_push_cab_file(struct ndr_push
*ndr
, int ndr_flags
, const struct cab_file
*r
)
166 uint32_t cntr_cffolders_0
;
167 uint32_t cntr_cffiles_0
;
168 uint32_t cntr_cfdata_0
;
169 uint32_t cab_size
= 0;
171 uint32_t _flags_save_STRUCT
= ndr
->flags
;
172 ndr_set_flags(&ndr
->flags
, LIBNDR_PRINT_ARRAY_HEX
|LIBNDR_FLAG_LITTLE_ENDIAN
|LIBNDR_FLAG_NOALIGN
);
173 NDR_PUSH_CHECK_FLAGS(ndr
, ndr_flags
);
174 if (ndr_flags
& NDR_SCALARS
) {
175 uint32_t next_offset
= 0;
176 NDR_CHECK(ndr_push_align(ndr
, 4));
177 NDR_CHECK(ndr_push_CFHEADER(ndr
, NDR_SCALARS
, &r
->cfheader
));
178 for (cntr_cffolders_0
= 0; cntr_cffolders_0
< (r
->cfheader
.cFolders
); cntr_cffolders_0
++) {
179 NDR_CHECK(ndr_push_CFFOLDER(ndr
, NDR_SCALARS
, &r
->cffolders
[cntr_cffolders_0
]));
181 for (cntr_cffiles_0
= 0; cntr_cffiles_0
< (r
->cfheader
.cFiles
); cntr_cffiles_0
++) {
182 uint32_t offset
= ndr
->offset
+ 4;
183 NDR_CHECK(ndr_push_CFFILE(ndr
, NDR_SCALARS
, &r
->cffiles
[cntr_cffiles_0
]));
184 if (cntr_cffiles_0
> 0) {
185 next_offset
+= r
->cffiles
[cntr_cffiles_0
- 1].cbFile
;
187 SIVAL(ndr
->data
, offset
, next_offset
);
190 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, ndr_count_cfdata(r
)));
192 for (cntr_cfdata_0
= 0; cntr_cfdata_0
< (ndr_count_cfdata(r
)); cntr_cfdata_0
++) {
193 NDR_CHECK(ndr_push_CFDATA(ndr
, NDR_SCALARS
, &r
->cfdata
[cntr_cfdata_0
]));
195 NDR_CHECK(ndr_push_trailer_align(ndr
, 4));
197 if (ndr_flags
& NDR_BUFFERS
) {
199 ndr
->flags
= _flags_save_STRUCT
;
202 if (ndr_size_cab_file(r
, &cab_size
) == false) {
203 return NDR_ERR_VALIDATE
;
205 SIVAL(ndr
->data
, 8, cab_size
);
207 return NDR_ERR_SUCCESS
;
210 _PUBLIC_
enum ndr_err_code
ndr_pull_cab_file(struct ndr_pull
*ndr
, int ndr_flags
, struct cab_file
*r
)
212 uint32_t size_cffolders_0
= 0;
213 uint32_t cntr_cffolders_0
;
214 TALLOC_CTX
*_mem_save_cffolders_0
= NULL
;
215 uint32_t size_cffiles_0
= 0;
216 uint32_t cntr_cffiles_0
;
217 TALLOC_CTX
*_mem_save_cffiles_0
= NULL
;
218 uint32_t size_cfdata_0
= 0;
219 uint32_t cntr_cfdata_0
;
220 TALLOC_CTX
*_mem_save_cfdata_0
= NULL
;
222 uint32_t _flags_save_STRUCT
= ndr
->flags
;
223 ndr_set_flags(&ndr
->flags
, LIBNDR_PRINT_ARRAY_HEX
|LIBNDR_FLAG_LITTLE_ENDIAN
|LIBNDR_FLAG_NOALIGN
);
224 NDR_PULL_CHECK_FLAGS(ndr
, ndr_flags
);
225 if (ndr_flags
& NDR_SCALARS
) {
226 NDR_CHECK(ndr_pull_align(ndr
, 4));
227 NDR_CHECK(ndr_pull_CFHEADER(ndr
, NDR_SCALARS
, &r
->cfheader
));
228 size_cffolders_0
= r
->cfheader
.cFolders
;
229 NDR_PULL_ALLOC_N(ndr
, r
->cffolders
, size_cffolders_0
);
230 _mem_save_cffolders_0
= NDR_PULL_GET_MEM_CTX(ndr
);
231 NDR_PULL_SET_MEM_CTX(ndr
, r
->cffolders
, 0);
232 for (cntr_cffolders_0
= 0; cntr_cffolders_0
< (size_cffolders_0
); cntr_cffolders_0
++) {
233 NDR_CHECK(ndr_pull_CFFOLDER(ndr
, NDR_SCALARS
, &r
->cffolders
[cntr_cffolders_0
]));
235 NDR_PULL_SET_MEM_CTX(ndr
, _mem_save_cffolders_0
, 0);
236 size_cffiles_0
= r
->cfheader
.cFiles
;
237 NDR_PULL_ALLOC_N(ndr
, r
->cffiles
, size_cffiles_0
);
238 _mem_save_cffiles_0
= NDR_PULL_GET_MEM_CTX(ndr
);
239 NDR_PULL_SET_MEM_CTX(ndr
, r
->cffiles
, 0);
240 for (cntr_cffiles_0
= 0; cntr_cffiles_0
< (size_cffiles_0
); cntr_cffiles_0
++) {
241 NDR_CHECK(ndr_pull_CFFILE(ndr
, NDR_SCALARS
, &r
->cffiles
[cntr_cffiles_0
]));
243 NDR_PULL_SET_MEM_CTX(ndr
, _mem_save_cffiles_0
, 0);
245 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &r
->cfdata_count
));
247 r
->cfdata_count
= ndr_count_cfdata(r
);
249 size_cfdata_0
= r
->cfdata_count
;
250 NDR_PULL_ALLOC_N(ndr
, r
->cfdata
, size_cfdata_0
);
251 _mem_save_cfdata_0
= NDR_PULL_GET_MEM_CTX(ndr
);
252 NDR_PULL_SET_MEM_CTX(ndr
, r
->cfdata
, 0);
253 for (cntr_cfdata_0
= 0; cntr_cfdata_0
< (size_cfdata_0
); cntr_cfdata_0
++) {
254 NDR_CHECK(ndr_pull_CFDATA(ndr
, NDR_SCALARS
, &r
->cfdata
[cntr_cfdata_0
]));
256 NDR_PULL_SET_MEM_CTX(ndr
, _mem_save_cfdata_0
, 0);
257 NDR_CHECK(ndr_pull_trailer_align(ndr
, 4));
259 if (ndr_flags
& NDR_BUFFERS
) {
261 ndr
->flags
= _flags_save_STRUCT
;
263 return NDR_ERR_SUCCESS
;