/src/samba/librpc/ndr/ndr_dcerpc.c
Line | Count | Source |
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 | | _PUBLIC_ enum ndr_err_code ndr_push_ncacn_packet(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct ncacn_packet *r) |
28 | 467 | { |
29 | 467 | NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); |
30 | 467 | if (ndr_flags & NDR_SCALARS) { |
31 | 467 | NDR_CHECK(ndr_push_align(ndr, 4)); |
32 | 467 | NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->rpc_vers)); |
33 | 467 | NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->rpc_vers_minor)); |
34 | 467 | NDR_CHECK(ndr_push_dcerpc_pkt_type(ndr, NDR_SCALARS, r->ptype)); |
35 | 467 | NDR_CHECK(ndr_push_dcerpc_pfc_flags(ndr, NDR_SCALARS, r->pfc_flags)); |
36 | 467 | NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->drep, 4)); |
37 | 467 | if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) { |
38 | 109 | ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT; |
39 | 109 | } |
40 | 467 | if (!(r->drep[0] & DCERPC_DREP_LE)) { |
41 | 371 | ndr->flags |= LIBNDR_FLAG_BIGENDIAN; |
42 | 371 | } |
43 | 467 | NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->frag_length)); |
44 | 467 | NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->auth_length)); |
45 | 467 | NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->call_id)); |
46 | 467 | NDR_CHECK(ndr_push_set_switch_value(ndr, &r->u, r->ptype)); |
47 | 467 | NDR_CHECK(ndr_push_dcerpc_payload(ndr, NDR_SCALARS, &r->u)); |
48 | 467 | NDR_CHECK(ndr_push_trailer_align(ndr, 4)); |
49 | 467 | } |
50 | 467 | if (ndr_flags & NDR_BUFFERS) { |
51 | 467 | } |
52 | 467 | return NDR_ERR_SUCCESS; |
53 | 467 | } |
54 | | |
55 | | _PUBLIC_ enum ndr_err_code ndr_pull_ncacn_packet(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct ncacn_packet *r) |
56 | 770 | { |
57 | 770 | uint32_t size_drep_0 = 0; |
58 | 770 | NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); |
59 | 770 | if (ndr_flags & NDR_SCALARS) { |
60 | 770 | NDR_CHECK(ndr_pull_align(ndr, 4)); |
61 | 770 | NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->rpc_vers)); |
62 | 769 | NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->rpc_vers_minor)); |
63 | 768 | NDR_CHECK(ndr_pull_dcerpc_pkt_type(ndr, NDR_SCALARS, &r->ptype)); |
64 | 767 | NDR_CHECK(ndr_pull_dcerpc_pfc_flags(ndr, NDR_SCALARS, &r->pfc_flags)); |
65 | 766 | size_drep_0 = 4; |
66 | 766 | NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->drep, size_drep_0)); |
67 | 764 | if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) { |
68 | 198 | ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT; |
69 | 198 | } |
70 | 764 | if (!(r->drep[0] & DCERPC_DREP_LE)) { |
71 | 603 | ndr->flags |= LIBNDR_FLAG_BIGENDIAN; |
72 | 603 | } |
73 | 764 | NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->frag_length)); |
74 | 756 | NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->auth_length)); |
75 | 754 | NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->call_id)); |
76 | 751 | NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->u, r->ptype)); |
77 | 751 | NDR_CHECK(ndr_pull_dcerpc_payload(ndr, NDR_SCALARS, &r->u)); |
78 | 467 | NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); |
79 | 467 | } |
80 | 467 | if (ndr_flags & NDR_BUFFERS) { |
81 | 467 | } |
82 | 467 | return NDR_ERR_SUCCESS; |
83 | 770 | } |
84 | | |
85 | | _PUBLIC_ void ndr_print_ncacn_packet(struct ndr_print *ndr, const char *name, const struct ncacn_packet *r) |
86 | 467 | { |
87 | 467 | ndr_print_struct(ndr, name, "ncacn_packet"); |
88 | 467 | if (r == NULL) { ndr_print_null(ndr); return; } |
89 | 467 | ndr->depth++; |
90 | 467 | ndr_print_uint8(ndr, "rpc_vers", r->rpc_vers); |
91 | 467 | ndr_print_uint8(ndr, "rpc_vers_minor", r->rpc_vers_minor); |
92 | 467 | ndr_print_dcerpc_pkt_type(ndr, "ptype", r->ptype); |
93 | 467 | ndr_print_dcerpc_pfc_flags(ndr, "pfc_flags", r->pfc_flags); |
94 | 467 | ndr_print_array_uint8(ndr, "drep", r->drep, 4); |
95 | 467 | if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) { |
96 | 109 | ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT; |
97 | 109 | } |
98 | 467 | if (!(r->drep[0] & DCERPC_DREP_LE)) { |
99 | 371 | ndr->flags |= LIBNDR_FLAG_BIGENDIAN; |
100 | 371 | } |
101 | 467 | ndr_print_uint16(ndr, "frag_length", r->frag_length); |
102 | 467 | ndr_print_uint16(ndr, "auth_length", r->auth_length); |
103 | 467 | ndr_print_uint32(ndr, "call_id", r->call_id); |
104 | 467 | ndr_print_set_switch_value(ndr, &r->u, r->ptype); |
105 | 467 | ndr_print_dcerpc_payload(ndr, "u", &r->u); |
106 | 467 | ndr->depth--; |
107 | 467 | } |
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 | | enum ndr_err_code ndr_pull_dcerpc_bind_nak(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct dcerpc_bind_nak *r) |
116 | 171 | { |
117 | 171 | uint32_t size_versions_0 = 0; |
118 | 171 | uint32_t cntr_versions_0; |
119 | 171 | TALLOC_CTX *_mem_save_versions_0 = NULL; |
120 | 171 | NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); |
121 | 171 | if (ndr_flags & NDR_SCALARS) { |
122 | 171 | uint32_t _available; |
123 | 171 | NDR_CHECK(ndr_pull_align(ndr, 4)); |
124 | 171 | NDR_CHECK(ndr_pull_dcerpc_bind_nak_reason(ndr, NDR_SCALARS, &r->reject_reason)); |
125 | 169 | _available = ndr->data_size - ndr->offset; |
126 | 169 | if (_available == 0) { |
127 | | /* |
128 | | * This works around a bug in older |
129 | | * Samba (<= 4.1) releases. |
130 | | * |
131 | | * See bug #11327. |
132 | | */ |
133 | 19 | r->num_versions = 0; |
134 | 150 | } else { |
135 | 150 | NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->num_versions)); |
136 | 150 | } |
137 | 169 | size_versions_0 = r->num_versions; |
138 | 169 | NDR_PULL_ALLOC_N(ndr, r->versions, size_versions_0); |
139 | 169 | _mem_save_versions_0 = NDR_PULL_GET_MEM_CTX(ndr); |
140 | 169 | NDR_PULL_SET_MEM_CTX(ndr, r->versions, 0); |
141 | 4.39k | for (cntr_versions_0 = 0; cntr_versions_0 < (size_versions_0); cntr_versions_0++) { |
142 | 4.26k | NDR_CHECK(ndr_pull_dcerpc_bind_nak_version(ndr, NDR_SCALARS, &r->versions[cntr_versions_0])); |
143 | 4.26k | } |
144 | 126 | NDR_PULL_SET_MEM_CTX(ndr, _mem_save_versions_0, 0); |
145 | 126 | { |
146 | 126 | libndr_flags _flags_save_DATA_BLOB = ndr->flags; |
147 | 126 | ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING); |
148 | 126 | NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->_pad)); |
149 | 126 | ndr->flags = _flags_save_DATA_BLOB; |
150 | 126 | } |
151 | 126 | NDR_CHECK(ndr_pull_trailer_align(ndr, 4)); |
152 | 126 | } |
153 | 126 | if (ndr_flags & NDR_BUFFERS) { |
154 | 112 | } |
155 | 126 | return NDR_ERR_SUCCESS; |
156 | 171 | } |
157 | | |
158 | | const uint8_t DCERPC_SEC_VT_MAGIC[] = {0x8a,0xe3,0x13,0x71,0x02,0xf4,0x36,0x71}; |
159 | | |
160 | | _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 | 241 | { |
162 | 241 | NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); |
163 | | /* nothing */ |
164 | 241 | return NDR_ERR_SUCCESS; |
165 | 241 | } |
166 | | |
167 | | _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 | 424 | { |
169 | 424 | uint32_t _saved_ofs = ndr->offset; |
170 | | |
171 | 424 | NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); |
172 | | |
173 | 424 | if (!(ndr_flags & NDR_SCALARS)) { |
174 | 0 | return NDR_ERR_SUCCESS; |
175 | 0 | } |
176 | | |
177 | 424 | r->count = 0; |
178 | | |
179 | 1.72M | while (true) { |
180 | 1.72M | uint16_t command; |
181 | 1.72M | uint16_t length; |
182 | | |
183 | 1.72M | NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &command)); |
184 | 1.72M | NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &length)); |
185 | 1.72M | NDR_CHECK(ndr_pull_advance(ndr, length)); |
186 | | |
187 | 1.72M | r->count += 1; |
188 | | |
189 | 1.72M | if (command & DCERPC_SEC_VT_COMMAND_END) { |
190 | 317 | break; |
191 | 317 | } |
192 | 1.72M | } |
193 | | |
194 | 317 | ndr->offset = _saved_ofs; |
195 | 317 | return NDR_ERR_SUCCESS; |
196 | 424 | } |
197 | | |
198 | | _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 | 0 | { |
202 | 0 | enum ndr_err_code ndr_err; |
203 | 0 | uint32_t ofs; |
204 | 0 | uint32_t min_ofs = 0; |
205 | 0 | struct dcerpc_sec_verification_trailer *r; |
206 | 0 | DATA_BLOB sub_blob = data_blob_null; |
207 | 0 | struct ndr_pull *sub_ndr = NULL; |
208 | 0 | uint32_t remaining; |
209 | |
|
210 | 0 | *_r = NULL; |
211 | |
|
212 | 0 | r = talloc_zero(mem_ctx, struct dcerpc_sec_verification_trailer); |
213 | 0 | if (r == NULL) { |
214 | 0 | return NDR_ERR_ALLOC; |
215 | 0 | } |
216 | | |
217 | 0 | if (ndr->data_size < sizeof(DCERPC_SEC_VT_MAGIC)) { |
218 | | /* |
219 | | * we return with r->count = 0 |
220 | | */ |
221 | 0 | *_r = r; |
222 | 0 | return NDR_ERR_SUCCESS; |
223 | 0 | } |
224 | | |
225 | 0 | ofs = ndr->data_size - sizeof(DCERPC_SEC_VT_MAGIC); |
226 | | /* the magic is 4 byte aligned */ |
227 | 0 | ofs &= ~3; |
228 | |
|
229 | 0 | if (ofs > DCERPC_SEC_VT_MAX_SIZE) { |
230 | | /* |
231 | | * We just scan the last 1024 bytes. |
232 | | */ |
233 | 0 | min_ofs = ofs - DCERPC_SEC_VT_MAX_SIZE; |
234 | 0 | } else { |
235 | 0 | min_ofs = 0; |
236 | 0 | } |
237 | |
|
238 | 0 | while (true) { |
239 | 0 | int ret; |
240 | |
|
241 | 0 | ret = memcmp(&ndr->data[ofs], |
242 | 0 | DCERPC_SEC_VT_MAGIC, |
243 | 0 | sizeof(DCERPC_SEC_VT_MAGIC)); |
244 | 0 | if (ret == 0) { |
245 | 0 | sub_blob = data_blob_const(&ndr->data[ofs], |
246 | 0 | ndr->data_size - ofs); |
247 | 0 | break; |
248 | 0 | } |
249 | | |
250 | 0 | if (ofs <= min_ofs) { |
251 | 0 | break; |
252 | 0 | } |
253 | | |
254 | 0 | ofs -= 4; |
255 | 0 | } |
256 | |
|
257 | 0 | if (sub_blob.length == 0) { |
258 | | /* |
259 | | * we return with r->count = 0 |
260 | | */ |
261 | 0 | *_r = r; |
262 | 0 | return NDR_ERR_SUCCESS; |
263 | 0 | } |
264 | | |
265 | 0 | sub_ndr = ndr_pull_init_blob(&sub_blob, r); |
266 | 0 | if (sub_ndr == NULL) { |
267 | 0 | TALLOC_FREE(r); |
268 | 0 | return NDR_ERR_ALLOC; |
269 | 0 | } |
270 | | |
271 | 0 | ndr_err = ndr_pull_dcerpc_sec_verification_trailer(sub_ndr, |
272 | 0 | NDR_SCALARS | NDR_BUFFERS, |
273 | 0 | r); |
274 | 0 | if (ndr_err == NDR_ERR_ALLOC) { |
275 | 0 | TALLOC_FREE(r); |
276 | 0 | return NDR_ERR_ALLOC; |
277 | 0 | } |
278 | | |
279 | 0 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { |
280 | 0 | goto ignore_error; |
281 | 0 | } |
282 | | |
283 | 0 | remaining = sub_ndr->data_size - sub_ndr->offset; |
284 | 0 | 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 | 0 | } |
291 | | |
292 | | /* |
293 | | * We assume that we got a real verification trailer. |
294 | | * |
295 | | * We remove it from the available stub data. |
296 | | */ |
297 | 0 | ndr->data_size = ofs; |
298 | |
|
299 | 0 | TALLOC_FREE(sub_ndr); |
300 | |
|
301 | 0 | *_r = r; |
302 | 0 | 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 | | ZERO_STRUCTP(r); |
314 | 0 | *_r = r; |
315 | 0 | return NDR_ERR_SUCCESS; |
316 | 0 | } |