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