s4:smb_server: avoid using gensec_update_ev() for the negotiate blob
[Samba.git] / librpc / ndr / ndr_cab.c
blobae95bf45b3b48601bdcb2a6eddf28db0ca4e1201
1 /*
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/>.
22 #include "includes.h"
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;
28 char *s;
29 if (r == NULL) { ndr_print_null(ndr); return; }
30 hour = r->time >> 11;
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);
36 talloc_free(s);
39 _PUBLIC_ void ndr_print_cf_date(struct ndr_print *ndr, const char *name, const struct cf_date *r)
41 uint16_t year = 0;
42 uint8_t month = 0, day = 0;
43 char *s;
44 if (r == NULL) { ndr_print_null(ndr); return; }
45 year = (r->date >> 9);
46 year += 1980;
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);
52 talloc_free(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) {
61 /* Integer wrap. */
62 return 0;
64 count += r->cffolders[i].cCFData;
67 return count;
70 static uint32_t ndr_cab_compute_checksum(uint8_t *data, uint32_t length, uint32_t seed)
72 int num_ulong;
73 uint32_t checksum;
74 uint8_t *pb;
75 uint32_t ul;
77 num_ulong = length / 4;
78 checksum = seed;
79 pb = data;
81 while (num_ulong-- > 0) {
82 ul = *pb++;
83 ul |= (((uint32_t)(*pb++)) << 8);
84 ul |= (((uint32_t)(*pb++)) << 16);
85 ul |= (((uint32_t)(*pb++)) << 24);
87 checksum ^= ul;
90 ul = 0;
92 switch (length % 4) {
93 case 3:
94 ul |= (((uint32_t)(*pb++)) << 16);
95 case 2:
96 ul |= (((uint32_t)(*pb++)) << 8);
97 case 1:
98 ul |= *pb++;
99 default:
100 break;
103 checksum ^= ul;
105 return checksum;
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),
116 csumPartial);
119 static bool ndr_size_cab_file(const struct cab_file *r, uint32_t *psize)
121 uint32_t size = 0;
122 int i;
124 /* header */
125 size += 36;
127 /* folder */
128 for (i = 0; i < r->cfheader.cFolders; i++) {
129 if (size + 8 < size) {
130 /* Integer wrap. */
131 return false;
133 size += 8;
136 /* files */
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) {
140 /* Integer wrap. */
141 return false;
143 size += cfsize;
146 /* data */
147 for (i = 0; i < ndr_count_cfdata(r); i++) {
148 if (size + 8 < size) {
149 /* Integer wrap. */
150 return false;
152 size += 8;
153 if (size + r->cfdata[i].cbData < size) {
154 /* Integer wrap. */
155 return false;
157 size += r->cfdata[i].cbData;
160 *psize = size;
161 return true;
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);
198 #if 0
199 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_count_cfdata(r)));
200 #endif
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);
253 #if 0
254 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->cfdata_count));
255 #else
256 r->cfdata_count = ndr_count_cfdata(r);
257 #endif
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;