Print this page
1575 untangle libmlrpc ... (libmlrpc)

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c
          +++ new/usr/src/lib/libmlrpc/common/ndr_process.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   * Copyright 2012 Milan Jurik. All rights reserved.
       25 + * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  25   26   */
  26   27  
  27   28  /*
  28   29   * Network Data Representation (NDR) is a compatible subset of the DCE RPC
  29   30   * and MSRPC NDR.  NDR is used to move parameters consisting of
  30   31   * complicated trees of data constructs between an RPC client and server.
  31   32   */
  32   33  
  33   34  #include <sys/byteorder.h>
  34   35  #include <strings.h>
  35   36  #include <assert.h>
  36   37  #include <string.h>
       38 +#include <stdio.h>
  37   39  #include <stdlib.h>
  38   40  
  39      -#include <smbsrv/libsmb.h>
  40      -#include <smbsrv/string.h>
  41      -#include <smbsrv/libmlrpc.h>
       41 +#include <libmlrpc.h>
       42 +#include <ndr_wchar.h>
  42   43  
  43      -#define NDR_STRING_MAX          4096
  44      -
  45   44  #define NDR_IS_UNION(T) \
  46   45          (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_UNION)
  47   46  #define NDR_IS_STRING(T)        \
  48   47          (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_STRING)
  49   48  
  50   49  extern ndr_typeinfo_t ndt_s_wchar;
  51   50  
  52   51  /*
  53   52   * The following synopsis describes the terms TOP-MOST, OUTER and INNER.
  54   53   *
↓ open down ↓ 1148 lines elided ↑ open up ↑
1203 1202                          return (0);
1204 1203                  }
1205 1204  
1206 1205                  if (outer_ref->backptr)
1207 1206                          assert(valp == *outer_ref->backptr);
1208 1207  
1209 1208                  if (ti == &ndt_s_wchar) {
1210 1209                          /*
1211 1210                           * size_is is the number of characters in the
1212 1211                           * (multibyte) string, including the null.
     1212 +                         * In other words, symbols, not bytes.
1213 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) {
     1214 +                        size_t wlen;
     1215 +                        wlen = ndr__mbstowcs(NULL, valp, NDR_STRING_MAX);
     1216 +                        if (wlen == (size_t)-1) {
     1217 +                                /* illegal sequence error? */
