xref: /onnv-gate/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c (revision 5772:237ac22142fe)
1*5772Sas200622 /*
2*5772Sas200622  * CDDL HEADER START
3*5772Sas200622  *
4*5772Sas200622  * The contents of this file are subject to the terms of the
5*5772Sas200622  * Common Development and Distribution License (the "License").
6*5772Sas200622  * You may not use this file except in compliance with the License.
7*5772Sas200622  *
8*5772Sas200622  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5772Sas200622  * or http://www.opensolaris.org/os/licensing.
10*5772Sas200622  * See the License for the specific language governing permissions
11*5772Sas200622  * and limitations under the License.
12*5772Sas200622  *
13*5772Sas200622  * When distributing Covered Code, include this CDDL HEADER in each
14*5772Sas200622  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5772Sas200622  * If applicable, add the following below this CDDL HEADER, with the
16*5772Sas200622  * fields enclosed by brackets "[]" replaced with your own identifying
17*5772Sas200622  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5772Sas200622  *
19*5772Sas200622  * CDDL HEADER END
20*5772Sas200622  */
21*5772Sas200622 /*
22*5772Sas200622  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*5772Sas200622  * Use is subject to license terms.
24*5772Sas200622  */
25*5772Sas200622 
26*5772Sas200622 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5772Sas200622 
28*5772Sas200622 #include <strings.h>
29*5772Sas200622 #include <sys/param.h>
30*5772Sas200622 
31*5772Sas200622 #include <smbsrv/libsmb.h>
32*5772Sas200622 #include <smbsrv/ndr.h>
33*5772Sas200622 #include <smbsrv/mlrpc.h>
34*5772Sas200622 
35*5772Sas200622 #ifdef _BIG_ENDIAN
36*5772Sas200622 static const int mlrpc_native_byte_order = MLRPC_REPLAB_INTG_BIG_ENDIAN;
37*5772Sas200622 #else
38*5772Sas200622 static const int mlrpc_native_byte_order = MLRPC_REPLAB_INTG_LITTLE_ENDIAN;
39*5772Sas200622 #endif
40*5772Sas200622 
41*5772Sas200622 int
42*5772Sas200622 mlrpc_encode_decode_common(struct mlrpc_xaction *mxa, int mode, unsigned opnum,
43*5772Sas200622     struct ndr_typeinfo *ti, void *datum)
44*5772Sas200622 {
45*5772Sas200622 	struct mlndr_stream	*mlnds;
46*5772Sas200622 	int			m_op = NDR_MODE_TO_M_OP(mode);
47*5772Sas200622 	int			rc;
48*5772Sas200622 
49*5772Sas200622 	if (m_op == NDR_M_OP_MARSHALL)
50*5772Sas200622 		mlnds = &mxa->send_mlnds;
51*5772Sas200622 	else
52*5772Sas200622 		mlnds = &mxa->recv_mlnds;
53*5772Sas200622 
54*5772Sas200622 	/*
55*5772Sas200622 	 * Make sure that mlnds is in the correct mode
56*5772Sas200622 	 */
57*5772Sas200622 	if (!NDR_MODE_MATCH(mlnds, mode))
58*5772Sas200622 		return (MLRPC_DRC_FAULT_MODE_MISMATCH);
59*5772Sas200622 
60*5772Sas200622 	/*
61*5772Sas200622 	 * Perform the (un)marshalling
62*5772Sas200622 	 */
63*5772Sas200622 	if (mlndo_operation(mlnds, ti, opnum, datum))
64*5772Sas200622 		return (MLRPC_DRC_OK);
65*5772Sas200622 
66*5772Sas200622 	switch (mlnds->error) {
67*5772Sas200622 	case NDR_ERR_MALLOC_FAILED:
68*5772Sas200622 		rc = MLRPC_DRC_FAULT_OUT_OF_MEMORY;
69*5772Sas200622 		break;
70*5772Sas200622 
71*5772Sas200622 	case NDR_ERR_SWITCH_VALUE_INVALID:
72*5772Sas200622 		rc = MLRPC_DRC_FAULT_PARAM_0_INVALID;
73*5772Sas200622 		break;
74*5772Sas200622 
75*5772Sas200622 	case NDR_ERR_UNDERFLOW:
76*5772Sas200622 		rc = MLRPC_DRC_FAULT_RECEIVED_RUNT;
77*5772Sas200622 		break;
78*5772Sas200622 
79*5772Sas200622 	case NDR_ERR_GROW_FAILED:
80*5772Sas200622 		rc = MLRPC_DRC_FAULT_ENCODE_TOO_BIG;
81*5772Sas200622 		break;
82*5772Sas200622 
83*5772Sas200622 	default:
84*5772Sas200622 		if (m_op == NDR_M_OP_MARSHALL)
85*5772Sas200622 			rc = MLRPC_DRC_FAULT_ENCODE_FAILED;
86*5772Sas200622 		else
87*5772Sas200622 			rc = MLRPC_DRC_FAULT_DECODE_FAILED;
88*5772Sas200622 		break;
89*5772Sas200622 	}
90*5772Sas200622 
91*5772Sas200622 	return (rc);
92*5772Sas200622 }
93*5772Sas200622 
94*5772Sas200622 int
95*5772Sas200622 mlrpc_decode_call(struct mlrpc_xaction *mxa, void *params)
96*5772Sas200622 {
97*5772Sas200622 	int rc;
98*5772Sas200622 
99*5772Sas200622 	rc = mlrpc_encode_decode_common(mxa, NDR_MODE_CALL_RECV,
100*5772Sas200622 	    mxa->opnum, mxa->binding->service->interface_ti, params);
101*5772Sas200622 
102*5772Sas200622 	return (rc + MLRPC_PTYPE_REQUEST);
103*5772Sas200622 }
104*5772Sas200622 
105*5772Sas200622 int
106*5772Sas200622 mlrpc_encode_return(struct mlrpc_xaction *mxa, void *params)
107*5772Sas200622 {
108*5772Sas200622 	int rc;
109*5772Sas200622 
110*5772Sas200622 	rc = mlrpc_encode_decode_common(mxa, NDR_MODE_RETURN_SEND,
111*5772Sas200622 	    mxa->opnum, mxa->binding->service->interface_ti, params);
112*5772Sas200622 
113*5772Sas200622 	return (rc + MLRPC_PTYPE_RESPONSE);
114*5772Sas200622 }
115*5772Sas200622 
116*5772Sas200622 int
117*5772Sas200622 mlrpc_encode_call(struct mlrpc_xaction *mxa, void *params)
118*5772Sas200622 {
119*5772Sas200622 	int rc;
120*5772Sas200622 
121*5772Sas200622 	rc = mlrpc_encode_decode_common(mxa, NDR_MODE_CALL_SEND,
122*5772Sas200622 	    mxa->opnum, mxa->binding->service->interface_ti, params);
123*5772Sas200622 
124*5772Sas200622 	return (rc + MLRPC_PTYPE_REQUEST);
125*5772Sas200622 }
126*5772Sas200622 
127*5772Sas200622 int
128*5772Sas200622 mlrpc_decode_return(struct mlrpc_xaction *mxa, void *params)
129*5772Sas200622 {
130*5772Sas200622 	int rc;
131*5772Sas200622 
132*5772Sas200622 	rc = mlrpc_encode_decode_common(mxa, NDR_MODE_RETURN_RECV,
133*5772Sas200622 	    mxa->opnum, mxa->binding->service->interface_ti, params);
134*5772Sas200622 
135*5772Sas200622 	return (rc + MLRPC_PTYPE_RESPONSE);
136*5772Sas200622 }
137*5772Sas200622 
138*5772Sas200622 int
139*5772Sas200622 mlrpc_decode_pdu_hdr(struct mlrpc_xaction *mxa)
140*5772Sas200622 {
141*5772Sas200622 	mlrpcconn_common_header_t *hdr = &mxa->recv_hdr.common_hdr;
142*5772Sas200622 	struct mlndr_stream 	*mlnds = &mxa->recv_mlnds;
143*5772Sas200622 	int			ptype;
144*5772Sas200622 	int			rc;
145*5772Sas200622 	int			charset;
146*5772Sas200622 	int			byte_order;
147*5772Sas200622 
148*5772Sas200622 	if (mlnds->m_op != NDR_M_OP_UNMARSHALL)
149*5772Sas200622 		return (MLRPC_DRC_FAULT_MODE_MISMATCH + 0xFF);
150*5772Sas200622 
151*5772Sas200622 	/*
152*5772Sas200622 	 * All PDU headers are at least this big
153*5772Sas200622 	 */
154*5772Sas200622 	rc = MLNDS_GROW_PDU(mlnds, sizeof (mlrpcconn_common_header_t), 0);
155*5772Sas200622 	if (!rc)
156*5772Sas200622 		return (MLRPC_DRC_FAULT_RECEIVED_RUNT + 0xFF);
157*5772Sas200622 
158*5772Sas200622 	/*
159*5772Sas200622 	 * Peek at the first eight bytes to figure out what we're doing.
160*5772Sas200622 	 */
161*5772Sas200622 	rc = MLNDS_GET_PDU(mlnds, 0, 8, (char *)hdr, 0, 0);
162*5772Sas200622 	if (!rc)
163*5772Sas200622 		return (MLRPC_DRC_FAULT_DECODE_FAILED + 0xFF);
164*5772Sas200622 
165*5772Sas200622 	/*
166*5772Sas200622 	 * Verify the protocol version.
167*5772Sas200622 	 */
168*5772Sas200622 	if ((hdr->rpc_vers != 5) || (hdr->rpc_vers_minor != 0))
169*5772Sas200622 		return (MLRPC_DRC_FAULT_DECODE_FAILED + 0xFF);
170*5772Sas200622 
171*5772Sas200622 	/*
172*5772Sas200622 	 * Check for ASCII as the character set.  This is an ASCII
173*5772Sas200622 	 * versus EBCDIC option and has nothing to do with Unicode.
174*5772Sas200622 	 */
175*5772Sas200622 	charset = hdr->packed_drep.intg_char_rep & MLRPC_REPLAB_CHAR_MASK;
176*5772Sas200622 	if (charset != MLRPC_REPLAB_CHAR_ASCII)
177*5772Sas200622 		return (MLRPC_DRC_FAULT_DECODE_FAILED + 0xFF);
178*5772Sas200622 
179*5772Sas200622 	/*
180*5772Sas200622 	 * Set the byte swap flag if the PDU byte-order
181*5772Sas200622 	 * is different from the local byte-order.
182*5772Sas200622 	 */
183*5772Sas200622 	byte_order = hdr->packed_drep.intg_char_rep & MLRPC_REPLAB_INTG_MASK;
184*5772Sas200622 	mlnds->swap = (byte_order != mlrpc_native_byte_order) ? 1 : 0;
185*5772Sas200622 
186*5772Sas200622 	ptype = hdr->ptype;
187*5772Sas200622 	if (ptype == MLRPC_PTYPE_REQUEST &&
188*5772Sas200622 	    (hdr->pfc_flags & MLRPC_PFC_OBJECT_UUID) != 0) {
189*5772Sas200622 		ptype = MLRPC_PTYPE_REQUEST_WITH;	/* fake for sizing */
190*5772Sas200622 	}
191*5772Sas200622 
192*5772Sas200622 	mxa->ptype = hdr->ptype;
193*5772Sas200622 
194*5772Sas200622 	rc = mlrpc_encode_decode_common(mxa,
195*5772Sas200622 	    NDR_M_OP_AND_DIR_TO_MODE(mlnds->m_op, mlnds->dir),
196*5772Sas200622 	    ptype, &TYPEINFO(mlrpcconn_hdr), hdr);
197*5772Sas200622 
198*5772Sas200622 	return (rc + 0xFF);
199*5772Sas200622 }
200*5772Sas200622 
201*5772Sas200622 /*
202*5772Sas200622  * Decode an RPC fragment header.  Use mlrpc_decode_pdu_hdr() to process
203*5772Sas200622  * the first fragment header then this function to process additional
204*5772Sas200622  * fragment headers.
205*5772Sas200622  */
206*5772Sas200622 void
207*5772Sas200622 mlrpc_decode_frag_hdr(struct mlndr_stream *mlnds,
208*5772Sas200622     mlrpcconn_common_header_t *hdr)
209*5772Sas200622 {
210*5772Sas200622 	mlrpcconn_common_header_t *tmp;
211*5772Sas200622 	uint8_t *pdu;
212*5772Sas200622 	int byte_order;
213*5772Sas200622 
214*5772Sas200622 	pdu = (uint8_t *)mlnds->pdu_base_offset + mlnds->pdu_scan_offset;
215*5772Sas200622 	bcopy(pdu, hdr, MLRPC_RSP_HDR_SIZE);
216*5772Sas200622 
217*5772Sas200622 	/*
218*5772Sas200622 	 * Swap non-byte fields if the PDU byte-order
219*5772Sas200622 	 * is different from the local byte-order.
220*5772Sas200622 	 */
221*5772Sas200622 	byte_order = hdr->packed_drep.intg_char_rep & MLRPC_REPLAB_INTG_MASK;
222*5772Sas200622 
223*5772Sas200622 	if (byte_order != mlrpc_native_byte_order) {
224*5772Sas200622 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
225*5772Sas200622 		tmp = (mlrpcconn_common_header_t *)pdu;
226*5772Sas200622 
227*5772Sas200622 		mlnds_bswap(&tmp->frag_length, &hdr->frag_length,
228*5772Sas200622 		    sizeof (WORD));
229*5772Sas200622 		mlnds_bswap(&tmp->auth_length, &hdr->auth_length,
230*5772Sas200622 		    sizeof (WORD));
231*5772Sas200622 		mlnds_bswap(&tmp->call_id, &hdr->call_id, sizeof (DWORD));
232*5772Sas200622 	}
233*5772Sas200622 }
234*5772Sas200622 
235*5772Sas200622 int
236*5772Sas200622 mlrpc_encode_pdu_hdr(struct mlrpc_xaction *mxa)
237*5772Sas200622 {
238*5772Sas200622 	mlrpcconn_common_header_t *hdr = &mxa->send_hdr.common_hdr;
239*5772Sas200622 	struct mlndr_stream 	*mlnds = &mxa->send_mlnds;
240*5772Sas200622 	int			ptype;
241*5772Sas200622 	int			rc;
242*5772Sas200622 
243*5772Sas200622 	if (mlnds->m_op != NDR_M_OP_MARSHALL)
244*5772Sas200622 		return (MLRPC_DRC_FAULT_MODE_MISMATCH + 0xFF);
245*5772Sas200622 
246*5772Sas200622 	ptype = hdr->ptype;
247*5772Sas200622 	if (ptype == MLRPC_PTYPE_REQUEST &&
248*5772Sas200622 	    (hdr->pfc_flags & MLRPC_PFC_OBJECT_UUID) != 0) {
249*5772Sas200622 		ptype = MLRPC_PTYPE_REQUEST_WITH;	/* fake for sizing */
250*5772Sas200622 	}
251*5772Sas200622 
252*5772Sas200622 	rc = mlrpc_encode_decode_common(mxa,
253*5772Sas200622 	    NDR_M_OP_AND_DIR_TO_MODE(mlnds->m_op, mlnds->dir),
254*5772Sas200622 	    ptype, &TYPEINFO(mlrpcconn_hdr), hdr);
255*5772Sas200622 
256*5772Sas200622 	return (rc + 0xFF);
257*5772Sas200622 }
258*5772Sas200622 
259*5772Sas200622 /*
260*5772Sas200622  * This is a hand-coded derivative of the automatically generated
261*5772Sas200622  * (un)marshalling routine for bind_ack headers. bind_ack headers
262*5772Sas200622  * have an interior conformant array, which is inconsistent with
263*5772Sas200622  * IDL/NDR rules.
264*5772Sas200622  */
265*5772Sas200622 extern struct ndr_typeinfo ndt__uchar;
266*5772Sas200622 extern struct ndr_typeinfo ndt__ushort;
267*5772Sas200622 extern struct ndr_typeinfo ndt__ulong;
268*5772Sas200622 
269*5772Sas200622 int mlndr__mlrpcconn_bind_ack_hdr(struct ndr_reference *encl_ref);
270*5772Sas200622 struct ndr_typeinfo ndt__mlrpcconn_bind_ack_hdr = {
271*5772Sas200622     1,		/* NDR version */
272*5772Sas200622     3,		/* alignment */
273*5772Sas200622     NDR_F_STRUCT,	/* flags */
274*5772Sas200622     mlndr__mlrpcconn_bind_ack_hdr,	/* ndr_func */
275*5772Sas200622     68,		/* pdu_size_fixed_part */
276*5772Sas200622     0,		/* pdu_size_variable_part */
277*5772Sas200622     68,		/* c_size_fixed_part */
278*5772Sas200622     0,		/* c_size_variable_part */
279*5772Sas200622 };
280*5772Sas200622 
281*5772Sas200622 /*
282*5772Sas200622  * [_no_reorder]
283*5772Sas200622  */
284*5772Sas200622 int
285*5772Sas200622 mlndr__mlrpcconn_bind_ack_hdr(struct ndr_reference *encl_ref)
286*5772Sas200622 {
287*5772Sas200622 	struct mlndr_stream 		*mlnds = encl_ref->stream;
288*5772Sas200622 	struct mlrpcconn_bind_ack_hdr   *val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
289*5772Sas200622 	    (struct mlrpcconn_bind_ack_hdr *)encl_ref->datum;
290*5772Sas200622 	struct ndr_reference	myref;
291*5772Sas200622 	unsigned long		offset;
292*5772Sas200622 
293*5772Sas200622 	bzero(&myref, sizeof (myref));
294*5772Sas200622 	myref.enclosing = encl_ref;
295*5772Sas200622 	myref.stream = encl_ref->stream;
296*5772Sas200622 	myref.packed_alignment = 0;
297*5772Sas200622 
298*5772Sas200622 	/* do all members in order */
299*5772Sas200622 	NDR_MEMBER(_mlrpcconn_common_header, common_hdr, 0UL);
300*5772Sas200622 	NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
301*5772Sas200622 	NDR_MEMBER(_ushort, max_recv_frag, 18UL);
302*5772Sas200622 	NDR_MEMBER(_ulong, assoc_group_id, 20UL);
303*5772Sas200622 
304*5772Sas200622 	/* port any is the conformant culprit */
305*5772Sas200622 	offset = 24UL;
306*5772Sas200622 
307*5772Sas200622 	switch (mlnds->m_op) {
308*5772Sas200622 	case NDR_M_OP_MARSHALL:
309*5772Sas200622 		val->sec_addr.length =
310*5772Sas200622 		    strlen((char *)val->sec_addr.port_spec) + 1;
311*5772Sas200622 		break;
312*5772Sas200622 
313*5772Sas200622 	case NDR_M_OP_UNMARSHALL:
314*5772Sas200622 		break;
315*5772Sas200622 
316*5772Sas200622 	default:
317*5772Sas200622 		NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
318*5772Sas200622 		return (0);
319*5772Sas200622 	}
320*5772Sas200622 
321*5772Sas200622 	NDR_MEMBER(_ushort, sec_addr.length, offset);
322*5772Sas200622 	NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
323*5772Sas200622 	    offset+2UL, val->sec_addr.length);
324*5772Sas200622 
325*5772Sas200622 	offset += 2;
326*5772Sas200622 	offset += val->sec_addr.length;
327*5772Sas200622 	offset += (4 - offset) & 3;
328*5772Sas200622 
329*5772Sas200622 	NDR_MEMBER(_mlrpc_p_result_list, p_result_list, offset);
330*5772Sas200622 	return (1);
331*5772Sas200622 }
332*5772Sas200622 
333*5772Sas200622 unsigned
334*5772Sas200622 mlrpc_bind_ack_hdr_size(struct mlrpcconn_bind_ack_hdr *bahdr)
335*5772Sas200622 {
336*5772Sas200622 	unsigned	offset;
337*5772Sas200622 	unsigned	length;
338*5772Sas200622 
339*5772Sas200622 	/* port any is the conformant culprit */
340*5772Sas200622 	offset = 24UL;
341*5772Sas200622 
342*5772Sas200622 	length = strlen((char *)bahdr->sec_addr.port_spec) + 1;
343*5772Sas200622 
344*5772Sas200622 	offset += 2;
345*5772Sas200622 	offset += length;
346*5772Sas200622 	offset += (4 - offset) & 3;
347*5772Sas200622 	offset += sizeof (bahdr->p_result_list);
348*5772Sas200622 	return (offset);
349*5772Sas200622 }
350