diff options
Diffstat (limited to 'usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c')
| -rw-r--r-- | usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c | 86 |
1 files changed, 71 insertions, 15 deletions
diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c index 12fd0c0d52..a690dfb2e9 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <assert.h> @@ -37,6 +36,7 @@ static const int ndr_native_byte_order = NDR_REPLAB_INTG_LITTLE_ENDIAN; #endif static int ndr_decode_hdr_common(ndr_stream_t *, ndr_common_header_t *); +static int ndr_decode_pac_hdr(ndr_stream_t *, ndr_pac_hdr_t *); static int ndr_encode_decode_common(ndr_stream_t *nds, unsigned opnum, @@ -122,10 +122,11 @@ ndr_buf_fini(ndr_buf_t *nbuf) * } */ int -ndr_buf_decode(ndr_buf_t *nbuf, unsigned opnum, const char *data, - size_t datalen, void *result) +ndr_buf_decode(ndr_buf_t *nbuf, unsigned hdr_type, unsigned opnum, + const char *data, size_t datalen, void *result) { ndr_common_header_t hdr; + ndr_pac_hdr_t pac_hdr; unsigned pdu_size_hint; int rc; @@ -145,12 +146,28 @@ ndr_buf_decode(ndr_buf_t *nbuf, unsigned opnum, const char *data, bcopy(data, nbuf->nb_nds.pdu_base_addr, datalen); - rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr); - if (NDR_DRC_IS_FAULT(rc)) - return (rc); + switch (hdr_type) { + case NDR_PTYPE_COMMON: + rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr); + if (NDR_DRC_IS_FAULT(rc)) + return (rc); + + if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags)) + return (NDR_DRC_FAULT_DECODE_FAILED); + break; + + case NDR_PTYPE_PAC: + rc = ndr_decode_pac_hdr(&nbuf->nb_nds, &pac_hdr); + if (NDR_DRC_IS_FAULT(rc)) + return (rc); - if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags)) - return (NDR_DRC_FAULT_DECODE_FAILED); + if (pac_hdr.common_hdr.hdrlen != sizeof (ndr_serialtype1_hdr_t)) + return (NDR_DRC_FAULT_DECODE_FAILED); + break; + + default: + return (NDR_ERR_UNIMPLEMENTED); + } rc = ndr_encode_decode_common(&nbuf->nb_nds, opnum, nbuf->nb_ti, result); @@ -244,7 +261,7 @@ ndr_decode_pdu_hdr(ndr_xa_t *mxa) * Verify the protocol version. */ if ((hdr->rpc_vers != 5) || (hdr->rpc_vers_minor != 0)) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_DECODE_FAILED)); + return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); mxa->ptype = hdr->ptype; return (NDR_DRC_OK); @@ -259,21 +276,21 @@ ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr) int byte_order; if (nds->m_op != NDR_M_OP_UNMARSHALL) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_MODE_MISMATCH)); + return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH); /* * All PDU headers are at least this big */ rc = NDS_GROW_PDU(nds, sizeof (ndr_common_header_t), 0); if (!rc) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_RECEIVED_RUNT)); + return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT); /* * Peek at the first eight bytes to figure out what we're doing. */ rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0); if (!rc) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_DECODE_FAILED)); + return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); /* * Check for ASCII as the character set. This is an ASCII @@ -281,7 +298,7 @@ ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr) */ charset = hdr->packed_drep.intg_char_rep & NDR_REPLAB_CHAR_MASK; if (charset != NDR_REPLAB_CHAR_ASCII) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_DECODE_FAILED)); + return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); /* * Set the byte swap flag if the PDU byte-order @@ -301,6 +318,45 @@ ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr) return (NDR_DRC_PTYPE_RPCHDR(rc)); } +static int +ndr_decode_pac_hdr(ndr_stream_t *nds, ndr_pac_hdr_t *hdr) +{ + int rc; + + if (nds->m_op != NDR_M_OP_UNMARSHALL) + return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH); + + /* + * All PDU headers are at least this big + */ + rc = NDS_GROW_PDU(nds, sizeof (ndr_pac_hdr_t), 0); + if (!rc) + return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT); + + /* + * Peek at the first eight bytes to figure out what we're doing. + */ + rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0); + if (!rc) + return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); + + /* Must be set to 1 to indicate type serialization version 1. */ + if (hdr->common_hdr.version != 1) + return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); + + /* + * Set the byte swap flag if the PDU byte-order + * is different from the local byte-order. + */ + nds->swap = + (hdr->common_hdr.endianness != ndr_native_byte_order) ? 1 : 0; + + rc = ndr_encode_decode_common(nds, NDR_PTYPE_PAC, + &TYPEINFO(ndr_hdr), hdr); + + return (NDR_DRC_PTYPE_RPCHDR(rc)); +} + /* * Decode an RPC fragment header. Use ndr_decode_pdu_hdr() to process * the first fragment header then this function to process additional @@ -400,7 +456,7 @@ ndr_encode_pdu_hdr(ndr_xa_t *mxa) int rc; if (nds->m_op != NDR_M_OP_MARSHALL) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_MODE_MISMATCH)); + return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH); ptype = hdr->ptype; if (ptype == NDR_PTYPE_REQUEST && |