1221 1218                                  NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
1222 1219                                  return (0);
1223 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;
1224 1228                  } else {
1225 1229                          valp = outer_ref->datum;
1226 1230                          n_zeroes = 0;
1227 1231                          for (ix = 0; ix < NDR_STRING_MAX; ix++) {
1228 1232                                  if (valp[ix] == 0) {
1229 1233                                          n_zeroes++;
1230 1234                                          if (n_zeroes >= is_varlen &&
1231 1235                                              ix % is_varlen == 0) {
1232 1236                                                  break;
1233 1237                                          }
↓ open down ↓ 47 lines elided ↑ open up ↑
1281 1285                          return (0);
1282 1286                  }
1283 1287  
1284 1288                  if (ti == &ndt_s_wchar) {
1285 1289                          /*
1286 1290                           * Decoding Unicode to UTF-8; we need to allow
1287 1291                           * for the maximum possible char size. It would
1288 1292                           * be nice to use mbequiv_strlen but the string
1289 1293                           * may not be null terminated.
1290 1294                           */
1291      -                        n_alloc = (size_is + 1) * MTS_MB_CHAR_MAX;
     1295 +                        n_alloc = (size_is + 1) * NDR_MB_CHAR_MAX;
1292 1296                  } else {
1293 1297                          n_alloc = (size_is + 1) * is_varlen;
1294 1298                  }
1295 1299  
1296 1300                  valp = NDS_MALLOC(nds, n_alloc, outer_ref);
1297 1301                  if (!valp) {
1298 1302                          NDR_SET_ERROR(outer_ref, NDR_ERR_MALLOC_FAILED);
1299 1303                          return (0);
1300 1304                  }
1301 1305  
↓ open down ↓ 432 lines elided ↑ open up ↑
1734 1738          }
1735 1739  
1736 1740          bzero(&myref, sizeof (myref));
1737 1741          myref.enclosing = encl_ref;
1738 1742          myref.stream = encl_ref->stream;
1739 1743          myref.packed_alignment = 0;
1740 1744          myref.ti = ti;
1741 1745          myref.inner_flags = NDR_F_NONE;
1742 1746  
1743 1747          for (i = 0; i < n_elem; i++) {
1744      -                (void) sprintf(name, "[%lu]", i);
     1748 +                (void) snprintf(name, sizeof (name), "[%lu]", i);
1745 1749                  myref.name = name;
1746 1750                  myref.pdu_offset = pdu_offset + i * ti->pdu_size_fixed_part;
1747 1751                  myref.datum = encl_ref->datum + i * ti->c_size_fixed_part;
1748 1752  
1749 1753                  if (!ndr_inner(&myref))
1750 1754                          return (0);
1751 1755          }
1752 1756  
1753 1757          return (1);
1754 1758  }
↓ open down ↓ 34 lines elided ↑ open up ↑
1789 1793          return (ndr_string_basic_integer(ref, &ndt_##TYPE)); \
1790 1794  }
1791 1795  
1792 1796  #define MAKE_BASIC_TYPE(TYPE, SIZE) \
1793 1797          MAKE_BASIC_TYPE_BASE(TYPE, SIZE) \
1794 1798          MAKE_BASIC_TYPE_STRING(TYPE, SIZE)
1795 1799  
1796 1800  int ndr_basic_integer(ndr_ref_t *, unsigned);
1797 1801  int ndr_string_basic_integer(ndr_ref_t *, ndr_typeinfo_t *);
1798 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 */
1799 1810  
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)
     1811 +MAKE_BASIC_TYPE_BASE(_wchar, 2) /* ndt__wchar, ndt_s_wchar */
