Print this page
1575 untangle libmlrpc ... (libmlrpc)
*** 20,29 ****
--- 20,30 ----
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Network Data Representation (NDR) is a compatible subset of the DCE RPC
* and MSRPC NDR. NDR is used to move parameters consisting of
*** 32,49 ****
#include <sys/byteorder.h>
#include <strings.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
! #include <smbsrv/libsmb.h>
! #include <smbsrv/string.h>
! #include <smbsrv/libmlrpc.h>
- #define NDR_STRING_MAX 4096
-
#define NDR_IS_UNION(T) \
(((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_UNION)
#define NDR_IS_STRING(T) \
(((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_STRING)
--- 33,48 ----
#include <sys/byteorder.h>
#include <strings.h>
#include <assert.h>
#include <string.h>
+ #include <stdio.h>
#include <stdlib.h>
! #include <libmlrpc.h>
! #include <ndr_wchar.h>
#define NDR_IS_UNION(T) \
(((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_UNION)
#define NDR_IS_STRING(T) \
(((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_STRING)
*** 1208,1228 ****
if (ti == &ndt_s_wchar) {
/*
* size_is is the number of characters in the
* (multibyte) string, including the null.
*/
! size_is = smb_wcequiv_strlen(valp) /
! sizeof (smb_wchar_t);
!
! if (!(nds->flags & NDS_F_NONULL))
! ++size_is;
!
! if (size_is > NDR_STRING_MAX) {
NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
return (0);
}
} else {
valp = outer_ref->datum;
n_zeroes = 0;
for (ix = 0; ix < NDR_STRING_MAX; ix++) {
if (valp[ix] == 0) {
--- 1207,1232 ----
if (ti == &ndt_s_wchar) {
/*
* size_is is the number of characters in the
* (multibyte) string, including the null.
+ * In other words, symbols, not bytes.
*/
! size_t wlen;
! wlen = ndr__mbstowcs(NULL, valp, NDR_STRING_MAX);
! if (wlen == (size_t)-1) {
! /* illegal sequence error? */
NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
return (0);
}
+ if ((nds->flags & NDS_F_NONULL) == 0)
+ wlen++;
+ if (wlen > NDR_STRING_MAX) {
+ NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
+ return (0);
+ }
+ size_is = wlen;
} else {
valp = outer_ref->datum;
n_zeroes = 0;
for (ix = 0; ix < NDR_STRING_MAX; ix++) {
if (valp[ix] == 0) {
*** 1286,1296 ****
* Decoding Unicode to UTF-8; we need to allow
* for the maximum possible char size. It would
* be nice to use mbequiv_strlen but the string
* may not be null terminated.
*/
! n_alloc = (size_is + 1) * MTS_MB_CHAR_MAX;
} else {
n_alloc = (size_is + 1) * is_varlen;
}
valp = NDS_MALLOC(nds, n_alloc, outer_ref);
--- 1290,1300 ----
* Decoding Unicode to UTF-8; we need to allow
* for the maximum possible char size. It would
* be nice to use mbequiv_strlen but the string
* may not be null terminated.
*/
! n_alloc = (size_is + 1) * NDR_MB_CHAR_MAX;
} else {
n_alloc = (size_is + 1) * is_varlen;
}
valp = NDS_MALLOC(nds, n_alloc, outer_ref);
*** 1739,1749 ****
myref.packed_alignment = 0;
myref.ti = ti;
myref.inner_flags = NDR_F_NONE;
for (i = 0; i < n_elem; i++) {
! (void) sprintf(name, "[%lu]", i);
myref.name = name;
myref.pdu_offset = pdu_offset + i * ti->pdu_size_fixed_part;
myref.datum = encl_ref->datum + i * ti->c_size_fixed_part;
if (!ndr_inner(&myref))
--- 1743,1753 ----
myref.packed_alignment = 0;
myref.ti = ti;
myref.inner_flags = NDR_F_NONE;
for (i = 0; i < n_elem; i++) {
! (void) snprintf(name, sizeof (name), "[%lu]", i);
myref.name = name;
myref.pdu_offset = pdu_offset + i * ti->pdu_size_fixed_part;
myref.datum = encl_ref->datum + i * ti->c_size_fixed_part;
if (!ndr_inner(&myref))
*** 1794,1813 ****
MAKE_BASIC_TYPE_STRING(TYPE, SIZE)
int ndr_basic_integer(ndr_ref_t *, unsigned);
int ndr_string_basic_integer(ndr_ref_t *, ndr_typeinfo_t *);
! MAKE_BASIC_TYPE(_char, 1)
! MAKE_BASIC_TYPE(_uchar, 1)
! MAKE_BASIC_TYPE(_short, 2)
! MAKE_BASIC_TYPE(_ushort, 2)
! MAKE_BASIC_TYPE(_long, 4)
! MAKE_BASIC_TYPE(_ulong, 4)
- MAKE_BASIC_TYPE_BASE(_wchar, 2)
-
int
ndr_basic_integer(ndr_ref_t *ref, unsigned size)
{
ndr_stream_t *nds = ref->stream;
char *valp = (char *)ref->datum;
--- 1798,1817 ----
MAKE_BASIC_TYPE_STRING(TYPE, SIZE)
int ndr_basic_integer(ndr_ref_t *, unsigned);
int ndr_string_basic_integer(ndr_ref_t *, ndr_typeinfo_t *);
+ /* Comments to be nice to those searching for these types. */
+ MAKE_BASIC_TYPE(_char, 1) /* ndt__char, ndt_s_char */
+ MAKE_BASIC_TYPE(_uchar, 1) /* ndt__uchar, ndt_s_uchar */
+ MAKE_BASIC_TYPE(_short, 2) /* ndt__short, ndt_s_short */
+ MAKE_BASIC_TYPE(_ushort, 2) /* ndt__ushort, ndt_s_ushort */
+ MAKE_BASIC_TYPE(_long, 4) /* ndt__long, ndt_s_long */
+ MAKE_BASIC_TYPE(_ulong, 4) /* ndt__ulong, ndt_s_ulong */
! MAKE_BASIC_TYPE_BASE(_wchar, 2) /* ndt__wchar, ndt_s_wchar */
int
ndr_basic_integer(ndr_ref_t *ref, unsigned size)
{
ndr_stream_t *nds = ref->stream;
char *valp = (char *)ref->datum;
*** 1852,1862 ****
myref.ti = type_under;
myref.inner_flags = NDR_F_NONE;
myref.name = name;
for (i = 0; i < NDR_STRING_MAX; i++) {
! (void) sprintf(name, "[%lu]", i);
myref.pdu_offset = pdu_offset + i * size;
valp = encl_ref->datum + i * size;
myref.datum = valp;
if (!ndr_inner(&myref))
--- 1856,1866 ----
myref.ti = type_under;
myref.inner_flags = NDR_F_NONE;
myref.name = name;
for (i = 0; i < NDR_STRING_MAX; i++) {
! (void) snprintf(name, sizeof (name), "[%lu]", i);
myref.pdu_offset = pdu_offset + i * size;
valp = encl_ref->datum + i * size;
myref.datum = valp;
if (!ndr_inner(&myref))
*** 1895,1926 ****
* Hand coded wchar function because all strings are transported
* as wide characters. During NDR_M_OP_MARSHALL, we convert from
* multi-byte to wide characters. During NDR_M_OP_UNMARSHALL, we
* convert from wide characters to multi-byte.
*
! * It appeared that NT would sometimes leave a spurious character
! * in the data stream before the null wide_char, which would get
! * included in the string decode because we processed until the
! * null character. It now looks like NT does not always terminate
! * RPC Unicode strings and the terminating null is a side effect
! * of field alignment. So now we rely on the strlen_is (set up in
! * ndr_outer_string) of the enclosing reference. This may or may
! * not include the null but it doesn't matter, the algorithm will
! * get it right.
*/
int
ndr_s_wchar(ndr_ref_t *encl_ref)
{
ndr_stream_t *nds = encl_ref->stream;
! unsigned short wide_char;
! char *valp;
ndr_ref_t myref;
- unsigned long i;
char name[30];
! int count;
! int char_count = 0;
if (nds->m_op == NDR_M_OP_UNMARSHALL) {
/*
* To avoid problems with zero length strings
* we can just null terminate here and be done.
*/
--- 1899,1930 ----
* Hand coded wchar function because all strings are transported
* as wide characters. During NDR_M_OP_MARSHALL, we convert from
* multi-byte to wide characters. During NDR_M_OP_UNMARSHALL, we
* convert from wide characters to multi-byte.
*
! * The most critical thing to get right in this function is to
! * marshall or unmarshall _exactly_ the number of elements the
! * OtW length specifies, as saved by the caller in: strlen_is.
! * Doing otherwise would leave us positioned at the wrong place
! * in the data stream for whatever follows this. Note that the
! * string data covered by strlen_is may or may not include any
! * null termination, but the converted string provided by the
! * caller or returned always has a null terminator.
*/
int
ndr_s_wchar(ndr_ref_t *encl_ref)
{
ndr_stream_t *nds = encl_ref->stream;
! char *valp = encl_ref->datum;
ndr_ref_t myref;
char name[30];
! ndr_wchar_t wcs[NDR_STRING_MAX+1];
! size_t i, slen, wlen;
+ /* This is enforced in ndr_outer_string() */
+ assert(encl_ref->strlen_is <= NDR_STRING_MAX);
+
if (nds->m_op == NDR_M_OP_UNMARSHALL) {
/*
* To avoid problems with zero length strings
* we can just null terminate here and be done.
*/
*** 1928,1992 ****
encl_ref->datum[0] = '\0';
return (1);
}
}
bzero(&myref, sizeof (myref));
myref.enclosing = encl_ref;
myref.stream = encl_ref->stream;
myref.packed_alignment = 0;
myref.ti = &ndt__wchar;
myref.inner_flags = NDR_F_NONE;
- myref.datum = (char *)&wide_char;
myref.name = name;
myref.pdu_offset = encl_ref->pdu_offset;
! valp = encl_ref->datum;
! count = 0;
!
! for (i = 0; i < NDR_STRING_MAX; i++) {
! (void) sprintf(name, "[%lu]", i);
!
! if (nds->m_op == NDR_M_OP_MARSHALL) {
! count = smb_mbtowc((smb_wchar_t *)&wide_char, valp,
! MTS_MB_CHAR_MAX);
! if (count < 0) {
return (0);
! } else if (count == 0) {
! if (encl_ref->strlen_is != encl_ref->size_is)
! break;
/*
! * If the input char is 0, mbtowc
! * returns 0 without setting wide_char.
! * Set wide_char to 0 and a count of 1.
*/
- wide_char = *valp;
- count = 1;
- }
- }
-
- if (!ndr_inner(&myref))
- return (0);
-
if (nds->m_op == NDR_M_OP_UNMARSHALL) {
! count = smb_wctomb(valp, wide_char);
!
! if ((++char_count) == encl_ref->strlen_is) {
! valp += count;
! *valp = '\0';
! break;
}
- }
- if (!wide_char)
- break;
-
- myref.pdu_offset += sizeof (wide_char);
- valp += count;
- }
-
return (1);
}
/*
* Converts a multibyte character string to a little-endian, wide-char
--- 1932,1997 ----
encl_ref->datum[0] = '\0';
return (1);
}
}
+ /*
+ * If we're marshalling, convert the given string
+ * from UTF-8 into a local UCS-2 string.
+ */
+ if (nds->m_op == NDR_M_OP_MARSHALL) {
+ wlen = ndr__mbstowcs(wcs, valp, NDR_STRING_MAX);
+ if (wlen == (size_t)-1)
+ return (0);
+ /*
+ * Add a nulls to make strlen_is.
+ * (always zero or one of them)
+ * Then null terminate at wlen,
+ * just for debug convenience.
+ */
+ while (wlen < encl_ref->strlen_is)
+ wcs[wlen++] = 0;
+ wcs[wlen] = 0;
+ }
+
+ /*
+ * Copy wire data to or from the local wc string.
+ * Always exactly strlen_is elements.
+ */
bzero(&myref, sizeof (myref));
myref.enclosing = encl_ref;
myref.stream = encl_ref->stream;
myref.packed_alignment = 0;
myref.ti = &ndt__wchar;
myref.inner_flags = NDR_F_NONE;
myref.name = name;
myref.pdu_offset = encl_ref->pdu_offset;
+ myref.datum = (char *)wcs;
+ wlen = encl_ref->strlen_is;
! for (i = 0; i < wlen; i++) {
! (void) snprintf(name, sizeof (name), "[%lu]", i);
! if (!ndr_inner(&myref))
return (0);
! myref.pdu_offset += sizeof (ndr_wchar_t);
! myref.datum += sizeof (ndr_wchar_t);
! }
/*
! * If this is unmarshall, convert the local UCS-2 string
! * into a UTF-8 string in the caller's buffer. The caller
! * previously determined the space required and provides a
! * buffer of sufficient size.
*/
if (nds->m_op == NDR_M_OP_UNMARSHALL) {
! wcs[wlen] = 0;
! slen = ndr__wcstombs(valp, wcs, wlen);
! if (slen == (size_t)-1)
! return (0);
! valp[slen] = '\0';
}
return (1);
}
/*
* Converts a multibyte character string to a little-endian, wide-char
*** 1995,2047 ****
*
* Returns the number of wide characters converted, not counting
* any terminating null wide character. Returns -1 if an invalid
* multibyte character is encountered.
*/
size_t
! ndr_mbstowcs(ndr_stream_t *nds, smb_wchar_t *wcs, const char *mbs,
size_t nwchars)
{
! smb_wchar_t *start = wcs;
! int nbytes;
- while (nwchars--) {
- nbytes = ndr_mbtowc(nds, wcs, mbs, MTS_MB_CHAR_MAX);
- if (nbytes < 0) {
- *wcs = 0;
- return ((size_t)-1);
- }
-
- if (*mbs == 0)
- break;
-
- ++wcs;
- mbs += nbytes;
- }
-
- return (wcs - start);
- }
-
- /*
- * Converts a multibyte character to a little-endian, wide-char, which
- * is stored in wcharp. Up to nbytes bytes are examined.
- *
- * If mbchar is valid, returns the number of bytes processed in mbchar.
- * If mbchar is invalid, returns -1. See also smb_mbtowc().
- */
- /*ARGSUSED*/
- int
- ndr_mbtowc(ndr_stream_t *nds, smb_wchar_t *wcharp, const char *mbchar,
- size_t nbytes)
- {
- int rc;
-
- if ((rc = smb_mbtowc(wcharp, mbchar, nbytes)) < 0)
- return (rc);
-
#ifdef _BIG_ENDIAN
! if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND))
! *wcharp = BSWAP_16(*wcharp);
#endif
! return (rc);
}
--- 2000,2021 ----
*
* Returns the number of wide characters converted, not counting
* any terminating null wide character. Returns -1 if an invalid
* multibyte character is encountered.
*/
+ /* ARGSUSED */
size_t
! ndr_mbstowcs(ndr_stream_t *nds, ndr_wchar_t *wcs, const char *mbs,
size_t nwchars)
{
! size_t len;
#ifdef _BIG_ENDIAN
! if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND)) {
! /* Make WC string in LE order. */
! len = ndr__mbstowcs_le(wcs, mbs, nwchars);
! } else
#endif
+ len = ndr__mbstowcs(wcs, mbs, nwchars);
! return (len);
}