5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Milan Jurik. All rights reserved.
25 */
26
27 /*
28 * Network Data Representation (NDR) is a compatible subset of the DCE RPC
29 * and MSRPC NDR. NDR is used to move parameters consisting of
30 * complicated trees of data constructs between an RPC client and server.
31 */
32
33 #include <sys/byteorder.h>
34 #include <strings.h>
35 #include <assert.h>
36 #include <string.h>
37 #include <stdlib.h>
38
39 #include <smbsrv/libsmb.h>
40 #include <smbsrv/string.h>
41 #include <smbsrv/libmlrpc.h>
42
43 #define NDR_STRING_MAX 4096
44
45 #define NDR_IS_UNION(T) \
46 (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_UNION)
47 #define NDR_IS_STRING(T) \
48 (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_STRING)
49
50 extern ndr_typeinfo_t ndt_s_wchar;
51
52 /*
53 * The following synopsis describes the terms TOP-MOST, OUTER and INNER.
54 *
55 * Each parameter (call arguments and return values) is a TOP-MOST item.
56 * A TOP-MOST item consists of one or more OUTER items. An OUTER item
57 * consists of one or more INNER items. There are important differences
58 * between each kind, which, primarily, have to do with the allocation
59 * of memory to contain data structures and the order of processing.
60 *
61 * This is most easily demonstrated with a short example.
62 * Consider these structures:
63 *
64 * struct top_param {
1193 n_fixed = 0;
1194
1195 if (!ndr_outer_grow(outer_ref, n_hdr))
1196 return (0); /* error already set */
1197
1198 switch (nds->m_op) {
1199 case NDR_M_OP_MARSHALL:
1200 valp = outer_ref->datum;
1201 if (!valp) {
1202 NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
1203 return (0);
1204 }
1205
1206 if (outer_ref->backptr)
1207 assert(valp == *outer_ref->backptr);
1208
1209 if (ti == &ndt_s_wchar) {
1210 /*
1211 * size_is is the number of characters in the
1212 * (multibyte) string, including the null.
1213 */
1214 size_is = smb_wcequiv_strlen(valp) /
1215 sizeof (smb_wchar_t);
1216
1217 if (!(nds->flags & NDS_F_NONULL))
1218 ++size_is;
1219
1220 if (size_is > NDR_STRING_MAX) {
1221 NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
1222 return (0);
1223 }
1224 } else {
1225 valp = outer_ref->datum;
1226 n_zeroes = 0;
1227 for (ix = 0; ix < NDR_STRING_MAX; ix++) {
1228 if (valp[ix] == 0) {
1229 n_zeroes++;
1230 if (n_zeroes >= is_varlen &&
1231 ix % is_varlen == 0) {
1232 break;
1233 }
1234 } else {
1235 n_zeroes = 0;
1236 }
1237 }
1238 if (ix >= NDR_STRING_MAX) {
1239 NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
1240 return (0);
1241 }
1242 size_is = ix+1;
1243 }
1271 * size_is = 261 (0x105)
1272 * first_is = 0
1273 * length_is = 53 (0x35)
1274 *
1275 * The length_is was correct (for the given path) but the
1276 * size_is was the maximum path length rather than being
1277 * related to length_is.
1278 */
1279 if (first_is != 0) {
1280 NDR_SET_ERROR(outer_ref, NDR_ERR_STRING_SIZING);
1281 return (0);
1282 }
1283
1284 if (ti == &ndt_s_wchar) {
1285 /*
1286 * Decoding Unicode to UTF-8; we need to allow
1287 * for the maximum possible char size. It would
1288 * be nice to use mbequiv_strlen but the string
1289 * may not be null terminated.
1290 */
1291 n_alloc = (size_is + 1) * MTS_MB_CHAR_MAX;
1292 } else {
1293 n_alloc = (size_is + 1) * is_varlen;
1294 }
1295
1296 valp = NDS_MALLOC(nds, n_alloc, outer_ref);
1297 if (!valp) {
1298 NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
1299 return (0);
1300 }
1301
1302 bzero(valp, (size_is+1) * is_varlen);
1303
1304 if (outer_ref->backptr)
1305 *outer_ref->backptr = valp;
1306 outer_ref->datum = valp;
1307 break;
1308
1309 default:
1310 NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
1311 return (0);
1724 char name[30];
1725
1726 if (encl_ref->inner_flags & NDR_F_SIZE_IS) {
1727 /* now is the time to check/set size */
1728 if (!ndr_size_is(encl_ref))
1729 return (0); /* error already set */
1730 n_elem = encl_ref->size_is;
1731 } else {
1732 assert(encl_ref->inner_flags & NDR_F_DIMENSION_IS);
1733 n_elem = encl_ref->dimension_is;
1734 }
1735
1736 bzero(&myref, sizeof (myref));
1737 myref.enclosing = encl_ref;
1738 myref.stream = encl_ref->stream;
1739 myref.packed_alignment = 0;
1740 myref.ti = ti;
1741 myref.inner_flags = NDR_F_NONE;
1742
1743 for (i = 0; i < n_elem; i++) {
1744 (void) sprintf(name, "[%lu]", i);
1745 myref.name = name;
1746 myref.pdu_offset = pdu_offset + i * ti->pdu_size_fixed_part;
1747 myref.datum = encl_ref->datum + i * ti->c_size_fixed_part;
1748
1749 if (!ndr_inner(&myref))
1750 return (0);
1751 }
1752
1753 return (1);
1754 }
1755
1756
1757 /*
1758 * BASIC TYPES
1759 */
1760 #define MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
1761 extern int ndr_##TYPE(struct ndr_reference *encl_ref); \
1762 ndr_typeinfo_t ndt_##TYPE = { \
1763 1, /* NDR version */ \
1764 (SIZE)-1, /* alignment */ \
1779 1, /* NDR version */ \
1780 (SIZE)-1, /* alignment */ \
1781 NDR_F_STRING, /* flags */ \
1782 ndr_s##TYPE, /* ndr_func */ \
1783 0, /* pdu_size_fixed_part */ \
1784 SIZE, /* pdu_size_variable_part */ \
1785 0, /* c_size_fixed_part */ \
1786 SIZE, /* c_size_variable_part */ \
1787 }; \
1788 int ndr_s##TYPE(struct ndr_reference *ref) { \
1789 return (ndr_string_basic_integer(ref, &ndt_##TYPE)); \
1790 }
1791
1792 #define MAKE_BASIC_TYPE(TYPE, SIZE) \
1793 MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
1794 MAKE_BASIC_TYPE_STRING(TYPE, SIZE)
1795
1796 int ndr_basic_integer(ndr_ref_t *, unsigned);
1797 int ndr_string_basic_integer(ndr_ref_t *, ndr_typeinfo_t *);
1798
1799
1800 MAKE_BASIC_TYPE(_char, 1)
1801 MAKE_BASIC_TYPE(_uchar, 1)
1802 MAKE_BASIC_TYPE(_short, 2)
1803 MAKE_BASIC_TYPE(_ushort, 2)
1804 MAKE_BASIC_TYPE(_long, 4)
1805 MAKE_BASIC_TYPE(_ulong, 4)
1806
1807 MAKE_BASIC_TYPE_BASE(_wchar, 2)
1808
1809 int
1810 ndr_basic_integer(ndr_ref_t *ref, unsigned size)
1811 {
1812 ndr_stream_t *nds = ref->stream;
1813 char *valp = (char *)ref->datum;
1814 int rc;
1815
1816 switch (nds->m_op) {
1817 case NDR_M_OP_MARSHALL:
1818 rc = NDS_PUT_PDU(nds, ref->pdu_offset, size,
1819 valp, nds->swap, ref);
1820 break;
1821
1822 case NDR_M_OP_UNMARSHALL:
1823 rc = NDS_GET_PDU(nds, ref->pdu_offset, size,
1824 valp, nds->swap, ref);
1825 break;
1826
1827 default:
1828 NDR_SET_ERROR(ref, NDR_ERR_M_OP_INVALID);
1837 {
1838 unsigned long pdu_offset = encl_ref->pdu_offset;
1839 unsigned size = type_under->pdu_size_fixed_part;
1840 char *valp;
1841 ndr_ref_t myref;
1842 unsigned long i;
1843 long sense = 0;
1844 char name[30];
1845
1846 assert(size != 0);
1847
1848 bzero(&myref, sizeof (myref));
1849 myref.enclosing = encl_ref;
1850 myref.stream = encl_ref->stream;
1851 myref.packed_alignment = 0;
1852 myref.ti = type_under;
1853 myref.inner_flags = NDR_F_NONE;
1854 myref.name = name;
1855
1856 for (i = 0; i < NDR_STRING_MAX; i++) {
1857 (void) sprintf(name, "[%lu]", i);
1858 myref.pdu_offset = pdu_offset + i * size;
1859 valp = encl_ref->datum + i * size;
1860 myref.datum = valp;
1861
1862 if (!ndr_inner(&myref))
1863 return (0);
1864
1865 switch (size) {
1866 case 1: sense = *valp; break;
1867 /*LINTED E_BAD_PTR_CAST_ALIGN*/
1868 case 2: sense = *(short *)valp; break;
1869 /*LINTED E_BAD_PTR_CAST_ALIGN*/
1870 case 4: sense = *(long *)valp; break;
1871 }
1872
1873 if (!sense)
1874 break;
1875 }
1876
1877 return (1);
1880
1881 extern int ndr_s_wchar(ndr_ref_t *encl_ref);
1882 ndr_typeinfo_t ndt_s_wchar = {
1883 1, /* NDR version */
1884 2-1, /* alignment */
1885 NDR_F_STRING, /* flags */
1886 ndr_s_wchar, /* ndr_func */
1887 0, /* pdu_size_fixed_part */
1888 2, /* pdu_size_variable_part */
1889 0, /* c_size_fixed_part */
1890 1, /* c_size_variable_part */
1891 };
1892
1893
1894 /*
1895 * Hand coded wchar function because all strings are transported
1896 * as wide characters. During NDR_M_OP_MARSHALL, we convert from
1897 * multi-byte to wide characters. During NDR_M_OP_UNMARSHALL, we
1898 * convert from wide characters to multi-byte.
1899 *
1900 * It appeared that NT would sometimes leave a spurious character
1901 * in the data stream before the null wide_char, which would get
1902 * included in the string decode because we processed until the
1903 * null character. It now looks like NT does not always terminate
1904 * RPC Unicode strings and the terminating null is a side effect
1905 * of field alignment. So now we rely on the strlen_is (set up in
1906 * ndr_outer_string) of the enclosing reference. This may or may
1907 * not include the null but it doesn't matter, the algorithm will
1908 * get it right.
1909 */
1910 int
1911 ndr_s_wchar(ndr_ref_t *encl_ref)
1912 {
1913 ndr_stream_t *nds = encl_ref->stream;
1914 unsigned short wide_char;
1915 char *valp;
1916 ndr_ref_t myref;
1917 unsigned long i;
1918 char name[30];
1919 int count;
1920 int char_count = 0;
1921
1922 if (nds->m_op == NDR_M_OP_UNMARSHALL) {
1923 /*
1924 * To avoid problems with zero length strings
1925 * we can just null terminate here and be done.
1926 */
1927 if (encl_ref->strlen_is == 0) {
1928 encl_ref->datum[0] = '\0';
1929 return (1);
1930 }
1931 }
1932
1933 bzero(&myref, sizeof (myref));
1934 myref.enclosing = encl_ref;
1935 myref.stream = encl_ref->stream;
1936 myref.packed_alignment = 0;
1937 myref.ti = &ndt__wchar;
1938 myref.inner_flags = NDR_F_NONE;
1939 myref.datum = (char *)&wide_char;
1940 myref.name = name;
1941 myref.pdu_offset = encl_ref->pdu_offset;
1942
1943 valp = encl_ref->datum;
1944 count = 0;
1945
1946 for (i = 0; i < NDR_STRING_MAX; i++) {
1947 (void) sprintf(name, "[%lu]", i);
1948
1949 if (nds->m_op == NDR_M_OP_MARSHALL) {
1950 count = smb_mbtowc((smb_wchar_t *)&wide_char, valp,
1951 MTS_MB_CHAR_MAX);
1952 if (count < 0) {
1953 return (0);
1954 } else if (count == 0) {
1955 if (encl_ref->strlen_is != encl_ref->size_is)
1956 break;
1957
1958 /*
1959 * If the input char is 0, mbtowc
1960 * returns 0 without setting wide_char.
1961 * Set wide_char to 0 and a count of 1.
1962 */
1963 wide_char = *valp;
1964 count = 1;
1965 }
1966 }
1967
1968 if (!ndr_inner(&myref))
1969 return (0);
1970
1971 if (nds->m_op == NDR_M_OP_UNMARSHALL) {
1972 count = smb_wctomb(valp, wide_char);
1973
1974 if ((++char_count) == encl_ref->strlen_is) {
1975 valp += count;
1976 *valp = '\0';
1977 break;
1978 }
1979 }
1980
1981 if (!wide_char)
1982 break;
1983
1984 myref.pdu_offset += sizeof (wide_char);
1985 valp += count;
1986 }
1987
1988 return (1);
1989 }
1990
1991 /*
1992 * Converts a multibyte character string to a little-endian, wide-char
1993 * string. No more than nwchars wide characters are stored.
1994 * A terminating null wide character is appended if there is room.
1995 *
1996 * Returns the number of wide characters converted, not counting
1997 * any terminating null wide character. Returns -1 if an invalid
1998 * multibyte character is encountered.
1999 */
2000 size_t
2001 ndr_mbstowcs(ndr_stream_t *nds, smb_wchar_t *wcs, const char *mbs,
2002 size_t nwchars)
2003 {
2004 smb_wchar_t *start = wcs;
2005 int nbytes;
2006
2007 while (nwchars--) {
2008 nbytes = ndr_mbtowc(nds, wcs, mbs, MTS_MB_CHAR_MAX);
2009 if (nbytes < 0) {
2010 *wcs = 0;
2011 return ((size_t)-1);
2012 }
2013
2014 if (*mbs == 0)
2015 break;
2016
2017 ++wcs;
2018 mbs += nbytes;
2019 }
2020
2021 return (wcs - start);
2022 }
2023
2024 /*
2025 * Converts a multibyte character to a little-endian, wide-char, which
2026 * is stored in wcharp. Up to nbytes bytes are examined.
2027 *
2028 * If mbchar is valid, returns the number of bytes processed in mbchar.
2029 * If mbchar is invalid, returns -1. See also smb_mbtowc().
2030 */
2031 /*ARGSUSED*/
2032 int
2033 ndr_mbtowc(ndr_stream_t *nds, smb_wchar_t *wcharp, const char *mbchar,
2034 size_t nbytes)
2035 {
2036 int rc;
2037
2038 if ((rc = smb_mbtowc(wcharp, mbchar, nbytes)) < 0)
2039 return (rc);
2040
2041 #ifdef _BIG_ENDIAN
2042 if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND))
2043 *wcharp = BSWAP_16(*wcharp);
2044 #endif
2045
2046 return (rc);
2047 }
|
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Milan Jurik. All rights reserved.
25 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 /*
29 * Network Data Representation (NDR) is a compatible subset of the DCE RPC
30 * and MSRPC NDR. NDR is used to move parameters consisting of
31 * complicated trees of data constructs between an RPC client and server.
32 */
33
34 #include <sys/byteorder.h>
35 #include <strings.h>
36 #include <assert.h>
37 #include <string.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40
41 #include <libmlrpc.h>
42 #include <ndr_wchar.h>
43
44 #define NDR_IS_UNION(T) \
45 (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_UNION)
46 #define NDR_IS_STRING(T) \
47 (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_STRING)
48
49 extern ndr_typeinfo_t ndt_s_wchar;
50
51 /*
52 * The following synopsis describes the terms TOP-MOST, OUTER and INNER.
53 *
54 * Each parameter (call arguments and return values) is a TOP-MOST item.
55 * A TOP-MOST item consists of one or more OUTER items. An OUTER item
56 * consists of one or more INNER items. There are important differences
57 * between each kind, which, primarily, have to do with the allocation
58 * of memory to contain data structures and the order of processing.
59 *
60 * This is most easily demonstrated with a short example.
61 * Consider these structures:
62 *
63 * struct top_param {
1192 n_fixed = 0;
1193
1194 if (!ndr_outer_grow(outer_ref, n_hdr))
1195 return (0); /* error already set */
1196
1197 switch (nds->m_op) {
1198 case NDR_M_OP_MARSHALL:
1199 valp = outer_ref->datum;
1200 if (!valp) {
1201 NDR_SET_ERROR(outer_ref, NDR_ERR_OUTER_PARAMS_BAD);
1202 return (0);
1203 }
1204
1205 if (outer_ref->backptr)
1206 assert(valp == *outer_ref->backptr);
1207
1208 if (ti == &ndt_s_wchar) {
1209 /*
1210 * size_is is the number of characters in the
1211 * (multibyte) string, including the null.
1212 * In other words, symbols, not bytes.
1213 */
1214 size_t wlen;
1215 wlen = ndr__mbstowcs(NULL, valp, NDR_STRING_MAX);
1216 if (wlen == (size_t)-1) {
1217 /* illegal sequence error? */
1218 NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
1219 return (0);
1220 }
1221 if ((nds->flags & NDS_F_NONULL) == 0)
1222 wlen++;
1223 if (wlen > NDR_STRING_MAX) {
1224 NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
1225 return (0);
1226 }
1227 size_is = wlen;
1228 } else {
1229 valp = outer_ref->datum;
1230 n_zeroes = 0;
1231 for (ix = 0; ix < NDR_STRING_MAX; ix++) {
1232 if (valp[ix] == 0) {
1233 n_zeroes++;
1234 if (n_zeroes >= is_varlen &&
1235 ix % is_varlen == 0) {
1236 break;
1237 }
1238 } else {
1239 n_zeroes = 0;
1240 }
1241 }
1242 if (ix >= NDR_STRING_MAX) {
1243 NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
1244 return (0);
1245 }
1246 size_is = ix+1;
1247 }
1275 * size_is = 261 (0x105)
1276 * first_is = 0
1277 * length_is = 53 (0x35)
1278 *
1279 * The length_is was correct (for the given path) but the
1280 * size_is was the maximum path length rather than being
1281 * related to length_is.
1282 */
1283 if (first_is != 0) {
1284 NDR_SET_ERROR(outer_ref, NDR_ERR_STRING_SIZING);
1285 return (0);
1286 }
1287
1288 if (ti == &ndt_s_wchar) {
1289 /*
1290 * Decoding Unicode to UTF-8; we need to allow
1291 * for the maximum possible char size. It would
1292 * be nice to use mbequiv_strlen but the string
1293 * may not be null terminated.
1294 */
1295 n_alloc = (size_is + 1) * NDR_MB_CHAR_MAX;
1296 } else {
1297 n_alloc = (size_is + 1) * is_varlen;
1298 }
1299
1300 valp = NDS_MALLOC(nds, n_alloc, outer_ref);
1301 if (!valp) {
1302 NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
1303 return (0);
1304 }
1305
1306 bzero(valp, (size_is+1) * is_varlen);
1307
1308 if (outer_ref->backptr)
1309 *outer_ref->backptr = valp;
1310 outer_ref->datum = valp;
1311 break;
1312
1313 default:
1314 NDR_SET_ERROR(outer_ref, NDR_ERR_M_OP_INVALID);
1315 return (0);
1728 char name[30];
1729
1730 if (encl_ref->inner_flags & NDR_F_SIZE_IS) {
1731 /* now is the time to check/set size */
1732 if (!ndr_size_is(encl_ref))
1733 return (0); /* error already set */
1734 n_elem = encl_ref->size_is;
1735 } else {
1736 assert(encl_ref->inner_flags & NDR_F_DIMENSION_IS);
1737 n_elem = encl_ref->dimension_is;
1738 }
1739
1740 bzero(&myref, sizeof (myref));
1741 myref.enclosing = encl_ref;
1742 myref.stream = encl_ref->stream;
1743 myref.packed_alignment = 0;
1744 myref.ti = ti;
1745 myref.inner_flags = NDR_F_NONE;
1746
1747 for (i = 0; i < n_elem; i++) {
1748 (void) snprintf(name, sizeof (name), "[%lu]", i);
1749 myref.name = name;
1750 myref.pdu_offset = pdu_offset + i * ti->pdu_size_fixed_part;
1751 myref.datum = encl_ref->datum + i * ti->c_size_fixed_part;
1752
1753 if (!ndr_inner(&myref))
1754 return (0);
1755 }
1756
1757 return (1);
1758 }
1759
1760
1761 /*
1762 * BASIC TYPES
1763 */
1764 #define MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
1765 extern int ndr_##TYPE(struct ndr_reference *encl_ref); \
1766 ndr_typeinfo_t ndt_##TYPE = { \
1767 1, /* NDR version */ \
1768 (SIZE)-1, /* alignment */ \
1783 1, /* NDR version */ \
1784 (SIZE)-1, /* alignment */ \
1785 NDR_F_STRING, /* flags */ \
1786 ndr_s##TYPE, /* ndr_func */ \
1787 0, /* pdu_size_fixed_part */ \
1788 SIZE, /* pdu_size_variable_part */ \
1789 0, /* c_size_fixed_part */ \
1790 SIZE, /* c_size_variable_part */ \
1791 }; \
1792 int ndr_s##TYPE(struct ndr_reference *ref) { \
1793 return (ndr_string_basic_integer(ref, &ndt_##TYPE)); \
1794 }
1795
1796 #define MAKE_BASIC_TYPE(TYPE, SIZE) \
1797 MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
1798 MAKE_BASIC_TYPE_STRING(TYPE, SIZE)
1799
1800 int ndr_basic_integer(ndr_ref_t *, unsigned);
1801 int ndr_string_basic_integer(ndr_ref_t *, ndr_typeinfo_t *);
1802
1803 /* Comments to be nice to those searching for these types. */
1804 MAKE_BASIC_TYPE(_char, 1) /* ndt__char, ndt_s_char */
1805 MAKE_BASIC_TYPE(_uchar, 1) /* ndt__uchar, ndt_s_uchar */
1806 MAKE_BASIC_TYPE(_short, 2) /* ndt__short, ndt_s_short */
1807 MAKE_BASIC_TYPE(_ushort, 2) /* ndt__ushort, ndt_s_ushort */
1808 MAKE_BASIC_TYPE(_long, 4) /* ndt__long, ndt_s_long */
1809 MAKE_BASIC_TYPE(_ulong, 4) /* ndt__ulong, ndt_s_ulong */
1810
1811 MAKE_BASIC_TYPE_BASE(_wchar, 2) /* ndt__wchar, ndt_s_wchar */
1812
1813 int
1814 ndr_basic_integer(ndr_ref_t *ref, unsigned size)
1815 {
1816 ndr_stream_t *nds = ref->stream;
1817 char *valp = (char *)ref->datum;
1818 int rc;
1819
1820 switch (nds->m_op) {
1821 case NDR_M_OP_MARSHALL:
1822 rc = NDS_PUT_PDU(nds, ref->pdu_offset, size,
1823 valp, nds->swap, ref);
1824 break;
1825
1826 case NDR_M_OP_UNMARSHALL:
1827 rc = NDS_GET_PDU(nds, ref->pdu_offset, size,
1828 valp, nds->swap, ref);
1829 break;
1830
1831 default:
1832 NDR_SET_ERROR(ref, NDR_ERR_M_OP_INVALID);
1841 {
1842 unsigned long pdu_offset = encl_ref->pdu_offset;
1843 unsigned size = type_under->pdu_size_fixed_part;
1844 char *valp;
1845 ndr_ref_t myref;
1846 unsigned long i;
1847 long sense = 0;
1848 char name[30];
1849
1850 assert(size != 0);
1851
1852 bzero(&myref, sizeof (myref));
1853 myref.enclosing = encl_ref;
1854 myref.stream = encl_ref->stream;
1855 myref.packed_alignment = 0;
1856 myref.ti = type_under;
1857 myref.inner_flags = NDR_F_NONE;
1858 myref.name = name;
1859
1860 for (i = 0; i < NDR_STRING_MAX; i++) {
1861 (void) snprintf(name, sizeof (name), "[%lu]", i);
1862 myref.pdu_offset = pdu_offset + i * size;
1863 valp = encl_ref->datum + i * size;
1864 myref.datum = valp;
1865
1866 if (!ndr_inner(&myref))
1867 return (0);
1868
1869 switch (size) {
1870 case 1: sense = *valp; break;
1871 /*LINTED E_BAD_PTR_CAST_ALIGN*/
1872 case 2: sense = *(short *)valp; break;
1873 /*LINTED E_BAD_PTR_CAST_ALIGN*/
1874 case 4: sense = *(long *)valp; break;
1875 }
1876
1877 if (!sense)
1878 break;
1879 }
1880
1881 return (1);
1884
1885 extern int ndr_s_wchar(ndr_ref_t *encl_ref);
1886 ndr_typeinfo_t ndt_s_wchar = {
1887 1, /* NDR version */
1888 2-1, /* alignment */
1889 NDR_F_STRING, /* flags */
1890 ndr_s_wchar, /* ndr_func */
1891 0, /* pdu_size_fixed_part */
1892 2, /* pdu_size_variable_part */
1893 0, /* c_size_fixed_part */
1894 1, /* c_size_variable_part */
1895 };
1896
1897
1898 /*
1899 * Hand coded wchar function because all strings are transported
1900 * as wide characters. During NDR_M_OP_MARSHALL, we convert from
1901 * multi-byte to wide characters. During NDR_M_OP_UNMARSHALL, we
1902 * convert from wide characters to multi-byte.
1903 *
1904 * The most critical thing to get right in this function is to
1905 * marshall or unmarshall _exactly_ the number of elements the
1906 * OtW length specifies, as saved by the caller in: strlen_is.
1907 * Doing otherwise would leave us positioned at the wrong place
1908 * in the data stream for whatever follows this. Note that the
1909 * string data covered by strlen_is may or may not include any
1910 * null termination, but the converted string provided by the
1911 * caller or returned always has a null terminator.
1912 */
1913 int
1914 ndr_s_wchar(ndr_ref_t *encl_ref)
1915 {
1916 ndr_stream_t *nds = encl_ref->stream;
1917 char *valp = encl_ref->datum;
1918 ndr_ref_t myref;
1919 char name[30];
1920 ndr_wchar_t wcs[NDR_STRING_MAX+1];
1921 size_t i, slen, wlen;
1922
1923 /* This is enforced in ndr_outer_string() */
1924 assert(encl_ref->strlen_is <= NDR_STRING_MAX);
1925
1926 if (nds->m_op == NDR_M_OP_UNMARSHALL) {
1927 /*
1928 * To avoid problems with zero length strings
1929 * we can just null terminate here and be done.
1930 */
1931 if (encl_ref->strlen_is == 0) {
1932 encl_ref->datum[0] = '\0';
1933 return (1);
1934 }
1935 }
1936
1937 /*
1938 * If we're marshalling, convert the given string
1939 * from UTF-8 into a local UCS-2 string.
1940 */
1941 if (nds->m_op == NDR_M_OP_MARSHALL) {
1942 wlen = ndr__mbstowcs(wcs, valp, NDR_STRING_MAX);
1943 if (wlen == (size_t)-1)
1944 return (0);
1945 /*
1946 * Add a nulls to make strlen_is.
1947 * (always zero or one of them)
1948 * Then null terminate at wlen,
1949 * just for debug convenience.
1950 */
1951 while (wlen < encl_ref->strlen_is)
1952 wcs[wlen++] = 0;
1953 wcs[wlen] = 0;
1954 }
1955
1956 /*
1957 * Copy wire data to or from the local wc string.
1958 * Always exactly strlen_is elements.
1959 */
1960 bzero(&myref, sizeof (myref));
1961 myref.enclosing = encl_ref;
1962 myref.stream = encl_ref->stream;
1963 myref.packed_alignment = 0;
1964 myref.ti = &ndt__wchar;
1965 myref.inner_flags = NDR_F_NONE;
1966 myref.name = name;
1967 myref.pdu_offset = encl_ref->pdu_offset;
1968 myref.datum = (char *)wcs;
1969 wlen = encl_ref->strlen_is;
1970
1971 for (i = 0; i < wlen; i++) {
1972 (void) snprintf(name, sizeof (name), "[%lu]", i);
1973 if (!ndr_inner(&myref))
1974 return (0);
1975 myref.pdu_offset += sizeof (ndr_wchar_t);
1976 myref.datum += sizeof (ndr_wchar_t);
1977 }
1978
1979 /*
1980 * If this is unmarshall, convert the local UCS-2 string
1981 * into a UTF-8 string in the caller's buffer. The caller
1982 * previously determined the space required and provides a
1983 * buffer of sufficient size.
1984 */
1985 if (nds->m_op == NDR_M_OP_UNMARSHALL) {
1986 wcs[wlen] = 0;
1987 slen = ndr__wcstombs(valp, wcs, wlen);
1988 if (slen == (size_t)-1)
1989 return (0);
1990 valp[slen] = '\0';
1991 }
1992
1993 return (1);
1994 }
1995
1996 /*
1997 * Converts a multibyte character string to a little-endian, wide-char
1998 * string. No more than nwchars wide characters are stored.
1999 * A terminating null wide character is appended if there is room.
2000 *
2001 * Returns the number of wide characters converted, not counting
2002 * any terminating null wide character. Returns -1 if an invalid
2003 * multibyte character is encountered.
2004 */
2005 /* ARGSUSED */
2006 size_t
2007 ndr_mbstowcs(ndr_stream_t *nds, ndr_wchar_t *wcs, const char *mbs,
2008 size_t nwchars)
2009 {
2010 size_t len;
2011
2012 #ifdef _BIG_ENDIAN
2013 if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND)) {
2014 /* Make WC string in LE order. */
2015 len = ndr__mbstowcs_le(wcs, mbs, nwchars);
2016 } else
2017 #endif
2018 len = ndr__mbstowcs(wcs, mbs, nwchars);
2019
2020 return (len);
2021 }
|