1806 1812  
1807      -MAKE_BASIC_TYPE_BASE(_wchar, 2)
1808      -
1809 1813  int
1810 1814  ndr_basic_integer(ndr_ref_t *ref, unsigned size)
1811 1815  {
1812 1816          ndr_stream_t    *nds = ref->stream;
1813 1817          char            *valp = (char *)ref->datum;
1814 1818          int             rc;
1815 1819  
1816 1820          switch (nds->m_op) {
1817 1821          case NDR_M_OP_MARSHALL:
1818 1822                  rc = NDS_PUT_PDU(nds, ref->pdu_offset, size,
↓ open down ↓ 28 lines elided ↑ open up ↑
1847 1851  
1848 1852          bzero(&myref, sizeof (myref));
1849 1853          myref.enclosing = encl_ref;
1850 1854          myref.stream = encl_ref->stream;
1851 1855          myref.packed_alignment = 0;
1852 1856          myref.ti = type_under;
1853 1857          myref.inner_flags = NDR_F_NONE;
1854 1858          myref.name = name;
1855 1859  
1856 1860          for (i = 0; i < NDR_STRING_MAX; i++) {
1857      -                (void) sprintf(name, "[%lu]", i);
     1861 +                (void) snprintf(name, sizeof (name), "[%lu]", i);
1858 1862                  myref.pdu_offset = pdu_offset + i * size;
1859 1863                  valp = encl_ref->datum + i * size;
1860 1864                  myref.datum = valp;
1861 1865  
1862 1866                  if (!ndr_inner(&myref))
1863 1867                          return (0);
1864 1868  
1865 1869                  switch (size) {
1866 1870                  case 1:         sense = *valp; break;
1867 1871                  /*LINTED E_BAD_PTR_CAST_ALIGN*/
↓ open down ↓ 22 lines elided ↑ open up ↑
1890 1894          1,              /* c_size_variable_part */
1891 1895  };
1892 1896  
1893 1897  
1894 1898  /*
1895 1899   * Hand coded wchar function because all strings are transported
1896 1900   * as wide characters. During NDR_M_OP_MARSHALL, we convert from
1897 1901   * multi-byte to wide characters. During NDR_M_OP_UNMARSHALL, we
1898 1902   * convert from wide characters to multi-byte.
1899 1903   *
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.
     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.
1909 1912   */
1910 1913  int
1911 1914  ndr_s_wchar(ndr_ref_t *encl_ref)
1912 1915  {
1913 1916          ndr_stream_t            *nds = encl_ref->stream;
1914      -        unsigned short          wide_char;
1915      -        char                    *valp;
     1917 +        char                    *valp = encl_ref->datum;
1916 1918          ndr_ref_t               myref;
1917      -        unsigned long           i;
1918 1919          char                    name[30];
1919      -        int                     count;
1920      -        int                     char_count = 0;
     1920 +        ndr_wchar_t             wcs[NDR_STRING_MAX+1];
     1921 +        size_t                  i, slen, wlen;
1921 1922  
     1923 +        /* This is enforced in ndr_outer_string() */
     1924 +        assert(encl_ref->strlen_is <= NDR_STRING_MAX);
     1925 +
1922 1926          if (nds->m_op == NDR_M_OP_UNMARSHALL) {
1923 1927                  /*
1924 1928                   * To avoid problems with zero length strings
1925 1929                   * we can just null terminate here and be done.
1926 1930                   */
1927 1931                  if (encl_ref->strlen_is == 0) {
1928 1932                          encl_ref->datum[0] = '\0';
1929 1933                          return (1);
1930 1934                  }
1931 1935          }
1932 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 +         */
1933 1960          bzero(&myref, sizeof (myref));
1934 1961          myref.enclosing = encl_ref;
1935 1962          myref.stream = encl_ref->stream;
1936 1963          myref.packed_alignment = 0;
1937 1964          myref.ti = &ndt__wchar;
1938 1965          myref.inner_flags = NDR_F_NONE;
1939      -        myref.datum = (char *)&wide_char;
1940 1966          myref.name = name;
1941 1967          myref.pdu_offset = encl_ref->pdu_offset;
     1968 +        myref.datum = (char *)wcs;
     1969 +        wlen = encl_ref->strlen_is;
1942 1970  
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      -
     1971 +        for (i = 0; i < wlen; i++) {
     1972 +                (void) snprintf(name, sizeof (name), "[%lu]", i);
1968 1973                  if (!ndr_inner(&myref))
1969 1974                          return (0);
     1975 +                myref.pdu_offset += sizeof (ndr_wchar_t);
     1976 +                myref.datum      += sizeof (ndr_wchar_t);
     1977 +        }
1970 1978  
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;
     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';
1986 1991          }
1987 1992  
1988 1993          return (1);
1989 1994  }
1990 1995  
1991 1996  /*
1992 1997   * Converts a multibyte character string to a little-endian, wide-char
1993 1998   * string.  No more than nwchars wide characters are stored.
1994 1999   * A terminating null wide character is appended if there is room.
1995 2000   *
1996 2001   * Returns the number of wide characters converted, not counting
1997 2002   * any terminating null wide character.  Returns -1 if an invalid
1998 2003   * multibyte character is encountered.
1999 2004   */
     2005 +/* ARGSUSED */
2000 2006  size_t
2001      -ndr_mbstowcs(ndr_stream_t *nds, smb_wchar_t *wcs, const char *mbs,
     2007 +ndr_mbstowcs(ndr_stream_t *nds, ndr_wchar_t *wcs, const char *mbs,
2002 2008      size_t nwchars)
2003 2009  {
2004      -        smb_wchar_t *start = wcs;
2005      -        int nbytes;
     2010 +        size_t len;
2006 2011  
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 2012  #ifdef _BIG_ENDIAN
2042      -        if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND))
2043      -                *wcharp = BSWAP_16(*wcharp);
     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
2044 2017  #endif
     2018 +                len = ndr__mbstowcs(wcs, mbs, nwchars);
2045 2019  
2046      -        return (rc);
     2020 +        return (len);
2047 2021  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX