smbd: Fix cached dos attributes
[Samba.git] / librpc / ndr / ndr_dcerpc.c
blobb368bfaa8189e73a5fd715bc9a55a65ee6307d34
1 /*
2 Unix SMB/CIFS implementation.
4 Manually parsed structures found in the DCERPC protocol
6 Copyright (C) Stefan Metzmacher 2014
7 Copyright (C) Gregor Beck 2014
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.
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.
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/>.
23 #include "includes.h"
24 #include "librpc/gen_ndr/ndr_dcerpc.h"
25 #include "librpc/gen_ndr/ndr_misc.h"
27 _PUBLIC_ enum ndr_err_code ndr_push_ncacn_packet(struct ndr_push *ndr, ndr_flags_type ndr_flags, const struct ncacn_packet *r)
29 NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
30 if (ndr_flags & NDR_SCALARS) {
31 NDR_CHECK(ndr_push_align(ndr, 4));
32 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->rpc_vers));
33 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->rpc_vers_minor));
34 NDR_CHECK(ndr_push_dcerpc_pkt_type(ndr, NDR_SCALARS, r->ptype));
35 NDR_CHECK(ndr_push_dcerpc_pfc_flags(ndr, NDR_SCALARS, r->pfc_flags));
36 NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->drep, 4));
37 if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
38 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
40 if (!(r->drep[0] & DCERPC_DREP_LE)) {
41 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
43 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->frag_length));
44 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->auth_length));
45 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->call_id));
46 NDR_CHECK(ndr_push_set_switch_value(ndr, &r->u, r->ptype));
47 NDR_CHECK(ndr_push_dcerpc_payload(ndr, NDR_SCALARS, &r->u));
48 NDR_CHECK(ndr_push_trailer_align(ndr, 4));
50 if (ndr_flags & NDR_BUFFERS) {
52 return NDR_ERR_SUCCESS;
55 _PUBLIC_ enum ndr_err_code ndr_pull_ncacn_packet(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct ncacn_packet *r)
57 uint32_t size_drep_0 = 0;
58 NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
59 if (ndr_flags & NDR_SCALARS) {
60 NDR_CHECK(ndr_pull_align(ndr, 4));
61 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->rpc_vers));
62 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->rpc_vers_minor));
63 NDR_CHECK(ndr_pull_dcerpc_pkt_type(ndr, NDR_SCALARS, &r->ptype));
64 NDR_CHECK(ndr_pull_dcerpc_pfc_flags(ndr, NDR_SCALARS, &r->pfc_flags));
65 size_drep_0 = 4;
66 NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->drep, size_drep_0));
67 if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
68 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
70 if (!(r->drep[0] & DCERPC_DREP_LE)) {
71 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
73 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->frag_length));
74 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->auth_length));
75 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->call_id));
76 NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->u, r->ptype));
77 NDR_CHECK(ndr_pull_dcerpc_payload(ndr, NDR_SCALARS, &r->u));
78 NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
80 if (ndr_flags & NDR_BUFFERS) {
82 return NDR_ERR_SUCCESS;
85 _PUBLIC_ void ndr_print_ncacn_packet(struct ndr_print *ndr, const char *name, const struct ncacn_packet *r)
87 ndr_print_struct(ndr, name, "ncacn_packet");
88 if (r == NULL) { ndr_print_null(ndr); return; }
89 ndr->depth++;
90 ndr_print_uint8(ndr, "rpc_vers", r->rpc_vers);
91 ndr_print_uint8(ndr, "rpc_vers_minor", r->rpc_vers_minor);
92 ndr_print_dcerpc_pkt_type(ndr, "ptype", r->ptype);
93 ndr_print_dcerpc_pfc_flags(ndr, "pfc_flags", r->pfc_flags);
94 ndr_print_array_uint8(ndr, "drep", r->drep, 4);
95 if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
96 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
98 if (!(r->drep[0] & DCERPC_DREP_LE)) {
99 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
101 ndr_print_uint16(ndr, "frag_length", r->frag_length);
102 ndr_print_uint16(ndr, "auth_length", r->auth_length);
103 ndr_print_uint32(ndr, "call_id", r->call_id);
104 ndr_print_set_switch_value(ndr, &r->u, r->ptype);
105 ndr_print_dcerpc_payload(ndr, "u", &r->u);
106 ndr->depth--;
110 * This function was generated by pidl and
111 * has been extended by the (_available == 0) check.
113 * That's why we ignore the 80 char per line limit.
115 enum ndr_err_code ndr_pull_dcerpc_bind_nak(struct ndr_pull *ndr, ndr_flags_type ndr_flags, struct dcerpc_bind_nak *r)
117 uint32_t size_versions_0 = 0;
118 uint32_t cntr_versions_0;
119 TALLOC_CTX *_mem_save_versions_0 = NULL;
120 NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
121 if (ndr_flags & NDR_SCALARS) {
122 uint32_t _available;
123 NDR_CHECK(ndr_pull_align(ndr, 4));
124 NDR_CHECK(ndr_pull_dcerpc_bind_nak_reason(ndr, NDR_SCALARS, &r->reject_reason));
125 _available = ndr->data_size - ndr->offset;
126 if (_available == 0) {
128 * This works around a bug in older
129 * Samba (<= 4.1) releases.
131 * See bug #11327.
133 r->num_versions = 0;
134 } else {
135 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->num_versions));
137 size_versions_0 = r->num_versions;
138 NDR_PULL_ALLOC_N(ndr, r->versions, size_versions_0);
139 _mem_save_versions_0 = NDR_PULL_GET_MEM_CTX(ndr);
140 NDR_PULL_SET_MEM_CTX(ndr, r->versions, 0);
141 for (cntr_versions_0 = 0; cntr_versions_0 < (size_versions_0); cntr_versions_0++) {
142 NDR_CHECK(ndr_pull_dcerpc_bind_nak_version(ndr, NDR_SCALARS, &r->versions[cntr_versions_0]));
144 NDR_PULL_SET_MEM_CTX(ndr, _mem_save_versions_0, 0);
146 libndr_flags _flags_save_DATA_BLOB = ndr->flags;
147 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
148 NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->_pad));
149 ndr->flags = _flags_save_DATA_BLOB;
151 NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
153 if (ndr_flags & NDR_BUFFERS) {
155 return NDR_ERR_SUCCESS;
158 const uint8_t DCERPC_SEC_VT_MAGIC[] = {0x8a,0xe3,0x13,0x71,0x02,0xf4,0x36,0x71};
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)
162 NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
163 /* nothing */
164 return NDR_ERR_SUCCESS;
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)
169 uint32_t _saved_ofs = ndr->offset;
171 NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
173 if (!(ndr_flags & NDR_SCALARS)) {
174 return NDR_ERR_SUCCESS;
177 r->count = 0;
179 while (true) {
180 uint16_t command;
181 uint16_t length;
183 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &command));
184 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &length));
185 NDR_CHECK(ndr_pull_advance(ndr, length));
187 r->count += 1;
189 if (command & DCERPC_SEC_VT_COMMAND_END) {
190 break;
194 ndr->offset = _saved_ofs;
195 return NDR_ERR_SUCCESS;
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)
202 enum ndr_err_code ndr_err;
203 uint32_t ofs;
204 uint32_t min_ofs = 0;
205 struct dcerpc_sec_verification_trailer *r;
206 DATA_BLOB sub_blob = data_blob_null;
207 struct ndr_pull *sub_ndr = NULL;
208 uint32_t remaining;
210 *_r = NULL;
212 r = talloc_zero(mem_ctx, struct dcerpc_sec_verification_trailer);
213 if (r == NULL) {
214 return NDR_ERR_ALLOC;
217 if (ndr->data_size < sizeof(DCERPC_SEC_VT_MAGIC)) {
219 * we return with r->count = 0
221 *_r = r;
222 return NDR_ERR_SUCCESS;
225 ofs = ndr->data_size - sizeof(DCERPC_SEC_VT_MAGIC);
226 /* the magic is 4 byte aligned */
227 ofs &= ~3;
229 if (ofs > DCERPC_SEC_VT_MAX_SIZE) {
231 * We just scan the last 1024 bytes.
233 min_ofs = ofs - DCERPC_SEC_VT_MAX_SIZE;
234 } else {
235 min_ofs = 0;
238 while (true) {
239 int ret;
241 ret = memcmp(&ndr->data[ofs],
242 DCERPC_SEC_VT_MAGIC,
243 sizeof(DCERPC_SEC_VT_MAGIC));
244 if (ret == 0) {
245 sub_blob = data_blob_const(&ndr->data[ofs],
246 ndr->data_size - ofs);
247 break;
250 if (ofs <= min_ofs) {
251 break;
254 ofs -= 4;
257 if (sub_blob.length == 0) {
259 * we return with r->count = 0
261 *_r = r;
262 return NDR_ERR_SUCCESS;
265 sub_ndr = ndr_pull_init_blob(&sub_blob, r);
266 if (sub_ndr == NULL) {
267 TALLOC_FREE(r);
268 return NDR_ERR_ALLOC;
271 ndr_err = ndr_pull_dcerpc_sec_verification_trailer(sub_ndr,
272 NDR_SCALARS | NDR_BUFFERS,
274 if (ndr_err == NDR_ERR_ALLOC) {
275 TALLOC_FREE(r);
276 return NDR_ERR_ALLOC;
279 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
280 goto ignore_error;
283 remaining = sub_ndr->data_size - sub_ndr->offset;
284 if (remaining > 16) {
286 * we expect not more than 16 byte of additional
287 * padding after the verification trailer.
289 goto ignore_error;
293 * We assume that we got a real verification trailer.
295 * We remove it from the available stub data.
297 ndr->data_size = ofs;
299 TALLOC_FREE(sub_ndr);
301 *_r = r;
302 return NDR_ERR_SUCCESS;
304 ignore_error:
305 TALLOC_FREE(sub_ndr);
307 * just ignore the error, it's likely
308 * that the magic we found belongs to
309 * the stub data.
311 * we return with r->count = 0
313 ZERO_STRUCTP(r);
314 *_r = r;
315 return NDR_ERR_SUCCESS;