Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Manually parsed structures found in the DCERPC protocol
5 :
6 : Copyright (C) Stefan Metzmacher 2014
7 : Copyright (C) Gregor Beck 2014
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "librpc/gen_ndr/ndr_dcerpc.h"
25 : #include "librpc/gen_ndr/ndr_misc.h"
26 :
27 2146715 : _PUBLIC_ enum ndr_err_code ndr_push_ncacn_packet(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct ncacn_packet *r)
28 : {
29 2146715 : NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
30 2146715 : if (ndr_flags & NDR_SCALARS) {
31 2146715 : NDR_CHECK(ndr_push_align(ndr, 4));
32 2146715 : NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->rpc_vers));
33 2146715 : NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->rpc_vers_minor));
34 2146715 : NDR_CHECK(ndr_push_dcerpc_pkt_type(ndr, NDR_SCALARS, r->ptype));
35 2146715 : NDR_CHECK(ndr_push_dcerpc_pfc_flags(ndr, NDR_SCALARS, r->pfc_flags));
36 2146715 : NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->drep, 4));
37 2146715 : if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
38 693 : ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
39 : }
40 2146715 : if (!(r->drep[0] & DCERPC_DREP_LE)) {
41 32503 : ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
42 : }
43 2146715 : NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->frag_length));
44 2146715 : NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->auth_length));
45 2146715 : NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->call_id));
46 2146715 : NDR_CHECK(ndr_push_set_switch_value(ndr, &r->u, r->ptype));
47 2146715 : NDR_CHECK(ndr_push_dcerpc_payload(ndr, NDR_SCALARS, &r->u));
48 2146715 : NDR_CHECK(ndr_push_trailer_align(ndr, 4));
49 : }
50 2146715 : if (ndr_flags & NDR_BUFFERS) {
51 15942 : }
52 2146715 : return NDR_ERR_SUCCESS;
53 : }
54 :
55 2799585 : _PUBLIC_ enum ndr_err_code ndr_pull_ncacn_packet(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct ncacn_packet *r)
56 : {
57 2799585 : uint32_t size_drep_0 = 0;
58 2799585 : NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
59 2799585 : if (ndr_flags & NDR_SCALARS) {
60 2799585 : NDR_CHECK(ndr_pull_align(ndr, 4));
61 2799585 : NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->rpc_vers));
62 2799585 : NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->rpc_vers_minor));
63 2799585 : NDR_CHECK(ndr_pull_dcerpc_pkt_type(ndr, NDR_SCALARS, &r->ptype));
64 2799585 : NDR_CHECK(ndr_pull_dcerpc_pfc_flags(ndr, NDR_SCALARS, &r->pfc_flags));
65 2799585 : size_drep_0 = 4;
66 2799585 : NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->drep, size_drep_0));
67 2799585 : if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
68 686 : ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
69 : }
70 2799585 : if (!(r->drep[0] & DCERPC_DREP_LE)) {
71 31224 : ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
72 : }
73 2799585 : NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->frag_length));
74 2799585 : NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->auth_length));
75 2799585 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->call_id));
76 2799585 : NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->u, r->ptype));
77 2799585 : NDR_CHECK(ndr_pull_dcerpc_payload(ndr, NDR_SCALARS, &r->u));
78 2799585 : NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
79 : }
80 2799585 : if (ndr_flags & NDR_BUFFERS) {
81 23886 : }
82 2799585 : return NDR_ERR_SUCCESS;
83 : }
84 :
85 248 : _PUBLIC_ void ndr_print_ncacn_packet(struct ndr_print *ndr, const char *name, const struct ncacn_packet *r)
86 : {
87 248 : ndr_print_struct(ndr, name, "ncacn_packet");
88 248 : if (r == NULL) { ndr_print_null(ndr); return; }
89 248 : ndr->depth++;
90 248 : ndr_print_uint8(ndr, "rpc_vers", r->rpc_vers);
91 248 : ndr_print_uint8(ndr, "rpc_vers_minor", r->rpc_vers_minor);
92 248 : ndr_print_dcerpc_pkt_type(ndr, "ptype", r->ptype);
93 248 : ndr_print_dcerpc_pfc_flags(ndr, "pfc_flags", r->pfc_flags);
94 248 : ndr_print_array_uint8(ndr, "drep", r->drep, 4);
95 248 : if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
96 0 : ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
97 : }
98 248 : if (!(r->drep[0] & DCERPC_DREP_LE)) {
99 0 : ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
100 : }
101 248 : ndr_print_uint16(ndr, "frag_length", r->frag_length);
102 248 : ndr_print_uint16(ndr, "auth_length", r->auth_length);
103 248 : ndr_print_uint32(ndr, "call_id", r->call_id);
104 248 : ndr_print_set_switch_value(ndr, &r->u, r->ptype);
105 248 : ndr_print_dcerpc_payload(ndr, "u", &r->u);
106 248 : ndr->depth--;
107 : }
108 :
109 : /*
110 : * This function was generated by pidl and
111 : * has been extended by the (_available == 0) check.
112 : *
113 : * That's why we ignore the 80 char per line limit.
114 : */
115 230 : enum ndr_err_code ndr_pull_dcerpc_bind_nak(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct dcerpc_bind_nak *r)
116 : {
117 230 : uint32_t size_versions_0 = 0;
118 36 : uint32_t cntr_versions_0;
119 230 : TALLOC_CTX *_mem_save_versions_0 = NULL;
120 230 : NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
121 230 : if (ndr_flags & NDR_SCALARS) {
122 36 : uint32_t _available;
123 230 : NDR_CHECK(ndr_pull_align(ndr, 4));
124 230 : NDR_CHECK(ndr_pull_dcerpc_bind_nak_reason(ndr, NDR_SCALARS, &r->reject_reason));
125 230 : _available = ndr->data_size - ndr->offset;
126 230 : if (_available == 0) {
127 : /*
128 : * This works around a bug in older
129 : * Samba (<= 4.1) releases.
130 : *
131 : * See bug #11327.
132 : */
133 0 : r->num_versions = 0;
134 : } else {
135 230 : NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->num_versions));
136 : }
137 230 : size_versions_0 = r->num_versions;
138 230 : NDR_PULL_ALLOC_N(ndr, r->versions, size_versions_0);
139 230 : _mem_save_versions_0 = NDR_PULL_GET_MEM_CTX(ndr);
140 230 : NDR_PULL_SET_MEM_CTX(ndr, r->versions, 0);
141 460 : for (cntr_versions_0 = 0; cntr_versions_0 < (size_versions_0); cntr_versions_0++) {
142 230 : NDR_CHECK(ndr_pull_dcerpc_bind_nak_version(ndr, NDR_SCALARS, &r->versions[cntr_versions_0]));
143 : }
144 230 : NDR_PULL_SET_MEM_CTX(ndr, _mem_save_versions_0, 0);
145 : {
146 230 : libndr_flags _flags_save_DATA_BLOB = ndr->flags;
147 230 : ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
148 230 : NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->_pad));
149 230 : ndr->flags = _flags_save_DATA_BLOB;
150 : }
151 230 : NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
152 : }
153 230 : if (ndr_flags & NDR_BUFFERS) {
154 36 : }
155 230 : return NDR_ERR_SUCCESS;
156 : }
157 :
158 : const uint8_t DCERPC_SEC_VT_MAGIC[] = {0x8a,0xe3,0x13,0x71,0x02,0xf4,0x36,0x71};
159 :
160 17187 : _PUBLIC_ enum ndr_err_code ndr_push_dcerpc_sec_vt_count(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct dcerpc_sec_vt_count *r)
161 : {
162 17187 : NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
163 : /* nothing */
164 16579 : return NDR_ERR_SUCCESS;
165 : }
166 :
167 17029 : _PUBLIC_ enum ndr_err_code ndr_pull_dcerpc_sec_vt_count(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct dcerpc_sec_vt_count *r)
168 : {
169 17029 : uint32_t _saved_ofs = ndr->offset;
170 :
171 17029 : NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
172 :
173 17029 : if (!(ndr_flags & NDR_SCALARS)) {
174 0 : return NDR_ERR_SUCCESS;
175 : }
176 :
177 17029 : r->count = 0;
178 :
179 9785 : while (true) {
180 1216 : uint16_t command;
181 1216 : uint16_t length;
182 :
183 26814 : NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &command));
184 26814 : NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &length));
185 26814 : NDR_CHECK(ndr_pull_advance(ndr, length));
186 :
187 26814 : r->count += 1;
188 :
189 26814 : if (command & DCERPC_SEC_VT_COMMAND_END) {
190 16420 : break;
191 : }
192 : }
193 :
194 17029 : ndr->offset = _saved_ofs;
195 17029 : return NDR_ERR_SUCCESS;
196 : }
197 :
198 847917 : _PUBLIC_ enum ndr_err_code ndr_pop_dcerpc_sec_verification_trailer(
199 : struct ndr_pull *ndr, TALLOC_CTX *mem_ctx,
200 : struct dcerpc_sec_verification_trailer **_r)
201 : {
202 6940 : enum ndr_err_code ndr_err;
203 6940 : uint32_t ofs;
204 847917 : uint32_t min_ofs = 0;
205 6940 : struct dcerpc_sec_verification_trailer *r;
206 847917 : DATA_BLOB sub_blob = data_blob_null;
207 847917 : struct ndr_pull *sub_ndr = NULL;
208 6940 : uint32_t remaining;
209 :
210 847917 : *_r = NULL;
211 :
212 847917 : r = talloc_zero(mem_ctx, struct dcerpc_sec_verification_trailer);
213 847917 : if (r == NULL) {
214 0 : return NDR_ERR_ALLOC;
215 : }
216 :
217 847917 : if (ndr->data_size < sizeof(DCERPC_SEC_VT_MAGIC)) {
218 : /*
219 : * we return with r->count = 0
220 : */
221 6074 : *_r = r;
222 6074 : return NDR_ERR_SUCCESS;
223 : }
224 :
225 841843 : ofs = ndr->data_size - sizeof(DCERPC_SEC_VT_MAGIC);
226 : /* the magic is 4 byte aligned */
227 841843 : ofs &= ~3;
228 :
229 841843 : if (ofs > DCERPC_SEC_VT_MAX_SIZE) {
230 : /*
231 : * We just scan the last 1024 bytes.
232 : */
233 6402 : min_ofs = ofs - DCERPC_SEC_VT_MAX_SIZE;
234 : } else {
235 835544 : min_ofs = 0;
236 : }
237 :
238 17474508 : while (true) {
239 274717 : int ret;
240 :
241 18041634 : ret = memcmp(&ndr->data[ofs],
242 : DCERPC_SEC_VT_MAGIC,
243 : sizeof(DCERPC_SEC_VT_MAGIC));
244 18041634 : if (ret == 0) {
245 17029 : sub_blob = data_blob_const(&ndr->data[ofs],
246 17029 : ndr->data_size - ofs);
247 17029 : break;
248 : }
249 :
250 18024605 : if (ofs <= min_ofs) {
251 818538 : break;
252 : }
253 :
254 17199791 : ofs -= 4;
255 : }
256 :
257 841843 : if (sub_blob.length == 0) {
258 : /*
259 : * we return with r->count = 0
260 : */
261 824814 : *_r = r;
262 824814 : return NDR_ERR_SUCCESS;
263 : }
264 :
265 17029 : sub_ndr = ndr_pull_init_blob(&sub_blob, r);
266 17029 : if (sub_ndr == NULL) {
267 0 : TALLOC_FREE(r);
268 0 : return NDR_ERR_ALLOC;
269 : }
270 :
271 17029 : ndr_err = ndr_pull_dcerpc_sec_verification_trailer(sub_ndr,
272 : NDR_SCALARS | NDR_BUFFERS,
273 : r);
274 17029 : if (ndr_err == NDR_ERR_ALLOC) {
275 0 : TALLOC_FREE(r);
276 0 : return NDR_ERR_ALLOC;
277 : }
278 :
279 17029 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
280 0 : goto ignore_error;
281 : }
282 :
283 17029 : remaining = sub_ndr->data_size - sub_ndr->offset;
284 17029 : if (remaining > 16) {
285 : /*
286 : * we expect not more than 16 byte of additional
287 : * padding after the verification trailer.
288 : */
289 0 : goto ignore_error;
290 : }
291 :
292 : /*
293 : * We assume that we got a real verification trailer.
294 : *
295 : * We remove it from the available stub data.
296 : */
297 17029 : ndr->data_size = ofs;
298 :
299 17029 : TALLOC_FREE(sub_ndr);
300 :
301 17029 : *_r = r;
302 17029 : return NDR_ERR_SUCCESS;
303 :
304 0 : ignore_error:
305 0 : TALLOC_FREE(sub_ndr);
306 : /*
307 : * just ignore the error, it's likely
308 : * that the magic we found belongs to
309 : * the stub data.
310 : *
311 : * we return with r->count = 0
312 : */
313 0 : ZERO_STRUCTP(r);
314 0 : *_r = r;
315 0 : return NDR_ERR_SUCCESS;
316 : }
|