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