13299f39fSGordon Ross /*
23299f39fSGordon Ross * CDDL HEADER START
33299f39fSGordon Ross *
43299f39fSGordon Ross * The contents of this file are subject to the terms of the
53299f39fSGordon Ross * Common Development and Distribution License (the "License").
63299f39fSGordon Ross * You may not use this file except in compliance with the License.
73299f39fSGordon Ross *
83299f39fSGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93299f39fSGordon Ross * or http://www.opensolaris.org/os/licensing.
103299f39fSGordon Ross * See the License for the specific language governing permissions
113299f39fSGordon Ross * and limitations under the License.
123299f39fSGordon Ross *
133299f39fSGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
143299f39fSGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153299f39fSGordon Ross * If applicable, add the following below this CDDL HEADER, with the
163299f39fSGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
173299f39fSGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
183299f39fSGordon Ross *
193299f39fSGordon Ross * CDDL HEADER END
203299f39fSGordon Ross */
213299f39fSGordon Ross /*
223299f39fSGordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*4d00d81bSMatt Barden * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
243299f39fSGordon Ross */
253299f39fSGordon Ross
263299f39fSGordon Ross #include <assert.h>
273299f39fSGordon Ross #include <strings.h>
283299f39fSGordon Ross #include <sys/param.h>
29*4d00d81bSMatt Barden #include <sys/debug.h>
303299f39fSGordon Ross
313299f39fSGordon Ross #include <libmlrpc.h>
323299f39fSGordon Ross
333299f39fSGordon Ross #ifdef _BIG_ENDIAN
343299f39fSGordon Ross static const int ndr_native_byte_order = NDR_REPLAB_INTG_BIG_ENDIAN;
353299f39fSGordon Ross #else
363299f39fSGordon Ross static const int ndr_native_byte_order = NDR_REPLAB_INTG_LITTLE_ENDIAN;
373299f39fSGordon Ross #endif
383299f39fSGordon Ross
393299f39fSGordon Ross static int ndr_decode_hdr_common(ndr_stream_t *, ndr_common_header_t *);
403299f39fSGordon Ross static int ndr_decode_pac_hdr(ndr_stream_t *, ndr_pac_hdr_t *);
413299f39fSGordon Ross
42ce8560eeSMatt Barden /*
43ce8560eeSMatt Barden * This is the layout of an RPC PDU, as shown in
44ce8560eeSMatt Barden * [MS-RPCE] 2.2.2.13 "Verification Trailer".
45ce8560eeSMatt Barden *
46ce8560eeSMatt Barden * +-------------------------------+
47ce8560eeSMatt Barden * | PDU Header |
48ce8560eeSMatt Barden * +-------------------------------+ ====
49ce8560eeSMatt Barden * | Stub Data |
50ce8560eeSMatt Barden * +-------------------------------+ PDU
51ce8560eeSMatt Barden * | Stub Padding Octets |
52ce8560eeSMatt Barden * +-------------------------------+ Body
53ce8560eeSMatt Barden * | Verification Trailer |
54ce8560eeSMatt Barden * +-------------------------------+ Here
55ce8560eeSMatt Barden * | Authentication Padding |
56ce8560eeSMatt Barden * +-------------------------------+ ====
57ce8560eeSMatt Barden * | sec_trailer |
58ce8560eeSMatt Barden * +-------------------------------+
59ce8560eeSMatt Barden * | Authentication Token |
60ce8560eeSMatt Barden * +-------------------------------+
61ce8560eeSMatt Barden *
62ce8560eeSMatt Barden * We don't use the "Verification Trailer" for anything yet.
63ce8560eeSMatt Barden * sec_trailer and Authentication Token are for Secure RPC,
64ce8560eeSMatt Barden * and are collectively the 'auth_verifier_co' in DCERPC.
65ce8560eeSMatt Barden *
66ce8560eeSMatt Barden * Each fragment of a multi-fragment response has a unique
67ce8560eeSMatt Barden * header and, if authentication was requested, a unique
68ce8560eeSMatt Barden * sec_trailer.
69ce8560eeSMatt Barden */
70ce8560eeSMatt Barden
713299f39fSGordon Ross static int
ndr_convert_nds_error(ndr_stream_t * nds)72ce8560eeSMatt Barden ndr_convert_nds_error(ndr_stream_t *nds)
733299f39fSGordon Ross {
743299f39fSGordon Ross int rc;
753299f39fSGordon Ross
763299f39fSGordon Ross switch (nds->error) {
773299f39fSGordon Ross case NDR_ERR_MALLOC_FAILED:
783299f39fSGordon Ross rc = NDR_DRC_FAULT_OUT_OF_MEMORY;
793299f39fSGordon Ross break;
803299f39fSGordon Ross
813299f39fSGordon Ross case NDR_ERR_SWITCH_VALUE_INVALID:
823299f39fSGordon Ross rc = NDR_DRC_FAULT_PARAM_0_INVALID;
833299f39fSGordon Ross break;
843299f39fSGordon Ross
853299f39fSGordon Ross case NDR_ERR_UNDERFLOW:
863299f39fSGordon Ross rc = NDR_DRC_FAULT_RECEIVED_RUNT;
873299f39fSGordon Ross break;
883299f39fSGordon Ross
893299f39fSGordon Ross case NDR_ERR_GROW_FAILED:
903299f39fSGordon Ross rc = NDR_DRC_FAULT_ENCODE_TOO_BIG;
913299f39fSGordon Ross break;
923299f39fSGordon Ross
933299f39fSGordon Ross default:
943299f39fSGordon Ross if (nds->m_op == NDR_M_OP_MARSHALL)
953299f39fSGordon Ross rc = NDR_DRC_FAULT_ENCODE_FAILED;
963299f39fSGordon Ross else
973299f39fSGordon Ross rc = NDR_DRC_FAULT_DECODE_FAILED;
983299f39fSGordon Ross break;
993299f39fSGordon Ross }
1003299f39fSGordon Ross
1013299f39fSGordon Ross return (rc);
1023299f39fSGordon Ross }
1033299f39fSGordon Ross
104ce8560eeSMatt Barden static int
ndr_encode_decode_common(ndr_stream_t * nds,unsigned opnum,ndr_typeinfo_t * ti,void * datum)105ce8560eeSMatt Barden ndr_encode_decode_common(ndr_stream_t *nds, unsigned opnum,
106ce8560eeSMatt Barden ndr_typeinfo_t *ti, void *datum)
107ce8560eeSMatt Barden {
108ce8560eeSMatt Barden /*
109ce8560eeSMatt Barden * Perform the (un)marshalling
110ce8560eeSMatt Barden */
111ce8560eeSMatt Barden if (ndo_operation(nds, ti, opnum, datum))
112ce8560eeSMatt Barden return (NDR_DRC_OK);
113ce8560eeSMatt Barden
114ce8560eeSMatt Barden return (ndr_convert_nds_error(nds));
115ce8560eeSMatt Barden }
116ce8560eeSMatt Barden
117ce8560eeSMatt Barden static int
ndr_encode_decode_type(ndr_stream_t * nds,ndr_typeinfo_t * ti,void * datum)118ce8560eeSMatt Barden ndr_encode_decode_type(ndr_stream_t *nds, ndr_typeinfo_t *ti, void *datum)
119ce8560eeSMatt Barden {
120ce8560eeSMatt Barden /*
121ce8560eeSMatt Barden * Perform the (un)marshalling
122ce8560eeSMatt Barden */
123ce8560eeSMatt Barden if (ndo_process(nds, ti, datum))
124ce8560eeSMatt Barden return (NDR_DRC_OK);
125ce8560eeSMatt Barden
126ce8560eeSMatt Barden return (ndr_convert_nds_error(nds));
127ce8560eeSMatt Barden }
128ce8560eeSMatt Barden
1293299f39fSGordon Ross ndr_buf_t *
ndr_buf_init(ndr_typeinfo_t * ti)1303299f39fSGordon Ross ndr_buf_init(ndr_typeinfo_t *ti)
1313299f39fSGordon Ross {
1323299f39fSGordon Ross ndr_buf_t *nbuf;
1333299f39fSGordon Ross
1343299f39fSGordon Ross if ((nbuf = calloc(1, sizeof (ndr_buf_t))) == NULL)
1353299f39fSGordon Ross return (NULL);
1363299f39fSGordon Ross
1373299f39fSGordon Ross if ((nbuf->nb_heap = ndr_heap_create()) == NULL) {
1383299f39fSGordon Ross free(nbuf);
1393299f39fSGordon Ross return (NULL);
1403299f39fSGordon Ross }
1413299f39fSGordon Ross
1423299f39fSGordon Ross nbuf->nb_ti = ti;
1433299f39fSGordon Ross nbuf->nb_magic = NDR_BUF_MAGIC;
1443299f39fSGordon Ross return (nbuf);
1453299f39fSGordon Ross }
1463299f39fSGordon Ross
1473299f39fSGordon Ross void
ndr_buf_fini(ndr_buf_t * nbuf)1483299f39fSGordon Ross ndr_buf_fini(ndr_buf_t *nbuf)
1493299f39fSGordon Ross {
1503299f39fSGordon Ross assert(nbuf->nb_magic == NDR_BUF_MAGIC);
1513299f39fSGordon Ross
1523299f39fSGordon Ross nds_destruct(&nbuf->nb_nds);
1533299f39fSGordon Ross ndr_heap_destroy(nbuf->nb_heap);
1543299f39fSGordon Ross nbuf->nb_magic = 0;
1553299f39fSGordon Ross free(nbuf);
1563299f39fSGordon Ross }
1573299f39fSGordon Ross
1583299f39fSGordon Ross /*
1593299f39fSGordon Ross * Decode an NDR encoded buffer. The buffer is expected to contain
1603299f39fSGordon Ross * a single fragment packet with a valid PDU header followed by NDR
1613299f39fSGordon Ross * encoded data. The structure to which result points should be
1623299f39fSGordon Ross * of the appropriate type to hold the decoded output. For example:
1633299f39fSGordon Ross *
1643299f39fSGordon Ross * pac_info_t info;
1653299f39fSGordon Ross *
1663299f39fSGordon Ross * if ((nbuf = ndr_buf_init(&TYPEINFO(ndr_pac)) != NULL) {
1673299f39fSGordon Ross * rc = ndr_decode_buf(nbuf, opnum, data, datalen, &info);
1683299f39fSGordon Ross * ...
1693299f39fSGordon Ross * ndr_buf_fini(nbuf);
1703299f39fSGordon Ross * }
1713299f39fSGordon Ross */
1723299f39fSGordon Ross int
ndr_buf_decode(ndr_buf_t * nbuf,unsigned hdr_type,unsigned opnum,const char * data,size_t datalen,void * result)1733299f39fSGordon Ross ndr_buf_decode(ndr_buf_t *nbuf, unsigned hdr_type, unsigned opnum,
1743299f39fSGordon Ross const char *data, size_t datalen, void *result)
1753299f39fSGordon Ross {
1763299f39fSGordon Ross ndr_common_header_t hdr;
1773299f39fSGordon Ross ndr_pac_hdr_t pac_hdr;
1783299f39fSGordon Ross unsigned pdu_size_hint;
1793299f39fSGordon Ross int rc;
1803299f39fSGordon Ross
1813299f39fSGordon Ross assert(nbuf->nb_magic == NDR_BUF_MAGIC);
1823299f39fSGordon Ross assert(nbuf->nb_heap != NULL);
1833299f39fSGordon Ross assert(nbuf->nb_ti != NULL);
1843299f39fSGordon Ross
1853299f39fSGordon Ross if (datalen < NDR_PDU_SIZE_HINT_DEFAULT)
1863299f39fSGordon Ross pdu_size_hint = NDR_PDU_SIZE_HINT_DEFAULT;
1873299f39fSGordon Ross else
1883299f39fSGordon Ross pdu_size_hint = datalen;
1893299f39fSGordon Ross
1903299f39fSGordon Ross rc = nds_initialize(&nbuf->nb_nds, pdu_size_hint, NDR_MODE_BUF_DECODE,
1913299f39fSGordon Ross nbuf->nb_heap);
1923299f39fSGordon Ross if (NDR_DRC_IS_FAULT(rc))
1933299f39fSGordon Ross return (rc);
1943299f39fSGordon Ross
1953299f39fSGordon Ross bcopy(data, nbuf->nb_nds.pdu_base_addr, datalen);
196ce8560eeSMatt Barden nbuf->nb_nds.pdu_size = datalen;
1973299f39fSGordon Ross
1983299f39fSGordon Ross switch (hdr_type) {
1993299f39fSGordon Ross case NDR_PTYPE_COMMON:
2003299f39fSGordon Ross rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr);
2013299f39fSGordon Ross if (NDR_DRC_IS_FAULT(rc))
2023299f39fSGordon Ross return (rc);
2033299f39fSGordon Ross
2043299f39fSGordon Ross if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags))
2053299f39fSGordon Ross return (NDR_DRC_FAULT_DECODE_FAILED);
2063299f39fSGordon Ross break;
2073299f39fSGordon Ross
2083299f39fSGordon Ross case NDR_PTYPE_PAC:
2093299f39fSGordon Ross rc = ndr_decode_pac_hdr(&nbuf->nb_nds, &pac_hdr);
2103299f39fSGordon Ross if (NDR_DRC_IS_FAULT(rc))
2113299f39fSGordon Ross return (rc);
2123299f39fSGordon Ross
2133299f39fSGordon Ross if (pac_hdr.common_hdr.hdrlen != sizeof (ndr_serialtype1_hdr_t))
2143299f39fSGordon Ross return (NDR_DRC_FAULT_DECODE_FAILED);
2153299f39fSGordon Ross break;
2163299f39fSGordon Ross
2173299f39fSGordon Ross default:
2183299f39fSGordon Ross return (NDR_ERR_UNIMPLEMENTED);
2193299f39fSGordon Ross }
2203299f39fSGordon Ross
2213299f39fSGordon Ross rc = ndr_encode_decode_common(&nbuf->nb_nds, opnum, nbuf->nb_ti,
2223299f39fSGordon Ross result);
2233299f39fSGordon Ross return (rc);
2243299f39fSGordon Ross }
2253299f39fSGordon Ross
2263299f39fSGordon Ross /*
2273299f39fSGordon Ross * Use the receive stream to unmarshall data (NDR_MODE_CALL_RECV).
2283299f39fSGordon Ross */
2293299f39fSGordon Ross int
ndr_decode_call(ndr_xa_t * mxa,void * params)2303299f39fSGordon Ross ndr_decode_call(ndr_xa_t *mxa, void *params)
2313299f39fSGordon Ross {
2323299f39fSGordon Ross ndr_stream_t *nds = &mxa->recv_nds;
2333299f39fSGordon Ross int rc;
2343299f39fSGordon Ross
2353299f39fSGordon Ross if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_RECV))
2363299f39fSGordon Ross return (NDR_DRC_FAULT_MODE_MISMATCH);
2373299f39fSGordon Ross
2383299f39fSGordon Ross rc = ndr_encode_decode_common(nds, mxa->opnum,
2393299f39fSGordon Ross mxa->binding->service->interface_ti, params);
2403299f39fSGordon Ross
2413299f39fSGordon Ross return (rc + NDR_PTYPE_REQUEST);
2423299f39fSGordon Ross }
2433299f39fSGordon Ross
2443299f39fSGordon Ross /*
2453299f39fSGordon Ross * Use the send stream to marshall data (NDR_MODE_RETURN_SEND).
2463299f39fSGordon Ross */
2473299f39fSGordon Ross int
ndr_encode_return(ndr_xa_t * mxa,void * params)2483299f39fSGordon Ross ndr_encode_return(ndr_xa_t *mxa, void *params)
2493299f39fSGordon Ross {
2503299f39fSGordon Ross ndr_stream_t *nds = &mxa->send_nds;
2513299f39fSGordon Ross int rc;
2523299f39fSGordon Ross
2533299f39fSGordon Ross if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND))
2543299f39fSGordon Ross return (NDR_DRC_FAULT_MODE_MISMATCH);
2553299f39fSGordon Ross
2563299f39fSGordon Ross rc = ndr_encode_decode_common(nds, mxa->opnum,
2573299f39fSGordon Ross mxa->binding->service->interface_ti, params);
2583299f39fSGordon Ross
2593299f39fSGordon Ross return (rc + NDR_PTYPE_RESPONSE);
2603299f39fSGordon Ross }
2613299f39fSGordon Ross
2623299f39fSGordon Ross /*
2633299f39fSGordon Ross * Use the send stream to marshall data (NDR_MODE_CALL_SEND).
2643299f39fSGordon Ross */
2653299f39fSGordon Ross int
ndr_encode_call(ndr_xa_t * mxa,void * params)2663299f39fSGordon Ross ndr_encode_call(ndr_xa_t *mxa, void *params)
2673299f39fSGordon Ross {
2683299f39fSGordon Ross ndr_stream_t *nds = &mxa->send_nds;
2693299f39fSGordon Ross int rc;
2703299f39fSGordon Ross
2713299f39fSGordon Ross if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_SEND))
2723299f39fSGordon Ross return (NDR_DRC_FAULT_MODE_MISMATCH);
2733299f39fSGordon Ross
2743299f39fSGordon Ross rc = ndr_encode_decode_common(nds, mxa->opnum,
2753299f39fSGordon Ross mxa->binding->service->interface_ti, params);
2763299f39fSGordon Ross
2773299f39fSGordon Ross return (rc + NDR_PTYPE_REQUEST);
2783299f39fSGordon Ross }
2793299f39fSGordon Ross
2803299f39fSGordon Ross /*
2813299f39fSGordon Ross * Use the receive stream to unmarshall data (NDR_MODE_RETURN_RECV).
2823299f39fSGordon Ross */
2833299f39fSGordon Ross int
ndr_decode_return(ndr_xa_t * mxa,void * params)2843299f39fSGordon Ross ndr_decode_return(ndr_xa_t *mxa, void *params)
2853299f39fSGordon Ross {
2863299f39fSGordon Ross ndr_stream_t *nds = &mxa->recv_nds;
2873299f39fSGordon Ross int rc;
2883299f39fSGordon Ross
2893299f39fSGordon Ross if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_RECV))
2903299f39fSGordon Ross return (NDR_DRC_FAULT_MODE_MISMATCH);
2913299f39fSGordon Ross
2923299f39fSGordon Ross rc = ndr_encode_decode_common(nds, mxa->opnum,
2933299f39fSGordon Ross mxa->binding->service->interface_ti, params);
2943299f39fSGordon Ross
2953299f39fSGordon Ross return (rc + NDR_PTYPE_RESPONSE);
2963299f39fSGordon Ross }
2973299f39fSGordon Ross
2983299f39fSGordon Ross int
ndr_decode_pdu_hdr(ndr_xa_t * mxa)2993299f39fSGordon Ross ndr_decode_pdu_hdr(ndr_xa_t *mxa)
3003299f39fSGordon Ross {
3013299f39fSGordon Ross ndr_common_header_t *hdr = &mxa->recv_hdr.common_hdr;
3023299f39fSGordon Ross ndr_stream_t *nds = &mxa->recv_nds;
3033299f39fSGordon Ross int rc;
304ce8560eeSMatt Barden ulong_t saved_offset;
3053299f39fSGordon Ross
306ce8560eeSMatt Barden saved_offset = nds->pdu_scan_offset;
3073299f39fSGordon Ross rc = ndr_decode_hdr_common(nds, hdr);
3083299f39fSGordon Ross if (NDR_DRC_IS_FAULT(rc))
3093299f39fSGordon Ross return (rc);
3103299f39fSGordon Ross
3113299f39fSGordon Ross /*
3123299f39fSGordon Ross * Verify the protocol version.
3133299f39fSGordon Ross */
3143299f39fSGordon Ross if ((hdr->rpc_vers != 5) || (hdr->rpc_vers_minor != 0))
3153299f39fSGordon Ross return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
3163299f39fSGordon Ross
3173299f39fSGordon Ross mxa->ptype = hdr->ptype;
318ce8560eeSMatt Barden /* pdu_scan_offset now points to (this fragment's) stub data */
319ce8560eeSMatt Barden nds->pdu_body_offset = nds->pdu_scan_offset;
320ce8560eeSMatt Barden nds->pdu_hdr_size = nds->pdu_scan_offset - saved_offset;
321ce8560eeSMatt Barden nds->pdu_body_size = hdr->frag_length - hdr->auth_length -
322ce8560eeSMatt Barden nds->pdu_hdr_size -
323ce8560eeSMatt Barden ((hdr->auth_length != 0) ? SEC_TRAILER_SIZE : 0);
324ce8560eeSMatt Barden
325ce8560eeSMatt Barden if (hdr->auth_length != 0 && hdr->auth_length >
326ce8560eeSMatt Barden (hdr->frag_length - nds->pdu_hdr_size - SEC_TRAILER_SIZE))
327ce8560eeSMatt Barden return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
3283299f39fSGordon Ross return (NDR_DRC_OK);
3293299f39fSGordon Ross }
3303299f39fSGordon Ross
3313299f39fSGordon Ross static int
ndr_decode_hdr_common(ndr_stream_t * nds,ndr_common_header_t * hdr)3323299f39fSGordon Ross ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr)
3333299f39fSGordon Ross {
3343299f39fSGordon Ross int ptype;
3353299f39fSGordon Ross int rc;
3363299f39fSGordon Ross int charset;
3373299f39fSGordon Ross int byte_order;
338ce8560eeSMatt Barden ulong_t saved_offset;
3393299f39fSGordon Ross
3403299f39fSGordon Ross if (nds->m_op != NDR_M_OP_UNMARSHALL)
3413299f39fSGordon Ross return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
3423299f39fSGordon Ross
3433299f39fSGordon Ross /*
3443299f39fSGordon Ross * All PDU headers are at least this big
3453299f39fSGordon Ross */
346ce8560eeSMatt Barden saved_offset = nds->pdu_scan_offset;
347ce8560eeSMatt Barden if ((nds->pdu_size - saved_offset) < sizeof (ndr_common_header_t))
3483299f39fSGordon Ross return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
3493299f39fSGordon Ross
3503299f39fSGordon Ross /*
3513299f39fSGordon Ross * Peek at the first eight bytes to figure out what we're doing.
3523299f39fSGordon Ross */
3533299f39fSGordon Ross rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
3543299f39fSGordon Ross if (!rc)
3553299f39fSGordon Ross return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
3563299f39fSGordon Ross
3573299f39fSGordon Ross /*
3583299f39fSGordon Ross * Check for ASCII as the character set. This is an ASCII
3593299f39fSGordon Ross * versus EBCDIC option and has nothing to do with Unicode.
3603299f39fSGordon Ross */
3613299f39fSGordon Ross charset = hdr->packed_drep.intg_char_rep & NDR_REPLAB_CHAR_MASK;
3623299f39fSGordon Ross if (charset != NDR_REPLAB_CHAR_ASCII)
3633299f39fSGordon Ross return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
3643299f39fSGordon Ross
3653299f39fSGordon Ross /*
3663299f39fSGordon Ross * Set the byte swap flag if the PDU byte-order
3673299f39fSGordon Ross * is different from the local byte-order.
3683299f39fSGordon Ross */
3693299f39fSGordon Ross byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
3703299f39fSGordon Ross nds->swap = (byte_order != ndr_native_byte_order) ? 1 : 0;
3713299f39fSGordon Ross
3723299f39fSGordon Ross ptype = hdr->ptype;
3733299f39fSGordon Ross if (ptype == NDR_PTYPE_REQUEST &&
3743299f39fSGordon Ross (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
3753299f39fSGordon Ross ptype = NDR_PTYPE_REQUEST_WITH; /* fake for sizing */
3763299f39fSGordon Ross }
3773299f39fSGordon Ross
3783299f39fSGordon Ross rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
3793299f39fSGordon Ross
380ce8560eeSMatt Barden if (hdr->frag_length > (nds->pdu_size - saved_offset))
381ce8560eeSMatt Barden rc = NDR_DRC_FAULT_RECEIVED_MALFORMED;
3823299f39fSGordon Ross return (NDR_DRC_PTYPE_RPCHDR(rc));
3833299f39fSGordon Ross }
3843299f39fSGordon Ross
3853299f39fSGordon Ross static int
ndr_decode_pac_hdr(ndr_stream_t * nds,ndr_pac_hdr_t * hdr)3863299f39fSGordon Ross ndr_decode_pac_hdr(ndr_stream_t *nds, ndr_pac_hdr_t *hdr)
3873299f39fSGordon Ross {
3883299f39fSGordon Ross int rc;
3893299f39fSGordon Ross
3903299f39fSGordon Ross if (nds->m_op != NDR_M_OP_UNMARSHALL)
3913299f39fSGordon Ross return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
3923299f39fSGordon Ross
3933299f39fSGordon Ross /*
3943299f39fSGordon Ross * All PDU headers are at least this big
3953299f39fSGordon Ross */
396ce8560eeSMatt Barden if ((nds->pdu_size - nds->pdu_scan_offset) < sizeof (ndr_pac_hdr_t))
3973299f39fSGordon Ross return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
3983299f39fSGordon Ross
3993299f39fSGordon Ross /*
4003299f39fSGordon Ross * Peek at the first eight bytes to figure out what we're doing.
4013299f39fSGordon Ross */
4023299f39fSGordon Ross rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
4033299f39fSGordon Ross if (!rc)
4043299f39fSGordon Ross return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
4053299f39fSGordon Ross
4063299f39fSGordon Ross /* Must be set to 1 to indicate type serialization version 1. */
4073299f39fSGordon Ross if (hdr->common_hdr.version != 1)
4083299f39fSGordon Ross return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
4093299f39fSGordon Ross
4103299f39fSGordon Ross /*
4113299f39fSGordon Ross * Set the byte swap flag if the PDU byte-order
4123299f39fSGordon Ross * is different from the local byte-order.
4133299f39fSGordon Ross */
4143299f39fSGordon Ross nds->swap =
4153299f39fSGordon Ross (hdr->common_hdr.endianness != ndr_native_byte_order) ? 1 : 0;
4163299f39fSGordon Ross
4173299f39fSGordon Ross rc = ndr_encode_decode_common(nds, NDR_PTYPE_PAC,
4183299f39fSGordon Ross &TYPEINFO(ndr_hdr), hdr);
4193299f39fSGordon Ross
4203299f39fSGordon Ross return (NDR_DRC_PTYPE_RPCHDR(rc));
4213299f39fSGordon Ross }
4223299f39fSGordon Ross
423*4d00d81bSMatt Barden CTASSERT(sizeof (ndr_common_header_t) >= NDR_CMN_HDR_SIZE);
424*4d00d81bSMatt Barden
4253299f39fSGordon Ross /*
4263299f39fSGordon Ross * Decode an RPC fragment header. Use ndr_decode_pdu_hdr() to process
4273299f39fSGordon Ross * the first fragment header then this function to process additional
4283299f39fSGordon Ross * fragment headers.
4293299f39fSGordon Ross */
4303299f39fSGordon Ross void
ndr_decode_frag_hdr(ndr_stream_t * nds,ndr_common_header_t * hdr)4313299f39fSGordon Ross ndr_decode_frag_hdr(ndr_stream_t *nds, ndr_common_header_t *hdr)
4323299f39fSGordon Ross {
4333299f39fSGordon Ross ndr_common_header_t *tmp;
4343299f39fSGordon Ross uint8_t *pdu;
4353299f39fSGordon Ross int byte_order;
4363299f39fSGordon Ross
4373299f39fSGordon Ross pdu = (uint8_t *)nds->pdu_base_offset + nds->pdu_scan_offset;
438*4d00d81bSMatt Barden bcopy(pdu, hdr, NDR_CMN_HDR_SIZE);
4393299f39fSGordon Ross
4403299f39fSGordon Ross /*
4413299f39fSGordon Ross * Swap non-byte fields if the PDU byte-order
4423299f39fSGordon Ross * is different from the local byte-order.
4433299f39fSGordon Ross */
4443299f39fSGordon Ross byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
4453299f39fSGordon Ross
4463299f39fSGordon Ross if (byte_order != ndr_native_byte_order) {
4473299f39fSGordon Ross /*LINTED E_BAD_PTR_CAST_ALIGN*/
4483299f39fSGordon Ross tmp = (ndr_common_header_t *)pdu;
4493299f39fSGordon Ross
4503299f39fSGordon Ross nds_bswap(&tmp->frag_length, &hdr->frag_length,
4513299f39fSGordon Ross sizeof (WORD));
4523299f39fSGordon Ross nds_bswap(&tmp->auth_length, &hdr->auth_length,
4533299f39fSGordon Ross sizeof (WORD));
4543299f39fSGordon Ross nds_bswap(&tmp->call_id, &hdr->call_id, sizeof (DWORD));
4553299f39fSGordon Ross }
456ce8560eeSMatt Barden
457ce8560eeSMatt Barden /* pdu_scan_offset points to byte 0 of this fragment */
458ce8560eeSMatt Barden nds->pdu_hdr_size = NDR_RSP_HDR_SIZE;
459ce8560eeSMatt Barden nds->pdu_body_offset = nds->pdu_scan_offset + nds->pdu_hdr_size;
460ce8560eeSMatt Barden nds->pdu_body_size = hdr->frag_length - hdr->auth_length -
461ce8560eeSMatt Barden nds->pdu_hdr_size -
462ce8560eeSMatt Barden ((hdr->auth_length != 0) ? SEC_TRAILER_SIZE : 0);
4633299f39fSGordon Ross }
4643299f39fSGordon Ross
4653299f39fSGordon Ross /*
4663299f39fSGordon Ross * Remove an RPC fragment header from the received data stream.
4673299f39fSGordon Ross *
4683299f39fSGordon Ross * NDR stream on entry:
4693299f39fSGordon Ross *
4703299f39fSGordon Ross * |<--- frag --->|
4713299f39fSGordon Ross * +-----+--------+-----+--------+-----+---------+-----+
4723299f39fSGordon Ross * | hdr | data | hdr | data | hdr | data | ... |
4733299f39fSGordon Ross * +-----+--------+-----+--------+-----+---------+-----+
4743299f39fSGordon Ross * <----
4753299f39fSGordon Ross *
4763299f39fSGordon Ross * NDR stream on return:
4773299f39fSGordon Ross *
4783299f39fSGordon Ross * +-----+----------------+-----+---------+-----+
4793299f39fSGordon Ross * | hdr | data | hdr | data | ... |
4803299f39fSGordon Ross * +-----+----------------+-----+---------+-----+
4813299f39fSGordon Ross */
4823299f39fSGordon Ross void
ndr_remove_frag_hdr(ndr_stream_t * nds)4833299f39fSGordon Ross ndr_remove_frag_hdr(ndr_stream_t *nds)
4843299f39fSGordon Ross {
4853299f39fSGordon Ross char *hdr;
4863299f39fSGordon Ross char *data;
4873299f39fSGordon Ross int nbytes;
4883299f39fSGordon Ross
4893299f39fSGordon Ross hdr = (char *)nds->pdu_base_offset + nds->pdu_scan_offset;
4903299f39fSGordon Ross data = hdr + NDR_RSP_HDR_SIZE;
4913299f39fSGordon Ross nbytes = nds->pdu_size - nds->pdu_scan_offset - NDR_RSP_HDR_SIZE;
4923299f39fSGordon Ross
493ce8560eeSMatt Barden /*
494ce8560eeSMatt Barden * Move all of the data after the header back to where the header began.
495ce8560eeSMatt Barden */
496ce8560eeSMatt Barden memmove(hdr, data, nbytes);
4973299f39fSGordon Ross nds->pdu_size -= NDR_RSP_HDR_SIZE;
4983299f39fSGordon Ross }
4993299f39fSGordon Ross
5003299f39fSGordon Ross void
ndr_show_hdr(ndr_common_header_t * hdr)5013299f39fSGordon Ross ndr_show_hdr(ndr_common_header_t *hdr)
5023299f39fSGordon Ross {
5033299f39fSGordon Ross char *fragtype;
5043299f39fSGordon Ross
5053299f39fSGordon Ross if (hdr == NULL) {
5063299f39fSGordon Ross ndo_printf(NULL, NULL, "ndr hdr: <null>");
5073299f39fSGordon Ross return;
5083299f39fSGordon Ross }
5093299f39fSGordon Ross
5103299f39fSGordon Ross if (NDR_IS_SINGLE_FRAG(hdr->pfc_flags))
5113299f39fSGordon Ross fragtype = "single";
5123299f39fSGordon Ross else if (NDR_IS_FIRST_FRAG(hdr->pfc_flags))
5133299f39fSGordon Ross fragtype = "first";
5143299f39fSGordon Ross else if (NDR_IS_LAST_FRAG(hdr->pfc_flags))
5153299f39fSGordon Ross fragtype = "last";
5163299f39fSGordon Ross else
5173299f39fSGordon Ross fragtype = "intermediate";
5183299f39fSGordon Ross
5193299f39fSGordon Ross ndo_printf(NULL, NULL,
520ce8560eeSMatt Barden "ndr hdr: %d.%d ptype=%d, %s frag (flags=0x%08x) len=%d "
521ce8560eeSMatt Barden "auth_len=%d",
5223299f39fSGordon Ross hdr->rpc_vers, hdr->rpc_vers_minor, hdr->ptype,
523ce8560eeSMatt Barden fragtype, hdr->pfc_flags, hdr->frag_length, hdr->auth_length);
524ce8560eeSMatt Barden }
525ce8560eeSMatt Barden
526ce8560eeSMatt Barden void
ndr_show_auth(ndr_sec_t * auth)527ce8560eeSMatt Barden ndr_show_auth(ndr_sec_t *auth)
528ce8560eeSMatt Barden {
529ce8560eeSMatt Barden if (auth == NULL) {
530ce8560eeSMatt Barden ndo_printf(NULL, NULL, "ndr auth: <null>");
531ce8560eeSMatt Barden return;
532ce8560eeSMatt Barden }
533ce8560eeSMatt Barden
534ce8560eeSMatt Barden ndo_printf(NULL, NULL,
535ce8560eeSMatt Barden "ndr auth: type=0x%x, level=0x%x, pad_len=%d, ctx_id=%d",
536ce8560eeSMatt Barden auth->auth_type, auth->auth_level, auth->auth_pad_len,
537ce8560eeSMatt Barden auth->auth_context_id);
5383299f39fSGordon Ross }
5393299f39fSGordon Ross
5403299f39fSGordon Ross int
ndr_encode_pdu_hdr(ndr_xa_t * mxa)5413299f39fSGordon Ross ndr_encode_pdu_hdr(ndr_xa_t *mxa)
5423299f39fSGordon Ross {
5433299f39fSGordon Ross ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
5443299f39fSGordon Ross ndr_stream_t *nds = &mxa->send_nds;
5453299f39fSGordon Ross int ptype;
5463299f39fSGordon Ross int rc;
5473299f39fSGordon Ross
5483299f39fSGordon Ross if (nds->m_op != NDR_M_OP_MARSHALL)
5493299f39fSGordon Ross return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
5503299f39fSGordon Ross
5513299f39fSGordon Ross ptype = hdr->ptype;
5523299f39fSGordon Ross if (ptype == NDR_PTYPE_REQUEST &&
5533299f39fSGordon Ross (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
5543299f39fSGordon Ross ptype = NDR_PTYPE_REQUEST_WITH; /* fake for sizing */
5553299f39fSGordon Ross }
5563299f39fSGordon Ross
5573299f39fSGordon Ross rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
5583299f39fSGordon Ross
5593299f39fSGordon Ross return (NDR_DRC_PTYPE_RPCHDR(rc));
5603299f39fSGordon Ross }
5613299f39fSGordon Ross
5623299f39fSGordon Ross /*
5633299f39fSGordon Ross * This is a hand-coded derivative of the automatically generated
5643299f39fSGordon Ross * (un)marshalling routine for bind_ack headers. bind_ack headers
5653299f39fSGordon Ross * have an interior conformant array, which is inconsistent with
5663299f39fSGordon Ross * IDL/NDR rules.
5673299f39fSGordon Ross */
5683299f39fSGordon Ross extern struct ndr_typeinfo ndt__uchar;
5693299f39fSGordon Ross extern struct ndr_typeinfo ndt__ushort;
5703299f39fSGordon Ross extern struct ndr_typeinfo ndt__ulong;
5713299f39fSGordon Ross
5723299f39fSGordon Ross int ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref);
5733299f39fSGordon Ross ndr_typeinfo_t ndt__ndr_bind_ack_hdr = {
5743299f39fSGordon Ross 1, /* NDR version */
5753299f39fSGordon Ross 3, /* alignment */
5763299f39fSGordon Ross NDR_F_STRUCT, /* flags */
5773299f39fSGordon Ross ndr__ndr_bind_ack_hdr, /* ndr_func */
5783299f39fSGordon Ross 68, /* pdu_size_fixed_part */
5793299f39fSGordon Ross 0, /* pdu_size_variable_part */
5803299f39fSGordon Ross 68, /* c_size_fixed_part */
5813299f39fSGordon Ross 0, /* c_size_variable_part */
5823299f39fSGordon Ross };
5833299f39fSGordon Ross
5843299f39fSGordon Ross /*
5853299f39fSGordon Ross * [_no_reorder]
5863299f39fSGordon Ross */
5873299f39fSGordon Ross int
ndr__ndr_bind_ack_hdr(ndr_ref_t * encl_ref)5883299f39fSGordon Ross ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref)
5893299f39fSGordon Ross {
5903299f39fSGordon Ross ndr_stream_t *nds = encl_ref->stream;
5913299f39fSGordon Ross struct ndr_bind_ack_hdr *val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
5923299f39fSGordon Ross (struct ndr_bind_ack_hdr *)encl_ref->datum;
5933299f39fSGordon Ross ndr_ref_t myref;
5943299f39fSGordon Ross unsigned long offset;
5953299f39fSGordon Ross
5963299f39fSGordon Ross bzero(&myref, sizeof (myref));
5973299f39fSGordon Ross myref.enclosing = encl_ref;
5983299f39fSGordon Ross myref.stream = encl_ref->stream;
5993299f39fSGordon Ross myref.packed_alignment = 0;
6003299f39fSGordon Ross
6013299f39fSGordon Ross /* do all members in order */
6023299f39fSGordon Ross NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
6033299f39fSGordon Ross NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
6043299f39fSGordon Ross NDR_MEMBER(_ushort, max_recv_frag, 18UL);
6053299f39fSGordon Ross NDR_MEMBER(_ulong, assoc_group_id, 20UL);
6063299f39fSGordon Ross
6073299f39fSGordon Ross /* port any is the conformant culprit */
6083299f39fSGordon Ross offset = 24UL;
6093299f39fSGordon Ross
6103299f39fSGordon Ross switch (nds->m_op) {
6113299f39fSGordon Ross case NDR_M_OP_MARSHALL:
6123299f39fSGordon Ross val->sec_addr.length =
6133299f39fSGordon Ross strlen((char *)val->sec_addr.port_spec) + 1;
6143299f39fSGordon Ross break;
6153299f39fSGordon Ross
6163299f39fSGordon Ross case NDR_M_OP_UNMARSHALL:
6173299f39fSGordon Ross break;
6183299f39fSGordon Ross
6193299f39fSGordon Ross default:
6203299f39fSGordon Ross NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
6213299f39fSGordon Ross return (0);
6223299f39fSGordon Ross }
6233299f39fSGordon Ross
6243299f39fSGordon Ross NDR_MEMBER(_ushort, sec_addr.length, offset);
6253299f39fSGordon Ross NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
6263299f39fSGordon Ross offset+2UL, val->sec_addr.length);
6273299f39fSGordon Ross
6283299f39fSGordon Ross offset += 2;
6293299f39fSGordon Ross offset += val->sec_addr.length;
6303299f39fSGordon Ross offset += NDR_ALIGN4(offset);
6313299f39fSGordon Ross
6323299f39fSGordon Ross NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
6333299f39fSGordon Ross return (1);
6343299f39fSGordon Ross }
6353299f39fSGordon Ross
6363299f39fSGordon Ross /*
6373299f39fSGordon Ross * Assume a single presentation context element in the result list.
6383299f39fSGordon Ross */
6393299f39fSGordon Ross unsigned
ndr_bind_ack_hdr_size(ndr_xa_t * mxa)6403299f39fSGordon Ross ndr_bind_ack_hdr_size(ndr_xa_t *mxa)
6413299f39fSGordon Ross {
6423299f39fSGordon Ross ndr_bind_ack_hdr_t *bahdr = &mxa->send_hdr.bind_ack_hdr;
6433299f39fSGordon Ross unsigned offset;
6443299f39fSGordon Ross unsigned length;
6453299f39fSGordon Ross
6463299f39fSGordon Ross /* port any is the conformant culprit */
6473299f39fSGordon Ross offset = 24UL;
6483299f39fSGordon Ross
6493299f39fSGordon Ross length = strlen((char *)bahdr->sec_addr.port_spec) + 1;
6503299f39fSGordon Ross
6513299f39fSGordon Ross offset += 2;
6523299f39fSGordon Ross offset += length;
6533299f39fSGordon Ross offset += NDR_ALIGN4(offset);
6543299f39fSGordon Ross offset += sizeof (ndr_p_result_list_t);
6553299f39fSGordon Ross return (offset);
6563299f39fSGordon Ross }
6573299f39fSGordon Ross
6583299f39fSGordon Ross /*
6593299f39fSGordon Ross * This is a hand-coded derivative of the automatically generated
6603299f39fSGordon Ross * (un)marshalling routine for alter_context_rsp headers.
6613299f39fSGordon Ross * Alter context response headers have an interior conformant array,
6623299f39fSGordon Ross * which is inconsistent with IDL/NDR rules.
6633299f39fSGordon Ross */
6643299f39fSGordon Ross int ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref);
6653299f39fSGordon Ross ndr_typeinfo_t ndt__ndr_alter_context_rsp_hdr = {
6663299f39fSGordon Ross 1, /* NDR version */
6673299f39fSGordon Ross 3, /* alignment */
6683299f39fSGordon Ross NDR_F_STRUCT, /* flags */
6693299f39fSGordon Ross ndr__ndr_alter_context_rsp_hdr, /* ndr_func */
6703299f39fSGordon Ross 56, /* pdu_size_fixed_part */
6713299f39fSGordon Ross 0, /* pdu_size_variable_part */
6723299f39fSGordon Ross 56, /* c_size_fixed_part */
6733299f39fSGordon Ross 0, /* c_size_variable_part */
6743299f39fSGordon Ross };
6753299f39fSGordon Ross
6763299f39fSGordon Ross /*
6773299f39fSGordon Ross * [_no_reorder]
6783299f39fSGordon Ross */
6793299f39fSGordon Ross int
ndr__ndr_alter_context_rsp_hdr(ndr_ref_t * encl_ref)6803299f39fSGordon Ross ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref)
6813299f39fSGordon Ross {
6823299f39fSGordon Ross ndr_stream_t *nds = encl_ref->stream;
6833299f39fSGordon Ross ndr_alter_context_rsp_hdr_t *val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
6843299f39fSGordon Ross (ndr_alter_context_rsp_hdr_t *)encl_ref->datum;
6853299f39fSGordon Ross ndr_ref_t myref;
6863299f39fSGordon Ross unsigned long offset;
6873299f39fSGordon Ross
6883299f39fSGordon Ross bzero(&myref, sizeof (myref));
6893299f39fSGordon Ross myref.enclosing = encl_ref;
6903299f39fSGordon Ross myref.stream = encl_ref->stream;
6913299f39fSGordon Ross myref.packed_alignment = 0;
6923299f39fSGordon Ross
6933299f39fSGordon Ross /* do all members in order */
6943299f39fSGordon Ross NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
6953299f39fSGordon Ross NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
6963299f39fSGordon Ross NDR_MEMBER(_ushort, max_recv_frag, 18UL);
6973299f39fSGordon Ross NDR_MEMBER(_ulong, assoc_group_id, 20UL);
6983299f39fSGordon Ross
6993299f39fSGordon Ross offset = 24UL; /* offset of sec_addr */
7003299f39fSGordon Ross
7013299f39fSGordon Ross switch (nds->m_op) {
7023299f39fSGordon Ross case NDR_M_OP_MARSHALL:
7033299f39fSGordon Ross val->sec_addr.length = 0;
7043299f39fSGordon Ross break;
7053299f39fSGordon Ross
7063299f39fSGordon Ross case NDR_M_OP_UNMARSHALL:
7073299f39fSGordon Ross break;
7083299f39fSGordon Ross
7093299f39fSGordon Ross default:
7103299f39fSGordon Ross NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
7113299f39fSGordon Ross return (0);
7123299f39fSGordon Ross }
7133299f39fSGordon Ross
7143299f39fSGordon Ross NDR_MEMBER(_ushort, sec_addr.length, offset);
7153299f39fSGordon Ross NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
7163299f39fSGordon Ross offset+2UL, val->sec_addr.length);
7173299f39fSGordon Ross
7183299f39fSGordon Ross offset += 2; /* sizeof (sec_addr.length) */
7193299f39fSGordon Ross offset += NDR_ALIGN4(offset);
7203299f39fSGordon Ross
7213299f39fSGordon Ross NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
7223299f39fSGordon Ross return (1);
7233299f39fSGordon Ross }
7243299f39fSGordon Ross
7253299f39fSGordon Ross /*
7263299f39fSGordon Ross * Assume a single presentation context element in the result list.
7273299f39fSGordon Ross */
7283299f39fSGordon Ross unsigned
ndr_alter_context_rsp_hdr_size(void)7293299f39fSGordon Ross ndr_alter_context_rsp_hdr_size(void)
7303299f39fSGordon Ross {
7313299f39fSGordon Ross unsigned offset;
7323299f39fSGordon Ross
7333299f39fSGordon Ross offset = 24UL; /* offset of sec_addr */
7343299f39fSGordon Ross offset += 2; /* sizeof (sec_addr.length) */
7353299f39fSGordon Ross offset += NDR_ALIGN4(offset);
7363299f39fSGordon Ross offset += sizeof (ndr_p_result_list_t);
7373299f39fSGordon Ross return (offset);
7383299f39fSGordon Ross }
739ce8560eeSMatt Barden
740ce8560eeSMatt Barden /*
741ce8560eeSMatt Barden * This is a hand-coded (un)marshalling routine for auth_verifier_co
742ce8560eeSMatt Barden * (aka ndr_sec_t).
743ce8560eeSMatt Barden *
744ce8560eeSMatt Barden * We need to pretend this structure isn't variably sized, until ndrgen
745ce8560eeSMatt Barden * has been modified to support variable-sized arrays.
746ce8560eeSMatt Barden * Here, we only account for the fixed-size members (8 bytes), plus
747ce8560eeSMatt Barden * a pointer for the C structure.
748ce8560eeSMatt Barden *
749ce8560eeSMatt Barden * We then convert between a pointer to the auth token (auth_value,
750ce8560eeSMatt Barden * allocated here during unmarshall) and a flat, 'fixed'-sized array.
751ce8560eeSMatt Barden */
752ce8560eeSMatt Barden
753ce8560eeSMatt Barden int ndr__auth_verifier_co(ndr_ref_t *encl_ref);
754ce8560eeSMatt Barden ndr_typeinfo_t ndt__auth_verifier_co = {
755ce8560eeSMatt Barden 1, /* NDR version */
756ce8560eeSMatt Barden 3, /* alignment */
757ce8560eeSMatt Barden NDR_F_STRUCT, /* flags */
758ce8560eeSMatt Barden ndr__auth_verifier_co, /* ndr_func */
759ce8560eeSMatt Barden 8, /* pdu_size_fixed_part */
760ce8560eeSMatt Barden 0, /* pdu_size_variable_part */
761ce8560eeSMatt Barden 8 + sizeof (void *), /* c_size_fixed_part */
762ce8560eeSMatt Barden 0, /* c_size_variable_part */
763ce8560eeSMatt Barden };
764ce8560eeSMatt Barden
765ce8560eeSMatt Barden /*
766ce8560eeSMatt Barden * [_no_reorder]
767ce8560eeSMatt Barden */
768ce8560eeSMatt Barden int
ndr__auth_verifier_co(ndr_ref_t * encl_ref)769ce8560eeSMatt Barden ndr__auth_verifier_co(ndr_ref_t *encl_ref)
770ce8560eeSMatt Barden {
771ce8560eeSMatt Barden ndr_stream_t *nds = encl_ref->stream;
772ce8560eeSMatt Barden ndr_xa_t *mxa = /*LINTED E_BAD_PTR_CAST_ALIGN*/
773ce8560eeSMatt Barden (ndr_xa_t *)encl_ref->datum;
774ce8560eeSMatt Barden ndr_common_header_t *hdr;
775ce8560eeSMatt Barden ndr_ref_t myref;
776ce8560eeSMatt Barden ndr_sec_t *val;
777ce8560eeSMatt Barden
778ce8560eeSMatt Barden /*
779ce8560eeSMatt Barden * Assumes scan_offset points to the end of PDU body.
780ce8560eeSMatt Barden * (That's base + frag_len - auth_len - SEC_TRAILER_SIZE)
781ce8560eeSMatt Barden *
782ce8560eeSMatt Barden * At some point, NDRGEN could use struct initializers instead of
783ce8560eeSMatt Barden * bzero() + initialization.
784ce8560eeSMatt Barden */
785ce8560eeSMatt Barden bzero(&myref, sizeof (myref));
786ce8560eeSMatt Barden myref.enclosing = encl_ref;
787ce8560eeSMatt Barden myref.stream = encl_ref->stream;
788ce8560eeSMatt Barden
789ce8560eeSMatt Barden switch (nds->m_op) {
790ce8560eeSMatt Barden case NDR_M_OP_MARSHALL:
791ce8560eeSMatt Barden val = &mxa->send_auth;
792ce8560eeSMatt Barden hdr = &mxa->send_hdr.common_hdr;
793ce8560eeSMatt Barden break;
794ce8560eeSMatt Barden
795ce8560eeSMatt Barden case NDR_M_OP_UNMARSHALL:
796ce8560eeSMatt Barden val = &mxa->recv_auth;
797ce8560eeSMatt Barden hdr = &mxa->recv_hdr.common_hdr;
798ce8560eeSMatt Barden val->auth_value = (uchar_t *)NDS_MALLOC(nds, hdr->auth_length,
799ce8560eeSMatt Barden encl_ref);
800ce8560eeSMatt Barden break;
801ce8560eeSMatt Barden
802ce8560eeSMatt Barden default:
803ce8560eeSMatt Barden NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
804ce8560eeSMatt Barden return (0);
805ce8560eeSMatt Barden }
806ce8560eeSMatt Barden
807ce8560eeSMatt Barden /*
808ce8560eeSMatt Barden * ndr_topmost() can't account for auth_length (pdu_scan/end_offset).
809ce8560eeSMatt Barden * This would only matter if any of this struct's members
810ce8560eeSMatt Barden * are treated as 'outer' constructs, but they aren't.
811ce8560eeSMatt Barden */
812ce8560eeSMatt Barden encl_ref->pdu_end_offset += hdr->auth_length;
813ce8560eeSMatt Barden nds->pdu_scan_offset += hdr->auth_length;
814ce8560eeSMatt Barden
815ce8560eeSMatt Barden NDR_MEMBER(_uchar, auth_type, 0UL);
816ce8560eeSMatt Barden NDR_MEMBER(_uchar, auth_level, 1UL);
817ce8560eeSMatt Barden NDR_MEMBER(_uchar, auth_pad_len, 2UL);
818ce8560eeSMatt Barden NDR_MEMBER(_uchar, auth_rsvd, 3UL);
819ce8560eeSMatt Barden NDR_MEMBER(_ulong, auth_context_id, 4UL);
820ce8560eeSMatt Barden
821ce8560eeSMatt Barden NDR_MEMBER_PTR_WITH_DIMENSION(_uchar, auth_value, 8UL,
822ce8560eeSMatt Barden hdr->auth_length);
823ce8560eeSMatt Barden
824ce8560eeSMatt Barden return (1);
825ce8560eeSMatt Barden }
826ce8560eeSMatt Barden
827ce8560eeSMatt Barden int
ndr_encode_pdu_auth(ndr_xa_t * mxa)828ce8560eeSMatt Barden ndr_encode_pdu_auth(ndr_xa_t *mxa)
829ce8560eeSMatt Barden {
830ce8560eeSMatt Barden ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr;
831ce8560eeSMatt Barden ndr_stream_t *nds = &mxa->send_nds;
832ce8560eeSMatt Barden int rc;
833ce8560eeSMatt Barden ulong_t want_size;
834ce8560eeSMatt Barden
835ce8560eeSMatt Barden if (nds->m_op != NDR_M_OP_MARSHALL)
836ce8560eeSMatt Barden return (NDR_DRC_FAULT_MODE_MISMATCH);
837ce8560eeSMatt Barden
838ce8560eeSMatt Barden if (hdr->auth_length == 0)
839ce8560eeSMatt Barden return (NDR_DRC_OK);
840ce8560eeSMatt Barden
841ce8560eeSMatt Barden want_size = nds->pdu_scan_offset + hdr->auth_length + SEC_TRAILER_SIZE;
842ce8560eeSMatt Barden
843ce8560eeSMatt Barden /*
844ce8560eeSMatt Barden * Make sure we have space for the sec trailer - the marshaller
845ce8560eeSMatt Barden * doesn't know how large the auth token is.
846ce8560eeSMatt Barden * Note: ndr_add_auth_token() has already added padding.
847ce8560eeSMatt Barden *
848ce8560eeSMatt Barden * NDS_GROW_PDU will adjust pdu_size for us.
849ce8560eeSMatt Barden */
850ce8560eeSMatt Barden if (nds->pdu_max_size < want_size) {
851ce8560eeSMatt Barden if (NDS_GROW_PDU(nds, want_size, NULL) == 0)
852ce8560eeSMatt Barden return (NDR_DRC_FAULT_ENCODE_TOO_BIG);
853ce8560eeSMatt Barden } else {
854ce8560eeSMatt Barden nds->pdu_size = want_size;
855ce8560eeSMatt Barden }
856ce8560eeSMatt Barden rc = ndr_encode_decode_type(nds, &TYPEINFO(auth_verifier_co),
857ce8560eeSMatt Barden mxa);
858ce8560eeSMatt Barden
859ce8560eeSMatt Barden return (rc);
860ce8560eeSMatt Barden }
861ce8560eeSMatt Barden
862ce8560eeSMatt Barden int
ndr_decode_pdu_auth(ndr_xa_t * mxa)863ce8560eeSMatt Barden ndr_decode_pdu_auth(ndr_xa_t *mxa)
864ce8560eeSMatt Barden {
865ce8560eeSMatt Barden ndr_common_header_t *hdr = &mxa->recv_hdr.common_hdr;
866ce8560eeSMatt Barden ndr_stream_t *nds = &mxa->recv_nds;
867ce8560eeSMatt Barden ndr_sec_t *auth = &mxa->recv_auth;
868ce8560eeSMatt Barden int rc;
869ce8560eeSMatt Barden ulong_t saved_offset;
870ce8560eeSMatt Barden size_t auth_size;
871ce8560eeSMatt Barden
872ce8560eeSMatt Barden if (nds->m_op != NDR_M_OP_UNMARSHALL)
873ce8560eeSMatt Barden return (NDR_DRC_FAULT_MODE_MISMATCH);
874ce8560eeSMatt Barden
875ce8560eeSMatt Barden mxa->recv_auth.auth_pad_len = 0;
876ce8560eeSMatt Barden if (hdr->auth_length == 0)
877ce8560eeSMatt Barden return (NDR_DRC_OK);
878ce8560eeSMatt Barden
879ce8560eeSMatt Barden /*
880ce8560eeSMatt Barden * Save the current offset, and skip to the sec_trailer.
881ce8560eeSMatt Barden * That's located after the (fragment of) stub data and the auth
882ce8560eeSMatt Barden * pad bytes (collectively the 'PDU Body').
883ce8560eeSMatt Barden */
884ce8560eeSMatt Barden saved_offset = nds->pdu_scan_offset;
885ce8560eeSMatt Barden nds->pdu_scan_offset = nds->pdu_body_offset + nds->pdu_body_size;
886ce8560eeSMatt Barden
887ce8560eeSMatt Barden /* auth_length is all of the data after the sec_trailer */
888ce8560eeSMatt Barden if (hdr->auth_length >
889ce8560eeSMatt Barden (nds->pdu_size - nds->pdu_scan_offset - SEC_TRAILER_SIZE)) {
890ce8560eeSMatt Barden nds->pdu_scan_offset = saved_offset;
891ce8560eeSMatt Barden return (NDR_DRC_FAULT_RECEIVED_MALFORMED);
892ce8560eeSMatt Barden }
893ce8560eeSMatt Barden
894ce8560eeSMatt Barden rc = ndr_encode_decode_type(nds, &TYPEINFO(auth_verifier_co),
895ce8560eeSMatt Barden mxa);
896ce8560eeSMatt Barden
897ce8560eeSMatt Barden /*
898ce8560eeSMatt Barden * Reset the scan_offset for call decode processing.
899ce8560eeSMatt Barden * If we were successful, remove the sec trailer and padding
900ce8560eeSMatt Barden * from size accounting.
901ce8560eeSMatt Barden */
902ce8560eeSMatt Barden if (auth->auth_pad_len > nds->pdu_body_size)
903ce8560eeSMatt Barden rc = NDR_DRC_FAULT_RECEIVED_MALFORMED;
904ce8560eeSMatt Barden else if (rc == NDR_DRC_OK) {
905ce8560eeSMatt Barden auth_size = hdr->auth_length + SEC_TRAILER_SIZE +
906ce8560eeSMatt Barden auth->auth_pad_len;
907ce8560eeSMatt Barden
908ce8560eeSMatt Barden /*
909ce8560eeSMatt Barden * After the authenticator has been decoded,
910ce8560eeSMatt Barden * pdu_scan_offset points to just after the auth token,
911ce8560eeSMatt Barden * which is the end of the fragment.
912ce8560eeSMatt Barden *
913ce8560eeSMatt Barden * If there's no data after the authenticator, then we
914ce8560eeSMatt Barden * just remove the authenticator from size accounting.
915ce8560eeSMatt Barden * Otherwise, need to memmove() all of that data back to after
916ce8560eeSMatt Barden * the stub data. The data we move starts at the beginning of
917ce8560eeSMatt Barden * the next fragment.
918ce8560eeSMatt Barden */
919ce8560eeSMatt Barden if (nds->pdu_size > nds->pdu_scan_offset) {
920ce8560eeSMatt Barden uchar_t *next_frag_ptr = nds->pdu_base_addr +
921ce8560eeSMatt Barden nds->pdu_scan_offset;
922ce8560eeSMatt Barden
923ce8560eeSMatt Barden memmove(next_frag_ptr - auth_size, next_frag_ptr,
924ce8560eeSMatt Barden nds->pdu_size - nds->pdu_scan_offset);
925ce8560eeSMatt Barden }
926ce8560eeSMatt Barden
927ce8560eeSMatt Barden nds->pdu_size -= auth_size;
928ce8560eeSMatt Barden }
929ce8560eeSMatt Barden nds->pdu_scan_offset = saved_offset;
930ce8560eeSMatt Barden return (rc);
931ce8560eeSMatt Barden }
932