1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
24 */
25
26 #include <assert.h>
27 #include <strings.h>
28 #include <sys/param.h>
29 #include <sys/debug.h>
30
31 #include <libmlrpc.h>
32
33 #ifdef _BIG_ENDIAN
34 static const int ndr_native_byte_order = NDR_REPLAB_INTG_BIG_ENDIAN;
35 #else
36 static const int ndr_native_byte_order = NDR_REPLAB_INTG_LITTLE_ENDIAN;
37 #endif
38
39 static int ndr_decode_hdr_common(ndr_stream_t *, ndr_common_header_t *);
40 static int ndr_decode_pac_hdr(ndr_stream_t *, ndr_pac_hdr_t *);
41
42 /*
43 * This is the layout of an RPC PDU, as shown in
44 * [MS-RPCE] 2.2.2.13 "Verification Trailer".
45 *
46 * +-------------------------------+
47 * | PDU Header |
48 * +-------------------------------+ ====
49 * | Stub Data |
50 * +-------------------------------+ PDU
51 * | Stub Padding Octets |
52 * +-------------------------------+ Body
53 * | Verification Trailer |
54 * +-------------------------------+ Here
55 * | Authentication Padding |
56 * +-------------------------------+ ====
57 * | sec_trailer |
58 * +-------------------------------+
59 * | Authentication Token |
60 * +-------------------------------+
61 *
62 * We don't use the "Verification Trailer" for anything yet.
63 * sec_trailer and Authentication Token are for Secure RPC,
64 * and are collectively the 'auth_verifier_co' in DCERPC.
65 *
66 * Each fragment of a multi-fragment response has a unique
67 * header and, if authentication was requested, a unique
68 * sec_trailer.
69 */
70
71 static int
ndr_convert_nds_error(ndr_stream_t * nds)72 ndr_convert_nds_error(ndr_stream_t *nds)
73 {
74 int rc;
75
76 switch (nds->error) {
77 case NDR_ERR_MALLOC_FAILED:
78 rc = NDR_DRC_FAULT_OUT_OF_MEMORY;
79 break;
80
81 case NDR_ERR_SWITCH_VALUE_INVALID:
82 rc = NDR_DRC_FAULT_PARAM_0_INVALID;
83 break;
84
85 case NDR_ERR_UNDERFLOW:
86 rc = NDR_DRC_FAULT_RECEIVED_RUNT;
87 break;
88
89 case NDR_ERR_GROW_FAILED:
90 rc = NDR_DRC_FAULT_ENCODE_TOO_BIG;
91 break;
92
93 default:
94 if (nds->m_op == NDR_M_OP_MARSHALL)
95 rc = NDR_DRC_FAULT_ENCODE_FAILED;
96 else
97 rc = NDR_DRC_FAULT_DECODE_FAILED;
98 break;
99 }
100
101 return (rc);
102 }
103
104 static int
ndr_encode_decode_common(ndr_stream_t * nds,unsigned opnum,ndr_typeinfo_t * ti,void * datum)105 ndr_encode_decode_common(ndr_stream_t *nds, unsigned opnum,
106 ndr_typeinfo_t *ti, void *datum)
107 {
108 /*
109 * Perform the (un)marshalling
110 */
111 if (ndo_operation(nds, ti, opnum, datum))
112 return (NDR_DRC_OK);
113
114 return (ndr_convert_nds_error(nds));
115 }
116
117 static int
ndr_encode_decode_type(ndr_stream_t * nds,ndr_typeinfo_t * ti,void * datum)118 ndr_encode_decode_type(ndr_stream_t *nds, ndr_typeinfo_t *ti, void *datum)
119 {
120 /*
121 * Perform the (un)marshalling
122 */
123 if (ndo_process(nds, ti, datum))
124 return (NDR_DRC_OK);
125
126 return (ndr_convert_nds_error(nds));
127 }
128
129 ndr_buf_t *
ndr_buf_init(ndr_typeinfo_t * ti)130 ndr_buf_init(ndr_typeinfo_t *ti)
131 {
132 ndr_buf_t *nbuf;
133
134 if ((nbuf = calloc(1, sizeof (ndr_buf_t))) == NULL)
135 return (NULL);
136
137 if ((nbuf->nb_heap = ndr_heap_create()) == NULL) {
138 free(nbuf);
139 return (NULL);
140 }
141
142 nbuf->nb_ti = ti;
143 nbuf->nb_magic = NDR_BUF_MAGIC;
144 return (nbuf);
145 }
146
147 void
ndr_buf_fini(ndr_buf_t * nbuf)148 ndr_buf_fini(ndr_buf_t *nbuf)
149 {
150 assert(nbuf->nb_magic == NDR_BUF_MAGIC);
151
152 nds_destruct(&nbuf->nb_nds);
153 ndr_heap_destroy(nbuf->nb_heap);
154 nbuf->nb_magic = 0;
155 free(nbuf);
156 }
157
158 /*
159 * Decode an NDR encoded buffer. The buffer is expected to contain
160 * a single fragment packet with a valid PDU header followed by NDR
161 * encoded data. The structure to which result points should be
162 * of the appropriate type to hold the decoded output. For example:
163 *
164 * pac_info_t info;
165 *
166 * if ((nbuf = ndr_buf_init(&TYPEINFO(ndr_pac)) != NULL) {
167 * rc = ndr_decode_buf(nbuf, opnum, data, datalen, &info);
168 * ...
169 * ndr_buf_fini(nbuf);
170 * }
171 */
172 int
ndr_buf_decode(ndr_buf_t * nbuf,unsigned hdr_type,unsigned opnum,const char * data,size_t datalen,void * result)173 ndr_buf_decode(ndr_buf_t *nbuf, unsigned hdr_type, unsigned opnum,
174 const char *data, size_t datalen, void *result)
175 {
176 ndr_common_header_t hdr;
177 ndr_pac_hdr_t pac_hdr;
178 unsigned pdu_size_hint;
179 int rc;
180
181 assert(nbuf->nb_magic == NDR_BUF_MAGIC);
182 assert(nbuf->nb_heap != NULL);
183 assert(nbuf->nb_ti != NULL);
184
185 if (datalen < NDR_PDU_SIZE_HINT_DEFAULT)
186 pdu_size_hint = NDR_PDU_SIZE_HINT_DEFAULT;
187 else
188 pdu_size_hint = datalen;
189
190 rc = nds_initialize(&nbuf->nb_nds, pdu_size_hint, NDR_MODE_BUF_DECODE,
191 nbuf->nb_heap);
192 if (NDR_DRC_IS_FAULT(rc))
193 return (rc);
194
195 bcopy(data, nbuf->nb_nds.pdu_base_addr, datalen);
196 nbuf->nb_nds.pdu_size = datalen;
197
198 switch (hdr_type) {
199 case NDR_PTYPE_COMMON:
200 rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr);
201 if (NDR_DRC_IS_FAULT(rc))
202 return (rc);
203
204 if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags))
205 return (NDR_DRC_FAULT_DECODE_FAILED);
206 break;
207
208 case NDR_PTYPE_PAC:
209 rc = ndr_decode_pac_hdr(&nbuf->nb_nds, &pac_hdr);
210 if (NDR_DRC_IS_FAULT(rc))
211 return (rc);
212
213 if (pac_hdr.common_hdr.hdrlen != sizeof (ndr_serialtype1_hdr_t))
214 return (NDR_DRC_FAULT_DECODE_FAILED);
215 break;
216
217 default:
218 return (NDR_ERR_UNIMPLEMENTED);
219 }
220
221 rc = ndr_encode_decode_common(&nbuf->nb_nds, opnum, nbuf->nb_ti,
222 result);
223 return (rc);
224 }
225
226 /*
227 * Use the receive stream to unmarshall data (NDR_MODE_CALL_RECV).
228 */
229 int
ndr_decode_call(ndr_xa_t * mxa,void * params)230 ndr_decode_call(ndr_xa_t *mxa, void *params)
231 {
232 ndr_stream_t *nds = &mxa->recv_nds;
233 int rc;
234
235 if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_RECV))
236 return (NDR_DRC_FAULT_MODE_MISMATCH);
237
238 rc = ndr_encode_decode_common(nds, mxa->opnum,
239 mxa->binding->service->interface_ti, params);
240
241 return (rc + NDR_PTYPE_REQUEST);
242 }
243
244 /*
245 * Use the send stream to marshall data (NDR_MODE_RETURN_SEND).
246 */
247 int
ndr_encode_return(ndr_xa_t * mxa,void * params)248 ndr_encode_return(ndr_xa_t *mxa, void *params)
249 {
250 ndr_stream_t *nds = &mxa->send_nds;
251 int rc;
252
253 if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND))
254 return (NDR_DRC_FAULT_MODE_MISMATCH);
255
256 rc = ndr_encode_decode_common(nds, mxa->opnum,
257 mxa->binding->service->interface_ti, params);
258
259 return (rc + NDR_PTYPE_RESPONSE);
260 }
261
262 /*
263 * Use the send stream to marshall data (NDR_MODE_CALL_SEND).
264 */
265 int
ndr_encode_call(ndr_xa_t * mxa,void * params)266 ndr_encode_call(ndr_xa_t *mxa, void *params)
267 {
268 ndr_stream_t *nds = &mxa->send_nds;
269 int rc;
270
271 if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_SEND))
272 return (NDR_DRC_FAULT_MODE_MISMATCH);
273
274 rc = ndr_encode_decode_common(nds, mxa->opnum,
275 mxa->binding->service->interface_ti, params);
276
277 return (rc + NDR_PTYPE_REQUEST);
278 }
279
280 /*
281 * Use the receive stream to unmarshall data (NDR_MODE_RETURN_RECV).
282 */
283 int
ndr_decode_return(ndr_xa_t * mxa,void * params)284 ndr_decode_return(ndr_xa_t *mxa, void *params)
285 {
286 ndr_stream_t *nds = &mxa->recv_nds;
287 int rc;
288
289 if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_RECV))
290 return (NDR_DRC_FAULT_MODE_MISMATCH);
291
292 rc = ndr_encode_decode_common(nds, mxa->opnum,
293 mxa->binding->service->interface_ti, params);
294
295 return (rc + NDR_PTYPE_RESPONSE);
296 }
297
298 int
ndr_decode_pdu_hdr(ndr_xa_t * mxa)299 ndr_decode_pdu_hdr(ndr_xa_t *mxa)
300 {
301 ndr_common_header_t *hdr = &mxa->recv_hdr.common_hdr;
302 ndr_stream_t *nds = &mxa->recv_nds;
303 int rc;
304 ulong_t saved_offset;
305
306 saved_offset = nds->pdu_scan_offset;
307 rc = ndr_decode_hdr_common(nds, hdr);
308 if (NDR_DRC_IS_FAULT(rc))
309 return (rc);
310
311 /*
312 * Verify the protocol version.
313 */
314 if ((hdr->rpc_vers != 5) || (hdr->rpc_vers_minor != 0))
315 return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
316
317 mxa->ptype = hdr->ptype;
318 /* pdu_scan_offset now points to (this fragment's) stub data */
319 nds->pdu_body_offset = nds->pdu_scan_offset;
320 nds->pdu_hdr_size = nds->pdu_scan_offset - saved_offset;
321 nds->pdu_body_size = hdr->frag_length - hdr->auth_length -
322 nds->pdu_hdr_size -
323 ((hdr->auth_length != 0) ? SEC_TRAILER_SIZE : 0);
324
325 if (hdr->auth_length != 0 && hdr->auth_length >
326 (hdr->frag_length - nds->pdu_hdr_size - SEC_TRAILER_SIZE))
327 return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
328 return (NDR_DRC_OK);
329 }
330
331 static int
ndr_decode_hdr_common(ndr_stream_t * nds,ndr_common_header_t * hdr)332 ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr)
333 {
334 int ptype;
335 int rc;
336 int charset;
337 int byte_order;
338 ulong_t saved_offset;
339
340 if (nds->m_op != NDR_M_OP_UNMARSHALL)
341 return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
342
343 /*
344 * All PDU headers are at least this big
345 */
346 saved_offset = nds->pdu_scan_offset;
347 if ((nds->pdu_size - saved_offset) < sizeof (ndr_common_header_t))
348 return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
349
350 /*
351 * Peek at the first eight bytes to figure out what we're doing.
352 */
353 rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
354 if (!rc)
355 return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
356
357 /*
358 * Check for ASCII as the character set. This is an ASCII
359 * versus EBCDIC option and has nothing to do with Unicode.
360 */
361 charset = hdr->packed_drep.intg_char_rep & NDR_REPLAB_CHAR_MASK;
362 if (charset != NDR_REPLAB_CHAR_ASCII)
363 return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
364
365 /*
366 * Set the byte swap flag if the PDU byte-order
367 * is different from the local byte-order.
368 */
369 byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
370 nds->swap = (byte_order != ndr_native_byte_order) ? 1 : 0;
371
372 ptype = hdr->ptype;
373 if (ptype == NDR_PTYPE_REQUEST &&
374 (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
375 ptype = NDR_PTYPE_REQUEST_WITH; /* fake for sizing */
376 }
377
378 rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
379
380 if (hdr->frag_length > (nds->pdu_size - saved_offset))
381 rc = NDR_DRC_FAULT_RECEIVED_MALFORMED;
382 return (NDR_DRC_PTYPE_RPCHDR(rc));
383 }
384
385 static int
ndr_decode_pac_hdr(ndr_stream_t * nds,ndr_pac_hdr_t * hdr)386 ndr_decode_pac_hdr(ndr_stream_t *nds, ndr_pac_hdr_t *hdr)
387 {
388 int rc;
389
390 if (nds->m_op != NDR_M_OP_UNMARSHALL)
391 return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
392
393 /*
394 * All PDU headers are at least this big
395 */
396 if ((nds->pdu_size - nds->pdu_scan_offset) < sizeof (ndr_pac_hdr_t))
397 return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
398
399 /*
400 * Peek at the first eight bytes to figure out what we're doing.
401 */
402 rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
403 if (!rc)
404 return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
405
406 /* Must be set to 1 to indicate type serialization version 1. */
407 if (hdr->common_hdr.version != 1)
408 return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
409
410 /*
411 * Set the byte swap flag if the PDU byte-order
412 * is different from the local byte-order.
413 */
414 nds->swap =
415 (hdr->common_hdr.endianness != ndr_native_byte_order) ? 1 : 0;
416
417 rc = ndr_encode_decode_common(nds, NDR_PTYPE_PAC,
418 &TYPEINFO(ndr_hdr), hdr);
419
420 return (NDR_DRC_PTYPE_RPCHDR(rc));
421 }
422
423 CTASSERT(sizeof (ndr_common_header_t) >= NDR_CMN_HDR_SIZE);
424
425 /*
426 * Decode an RPC fragment header. Use ndr_decode_pdu_hdr() to process
427 * the first fragment header then this function to process additional
428 * fragment headers.
429 */
430 void
ndr_decode_frag_hdr(ndr_stream_t * nds,ndr_common_header_t * hdr)431 ndr_decode_frag_hdr(ndr_stream_t *nds, ndr_common_header_t *hdr)
432 {
433 ndr_common_header_t *tmp;
434 uint8_t *pdu;
435 int byte_order;
436
437 pdu = (uint8_t *)nds->pdu_base_offset + nds->pdu_scan_offset;
438 bcopy(pdu, hdr, NDR_CMN_HDR_SIZE);
439
440 /*
441 * Swap non-byte fields if the PDU byte-order
442 * is different from the local byte-order.
443 */
444 byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
445
446 if (byte_order != ndr_native_byte_order) {
447 /*LINTED E_BAD_PTR_CAST_ALIGN*/
448 tmp = (ndr_common_header_t *)pdu;
449
450 nds_bswap(&tmp->frag_length, &hdr->frag_length,
451 sizeof (WORD));
452 nds_bswap(&tmp->auth_length, &hdr->auth_length,
453 sizeof (WORD));
454 nds_bswap(&tmp->call_id, &hdr->call_id, sizeof (DWORD));
455 }
456
457 /* pdu_scan_offset points to byte 0 of this fragment */
458 nds->pdu_hdr_size = NDR_RSP_HDR_SIZE;
459 nds->pdu_body_offset = nds->pdu_scan_offset + nds->pdu_hdr_size;
460 nds->pdu_body_size = hdr->frag_length - hdr->auth_length -
461 nds->pdu_hdr_size -
462 ((hdr->auth_length != 0) ? SEC_TRAILER_SIZE : 0);
463 }
464
465 /*
466 * Remove an RPC fragment header from the received data stream.
467 *
468 * NDR stream on entry:
469 *
470 * |<--- frag --->|
471 * +-----+--------+-----+--------+-----+---------+-----+
472 * | hdr | data | hdr | data | hdr | data | ... |
473 * +-----+--------+-----+--------+-----+---------+-----+
474 * <----
475 *
476 * NDR stream on return:
477 *
478 * +-----+----------------+-----+---------+-----+
479 * | hdr | data | hdr | data | ... |
480 * +-----+----------------+-----+---------+-----+
481 */
482 void
ndr_remove_frag_hdr(ndr_stream_t * nds)483 ndr_remove_frag_hdr(ndr_stream_t *nds)
484 {
485 char *hdr;
486 char *data;
487 int nbytes;
488
489 hdr = (char *)nds->pdu_base_offset + nds->pdu_scan_offset;
490 data = hdr + NDR_RSP_HDR_SIZE;
491 nbytes = nds->pdu_size - nds->pdu_scan_offset - NDR_RSP_HDR_SIZE;
492
493 /*
494 * Move all of the data after the header back to where the header began.
495 */
496 memmove(hdr, data, nbytes);
497 nds->pdu_size -= NDR_RSP_HDR_SIZE;
498 }
499
500 void
ndr_show_hdr(ndr_common_header_t * hdr)501 ndr_show_hdr(ndr_common_header_t *hdr)
502 {
503 char *fragtype;
504
505 if (hdr == NULL) {
506 ndo_printf(NULL, NULL, "ndr hdr: <null>");
507 return;
508 }
509
510 if (NDR_IS_SINGLE_FRAG(hdr->pfc_flags))
511 fragtype = "single";
512 else if (NDR_IS_FIRST_FRAG(hdr->pfc_flags))
513 fragtype = "first";
514 else if (NDR_IS_LAST_FRAG(hdr->pfc_flags))
515 fragtype = "last";
516 else
517 fragtype = "intermediate";
518
519 ndo_printf(NULL, NULL,
520 "ndr hdr: %d.%d ptype=%d, %s frag (flags=0x%08x) len=%d "
521 "auth_len=%d",
522 hdr->rpc_vers, hdr->rpc_vers_minor, hdr->ptype,
523 fragtype, hdr->pfc_flags, hdr->frag_length, hdr->auth_length);
524 }
525
526 void
ndr_show_auth(ndr_sec_t * auth)527 ndr_show_auth(ndr_sec_t *auth)
528 {
529 if (auth == NULL) {
530 ndo_printf(NULL, NULL, "ndr auth: <null>");
531 return;
532 }
533
534 ndo_printf(NULL, NULL,
535 "ndr auth: type=0x%x, level=0x%x, pad_len=%d, ctx_id=%d",
536 auth->auth_type, auth->auth_level, auth->auth_pad_len,
537 auth->auth_context_id);
538 }
539
540 int
ndr_encode_pdu_hdr(ndr_xa_t * mxa)541 ndr_encode_pdu_hdr(ndr_xa_t *mxa)
542 {
543 ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
544 ndr_stream_t *nds = &mxa->send_nds;
545 int ptype;
546 int rc;
547
548 if (nds->m_op != NDR_M_OP_MARSHALL)
549 return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
550
551 ptype = hdr->ptype;
552 if (ptype == NDR_PTYPE_REQUEST &&
553 (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
554 ptype = NDR_PTYPE_REQUEST_WITH; /* fake for sizing */
555 }
556
557 rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
558
559 return (NDR_DRC_PTYPE_RPCHDR(rc));
560 }
561
562 /*
563 * This is a hand-coded derivative of the automatically generated
564 * (un)marshalling routine for bind_ack headers. bind_ack headers
565 * have an interior conformant array, which is inconsistent with
566 * IDL/NDR rules.
567 */
568 extern struct ndr_typeinfo ndt__uchar;
569 extern struct ndr_typeinfo ndt__ushort;
570 extern struct ndr_typeinfo ndt__ulong;
571
572 int ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref);
573 ndr_typeinfo_t ndt__ndr_bind_ack_hdr = {
574 1, /* NDR version */
575 3, /* alignment */
576 NDR_F_STRUCT, /* flags */
577 ndr__ndr_bind_ack_hdr, /* ndr_func */
578 68, /* pdu_size_fixed_part */
579 0, /* pdu_size_variable_part */
580 68, /* c_size_fixed_part */
581 0, /* c_size_variable_part */
582 };
583
584 /*
585 * [_no_reorder]
586 */
587 int
ndr__ndr_bind_ack_hdr(ndr_ref_t * encl_ref)588 ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref)
589 {
590 ndr_stream_t *nds = encl_ref->stream;
591 struct ndr_bind_ack_hdr *val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
592 (struct ndr_bind_ack_hdr *)encl_ref->datum;
593 ndr_ref_t myref;
594 unsigned long offset;
595
596 bzero(&myref, sizeof (myref));
597 myref.enclosing = encl_ref;
598 myref.stream = encl_ref->stream;
599 myref.packed_alignment = 0;
600
601 /* do all members in order */
602 NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
603 NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
604 NDR_MEMBER(_ushort, max_recv_frag, 18UL);
605 NDR_MEMBER(_ulong, assoc_group_id, 20UL);
606
607 /* port any is the conformant culprit */
608 offset = 24UL;
609
610 switch (nds->m_op) {
611 case NDR_M_OP_MARSHALL:
612 val->sec_addr.length =
613 strlen((char *)val->sec_addr.port_spec) + 1;
614 break;
615
616 case NDR_M_OP_UNMARSHALL:
617 break;
618
619 default:
620 NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
621 return (0);
622 }
623
624 NDR_MEMBER(_ushort, sec_addr.length, offset);
625 NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
626 offset+2UL, val->sec_addr.length);
627
628 offset += 2;
629 offset += val->sec_addr.length;
630 offset += NDR_ALIGN4(offset);
631
632 NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
633 return (1);
634 }
635
636 /*
637 * Assume a single presentation context element in the result list.
638 */
639 unsigned
ndr_bind_ack_hdr_size(ndr_xa_t * mxa)640 ndr_bind_ack_hdr_size(ndr_xa_t *mxa)
641 {
642 ndr_bind_ack_hdr_t *bahdr = &mxa->send_hdr.bind_ack_hdr;
643 unsigned offset;
644 unsigned length;
645
646 /* port any is the conformant culprit */
647 offset = 24UL;
648
649 length = strlen((char *)bahdr->sec_addr.port_spec) + 1;
650
651 offset += 2;
652 offset += length;
653 offset += NDR_ALIGN4(offset);
654 offset += sizeof (ndr_p_result_list_t);
655 return (offset);
656 }
657
658 /*
659 * This is a hand-coded derivative of the automatically generated
660 * (un)marshalling routine for alter_context_rsp headers.
661 * Alter context response headers have an interior conformant array,
662 * which is inconsistent with IDL/NDR rules.
663 */
664 int ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref);
665 ndr_typeinfo_t ndt__ndr_alter_context_rsp_hdr = {
666 1, /* NDR version */
667 3, /* alignment */
668 NDR_F_STRUCT, /* flags */
669 ndr__ndr_alter_context_rsp_hdr, /* ndr_func */
670 56, /* pdu_size_fixed_part */
671 0, /* pdu_size_variable_part */
672 56, /* c_size_fixed_part */
673 0, /* c_size_variable_part */
674 };
675
676 /*
677 * [_no_reorder]
678 */
679 int
ndr__ndr_alter_context_rsp_hdr(ndr_ref_t * encl_ref)680 ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref)
681 {
682 ndr_stream_t *nds = encl_ref->stream;
683 ndr_alter_context_rsp_hdr_t *val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
684 (ndr_alter_context_rsp_hdr_t *)encl_ref->datum;
685 ndr_ref_t myref;
686 unsigned long offset;
687
688 bzero(&myref, sizeof (myref));
689 myref.enclosing = encl_ref;
690 myref.stream = encl_ref->stream;
691 myref.packed_alignment = 0;
692
693 /* do all members in order */
694 NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
695 NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
696 NDR_MEMBER(_ushort, max_recv_frag, 18UL);
697 NDR_MEMBER(_ulong, assoc_group_id, 20UL);
698
699 offset = 24UL; /* offset of sec_addr */
700
701 switch (nds->m_op) {
702 case NDR_M_OP_MARSHALL:
703 val->sec_addr.length = 0;
704 break;
705
706 case NDR_M_OP_UNMARSHALL:
707 break;
708
709 default:
710 NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
711 return (0);
712 }
713
714 NDR_MEMBER(_ushort, sec_addr.length, offset);
715 NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
716 offset+2UL, val->sec_addr.length);
717
718 offset += 2; /* sizeof (sec_addr.length) */
719 offset += NDR_ALIGN4(offset);
720
721 NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
722 return (1);
723 }
724
725 /*
726 * Assume a single presentation context element in the result list.
727 */
728 unsigned
ndr_alter_context_rsp_hdr_size(void)729 ndr_alter_context_rsp_hdr_size(void)
730 {
731 unsigned offset;
732
733 offset = 24UL; /* offset of sec_addr */
734 offset += 2; /* sizeof (sec_addr.length) */
735 offset += NDR_ALIGN4(offset);
736 offset += sizeof (ndr_p_result_list_t);
737 return (offset);
738 }
739
740 /*
741 * This is a hand-coded (un)marshalling routine for auth_verifier_co
742 * (aka ndr_sec_t).
743 *
744 * We need to pretend this structure isn't variably sized, until ndrgen
745 * has been modified to support variable-sized arrays.
746 * Here, we only account for the fixed-size members (8 bytes), plus
747 * a pointer for the C structure.
748 *
749 * We then convert between a pointer to the auth token (auth_value,
750 * allocated here during unmarshall) and a flat, 'fixed'-sized array.
751 */
752
753 int ndr__auth_verifier_co(ndr_ref_t *encl_ref);
754 ndr_typeinfo_t ndt__auth_verifier_co = {
755 1, /* NDR version */
756 3, /* alignment */
757 NDR_F_STRUCT, /* flags */
758 ndr__auth_verifier_co, /* ndr_func */
759 8, /* pdu_size_fixed_part */
760 0, /* pdu_size_variable_part */
761 8 + sizeof (void *), /* c_size_fixed_part */
762 0, /* c_size_variable_part */
763 };
764
765 /*
766 * [_no_reorder]
767 */
768 int
ndr__auth_verifier_co(ndr_ref_t * encl_ref)769 ndr__auth_verifier_co(ndr_ref_t *encl_ref)
770 {
771 ndr_stream_t *nds = encl_ref->stream;
772 ndr_xa_t *mxa = /*LINTED E_BAD_PTR_CAST_ALIGN*/
773 (ndr_xa_t *)encl_ref->datum;
774 ndr_common_header_t *hdr;
775 ndr_ref_t myref;
776 ndr_sec_t *val;
777
778 /*
779 * Assumes scan_offset points to the end of PDU body.
780 * (That's base + frag_len - auth_len - SEC_TRAILER_SIZE)
781 *
782 * At some point, NDRGEN could use struct initializers instead of
783 * bzero() + initialization.
784 */
785 bzero(&myref, sizeof (myref));
786 myref.enclosing = encl_ref;
787 myref.stream = encl_ref->stream;
788
789 switch (nds->m_op) {
790 case NDR_M_OP_MARSHALL:
791 val = &mxa->send_auth;
792 hdr = &mxa->send_hdr.common_hdr;
793 break;
794
795 case NDR_M_OP_UNMARSHALL:
796 val = &mxa->recv_auth;
797 hdr = &mxa->recv_hdr.common_hdr;
798 val->auth_value = (uchar_t *)NDS_MALLOC(nds, hdr->auth_length,
799 encl_ref);
800 break;
801
802 default:
803 NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
804 return (0);
805 }
806
807 /*
808 * ndr_topmost() can't account for auth_length (pdu_scan/end_offset).
809 * This would only matter if any of this struct's members
810 * are treated as 'outer' constructs, but they aren't.
811 */
812 encl_ref->pdu_end_offset += hdr->auth_length;
813 nds->pdu_scan_offset += hdr->auth_length;
814
815 NDR_MEMBER(_uchar, auth_type, 0UL);
816 NDR_MEMBER(_uchar, auth_level, 1UL);
817 NDR_MEMBER(_uchar, auth_pad_len, 2UL);
818 NDR_MEMBER(_uchar, auth_rsvd, 3UL);
819 NDR_MEMBER(_ulong, auth_context_id, 4UL);
820
821 NDR_MEMBER_PTR_WITH_DIMENSION(_uchar, auth_value, 8UL,
822 hdr->auth_length);
823
824 return (1);
825 }
826
827 int
ndr_encode_pdu_auth(ndr_xa_t * mxa)828 ndr_encode_pdu_auth(ndr_xa_t *mxa)
829 {
830 ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
831 ndr_stream_t *nds = &mxa->send_nds;
832 int rc;
833 ulong_t want_size;
834
835 if (nds->m_op != NDR_M_OP_MARSHALL)
836 return (NDR_DRC_FAULT_MODE_MISMATCH);
837
838 if (hdr->auth_length == 0)
839 return (NDR_DRC_OK);
840
841 want_size = nds->pdu_scan_offset + hdr->auth_length + SEC_TRAILER_SIZE;
842
843 /*
844 * Make sure we have space for the sec trailer - the marshaller
845 * doesn't know how large the auth token is.
846 * Note: ndr_add_auth_token() has already added padding.
847 *
848 * NDS_GROW_PDU will adjust pdu_size for us.
849 */
850 if (nds->pdu_max_size < want_size) {
851 if (NDS_GROW_PDU(nds, want_size, NULL) == 0)
852 return (NDR_DRC_FAULT_ENCODE_TOO_BIG);
853 } else {
854 nds->pdu_size = want_size;
855 }
856 rc = ndr_encode_decode_type(nds, &TYPEINFO(auth_verifier_co),
857 mxa);
858
859 return (rc);
860 }
861
862 int
ndr_decode_pdu_auth(ndr_xa_t * mxa)863 ndr_decode_pdu_auth(ndr_xa_t *mxa)
864 {
865 ndr_common_header_t *hdr = &mxa->recv_hdr.common_hdr;
866 ndr_stream_t *nds = &mxa->recv_nds;
867 ndr_sec_t *auth = &mxa->recv_auth;
868 int rc;
869 ulong_t saved_offset;
870 size_t auth_size;
871
872 if (nds->m_op != NDR_M_OP_UNMARSHALL)
873 return (NDR_DRC_FAULT_MODE_MISMATCH);
874
875 mxa->recv_auth.auth_pad_len = 0;
876 if (hdr->auth_length == 0)
877 return (NDR_DRC_OK);
878
879 /*
880 * Save the current offset, and skip to the sec_trailer.
881 * That's located after the (fragment of) stub data and the auth
882 * pad bytes (collectively the 'PDU Body').
883 */
884 saved_offset = nds->pdu_scan_offset;
885 nds->pdu_scan_offset = nds->pdu_body_offset + nds->pdu_body_size;
886
887 /* auth_length is all of the data after the sec_trailer */
888 if (hdr->auth_length >
889 (nds->pdu_size - nds->pdu_scan_offset - SEC_TRAILER_SIZE)) {
890 nds->pdu_scan_offset = saved_offset;
891 return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
892 }
893
894 rc = ndr_encode_decode_type(nds, &TYPEINFO(auth_verifier_co),
895 mxa);
896
897 /*
898 * Reset the scan_offset for call decode processing.
899 * If we were successful, remove the sec trailer and padding
900 * from size accounting.
901 */
902 if (auth->auth_pad_len > nds->pdu_body_size)
903 rc = NDR_DRC_FAULT_RECEIVED_MALFORMED;
904 else if (rc == NDR_DRC_OK) {
905 auth_size = hdr->auth_length + SEC_TRAILER_SIZE +
906 auth->auth_pad_len;
907
908 /*
909 * After the authenticator has been decoded,
910 * pdu_scan_offset points to just after the auth token,
911 * which is the end of the fragment.
912 *
913 * If there's no data after the authenticator, then we
914 * just remove the authenticator from size accounting.
915 * Otherwise, need to memmove() all of that data back to after
916 * the stub data. The data we move starts at the beginning of
917 * the next fragment.
918 */
919 if (nds->pdu_size > nds->pdu_scan_offset) {
920 uchar_t *next_frag_ptr = nds->pdu_base_addr +
921 nds->pdu_scan_offset;
922
923 memmove(next_frag_ptr - auth_size, next_frag_ptr,
924 nds->pdu_size - nds->pdu_scan_offset);
925 }
926
927 nds->pdu_size -= auth_size;
928 }
929 nds->pdu_scan_offset = saved_offset;
930 return (rc);
931 }
932