Print this page
NEX-19025 CIFS gets confused with filenames containing enhanced Unicode
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
and: (fix build, check-rtime)
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-4458 Incorrect directory listing response for non-UNICODE clients
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-4029 Hang listing directory with fksmbd
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-3738 Should support SMB2_CAP_LARGE_MTU
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3611 CLONE NEX-3550 Replace smb2_enable with max_protocol
Reviewed by: Yuri Pankov <Yuri.Pankov@nexenta.com>
NEX-2353 Codenomicon: SMB2 TC # 448950 - PANIC in SMB2.Compounded-commands...
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-56 extended security NTLMSSP, inbound
SMB-48 Panic with smbtorture raw.scan-eamax
*** 20,30 ****
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
! * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* SMB mbuf marshaling encode/decode.
*/
--- 20,30 ----
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
! * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
*/
/*
* SMB mbuf marshaling encode/decode.
*/
*** 37,54 ****
#define DECODE_NO_ERROR 0
#define DECODE_NO_MORE_DATA 1
#define DECODE_ALLOCATION_ERROR 2
#define DECODE_CONVERSION_ERROR 3
- static int mbc_marshal_cstou8(char *, char *, size_t, char *, size_t);
static int mbc_marshal_make_room(mbuf_chain_t *, int32_t);
static void mbc_marshal_store_byte(mbuf_chain_t *, uint8_t);
static int mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t);
static int mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t);
static int mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t);
static int mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t);
! static int mbc_marshal_put_ascii_string(mbuf_chain_t *, char *, int);
static int mbc_marshal_put_unicode_string(mbuf_chain_t *, char *, int);
static int mbc_marshal_put_uio(mbuf_chain_t *, struct uio *);
static int mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m);
static int mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc);
static uint8_t mbc_marshal_fetch_byte(mbuf_chain_t *mbc);
--- 37,53 ----
#define DECODE_NO_ERROR 0
#define DECODE_NO_MORE_DATA 1
#define DECODE_ALLOCATION_ERROR 2
#define DECODE_CONVERSION_ERROR 3
static int mbc_marshal_make_room(mbuf_chain_t *, int32_t);
static void mbc_marshal_store_byte(mbuf_chain_t *, uint8_t);
static int mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t);
static int mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t);
static int mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t);
static int mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t);
! static int mbc_marshal_put_oem_string(mbuf_chain_t *, char *, int);
static int mbc_marshal_put_unicode_string(mbuf_chain_t *, char *, int);
static int mbc_marshal_put_uio(mbuf_chain_t *, struct uio *);
static int mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m);
static int mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc);
static uint8_t mbc_marshal_fetch_byte(mbuf_chain_t *mbc);
*** 56,69 ****
static int mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data);
static int mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data);
static uint64_t qswap(uint64_t ll);
static int mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data);
static int mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data);
! static int mbc_marshal_get_ascii_string(smb_request_t *, mbuf_chain_t *,
! uint8_t **ascii, int);
static int mbc_marshal_get_unicode_string(smb_request_t *, mbuf_chain_t *,
! uint8_t **, int);
static int mbc_marshal_get_mbufs(mbuf_chain_t *, int32_t, mbuf_t **);
static int mbc_marshal_get_mbuf_chain(mbuf_chain_t *, int32_t, mbuf_chain_t *);
static int mbc_marshal_get_uio(mbuf_chain_t *, struct uio *);
static int mbc_marshal_get_skip(mbuf_chain_t *, uint_t);
--- 55,68 ----
static int mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data);
static int mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data);
static uint64_t qswap(uint64_t ll);
static int mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data);
static int mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data);
! static int mbc_marshal_get_oem_string(smb_request_t *, mbuf_chain_t *,
! char **, int);
static int mbc_marshal_get_unicode_string(smb_request_t *, mbuf_chain_t *,
! char **, int);
static int mbc_marshal_get_mbufs(mbuf_chain_t *, int32_t, mbuf_t **);
static int mbc_marshal_get_mbuf_chain(mbuf_chain_t *, int32_t, mbuf_chain_t *);
static int mbc_marshal_get_uio(mbuf_chain_t *, struct uio *);
static int mbc_marshal_get_skip(mbuf_chain_t *, uint_t);
*** 150,160 ****
smb_mbc_vdecodef(mbuf_chain_t *mbc, const char *fmt, va_list ap)
{
uint8_t c;
uint8_t cval;
uint8_t *cvalp;
! uint8_t **cvalpp;
uint16_t wval;
uint16_t *wvalp;
uint32_t *lvalp;
uint64_t *llvalp;
smb_vdb_t *vdp;
--- 149,159 ----
smb_mbc_vdecodef(mbuf_chain_t *mbc, const char *fmt, va_list ap)
{
uint8_t c;
uint8_t cval;
uint8_t *cvalp;
! char **charpp;
uint16_t wval;
uint16_t *wvalp;
uint32_t *lvalp;
uint64_t *llvalp;
smb_vdb_t *vdp;
*** 292,302 ****
case 'L':
if (mbc_marshal_get_char(mbc, &cval) != 0)
return (-1);
if (cval != 2)
return (-1);
! goto ascii_conversion;
case 'A':
case 'S':
if (mbc_marshal_get_char(mbc, &cval) != 0)
return (-1);
--- 291,301 ----
case 'L':
if (mbc_marshal_get_char(mbc, &cval) != 0)
return (-1);
if (cval != 2)
return (-1);
! goto oem_conversion;
case 'A':
case 'S':
if (mbc_marshal_get_char(mbc, &cval) != 0)
return (-1);
*** 308,338 ****
case 'u': /* Convert from unicode if flags are set */
if (unicode)
goto unicode_translation;
/* FALLTHROUGH */
! case 's':
! ascii_conversion:
ASSERT(sr != NULL);
! cvalpp = va_arg(ap, uint8_t **);
if (!repc_specified)
repc = 0;
! if (mbc_marshal_get_ascii_string(sr,
! mbc, cvalpp, repc) != 0)
return (-1);
break;
! case 'U': /* Convert from unicode */
unicode_translation:
ASSERT(sr != 0);
! cvalpp = va_arg(ap, uint8_t **);
if (!repc_specified)
repc = 0;
- if (mbc->chain_offset & 1)
- mbc->chain_offset++;
if (mbc_marshal_get_unicode_string(sr,
! mbc, cvalpp, repc) != 0)
return (-1);
break;
case 'Y': /* dos time to unix time tt/dd */
lvalp = va_arg(ap, uint32_t *);
--- 307,335 ----
case 'u': /* Convert from unicode if flags are set */
if (unicode)
goto unicode_translation;
/* FALLTHROUGH */
! case 's': /* get OEM string */
! oem_conversion:
ASSERT(sr != NULL);
! charpp = va_arg(ap, char **);
if (!repc_specified)
repc = 0;
! if (mbc_marshal_get_oem_string(sr,
! mbc, charpp, repc) != 0)
return (-1);
break;
! case 'U': /* get UTF-16 string */
unicode_translation:
ASSERT(sr != 0);
! charpp = va_arg(ap, char **);
if (!repc_specified)
repc = 0;
if (mbc_marshal_get_unicode_string(sr,
! mbc, charpp, repc) != 0)
return (-1);
break;
case 'Y': /* dos time to unix time tt/dd */
lvalp = va_arg(ap, uint32_t *);
*** 517,526 ****
--- 514,524 ----
* U Align the offset of the mbuf chain on a 16bit boundary.
*/
int
smb_mbc_vencodef(mbuf_chain_t *mbc, const char *fmt, va_list ap)
{
+ char *charp;
uint8_t *cvalp;
timestruc_t *tvp;
smb_vdb_t *vdp;
smb_request_t *sr = NULL;
uint64_t llval;
*** 547,557 ****
repc_specified = B_TRUE;
} else if (c == '#') {
repc = va_arg(ap, int);
c = *fmt++;
repc_specified = B_TRUE;
-
}
switch (c) {
case '%':
sr = va_arg(ap, struct smb_request *);
--- 545,554 ----
*** 657,667 ****
break;
case 'L':
tag = 2;
! goto ascii_conversion;
case 'S':
case 'A':
tag = 4;
goto tagged_str;
--- 654,664 ----
break;
case 'L':
tag = 2;
! goto oem_conversion;
case 'S':
case 'A':
tag = 4;
goto tagged_str;
*** 678,696 ****
case 'u': /* Convert from unicode if flags are set */
if (unicode)
goto unicode_translation;
/* FALLTHROUGH */
! case 's': /* ASCII/multibyte string */
! ascii_conversion: cvalp = va_arg(ap, uint8_t *);
if (!repc_specified)
repc = 0;
! if (mbc_marshal_put_ascii_string(mbc,
! (char *)cvalp, repc) != 0)
return (DECODE_NO_MORE_DATA);
break;
case 'Y': /* int32_t, encode dos date/time */
while (repc-- > 0) {
uint16_t d, t;
lval = va_arg(ap, uint32_t);
--- 675,704 ----
case 'u': /* Convert from unicode if flags are set */
if (unicode)
goto unicode_translation;
/* FALLTHROUGH */
! case 's': /* put OEM string */
! oem_conversion:
! charp = va_arg(ap, char *);
if (!repc_specified)
repc = 0;
! if (mbc_marshal_put_oem_string(mbc,
! charp, repc) != 0)
return (DECODE_NO_MORE_DATA);
break;
+ case 'U': /* put UTF-16 string */
+ unicode_translation:
+ charp = va_arg(ap, char *);
+ if (!repc_specified)
+ repc = 0;
+ if (mbc_marshal_put_unicode_string(mbc,
+ charp, repc) != 0)
+ return (DECODE_NO_MORE_DATA);
+ break;
+
case 'Y': /* int32_t, encode dos date/time */
while (repc-- > 0) {
uint16_t d, t;
lval = va_arg(ap, uint32_t);
*** 726,747 ****
while (repc-- > 0)
if (mbc_marshal_put_char(mbc, 0) != 0)
return (DECODE_NO_MORE_DATA);
break;
- case 'U': /* Convert to unicode, align to word boundary */
- unicode_translation:
- if (mbc->chain_offset & 1)
- mbc->chain_offset++;
- cvalp = va_arg(ap, uint8_t *);
- if (!repc_specified)
- repc = 0;
- if (mbc_marshal_put_unicode_string(mbc,
- (char *)cvalp, repc) != 0)
- return (DECODE_NO_MORE_DATA);
- break;
-
default:
ASSERT(0);
return (-1);
}
}
--- 734,743 ----
*** 918,927 ****
--- 914,940 ----
return (0);
}
/*
+ * Put padding sufficient to align to A, where
+ * A is some power of 2 greater than zero.
+ */
+ int
+ smb_mbc_put_align(mbuf_chain_t *mbc, int align)
+ {
+ int mask = align - 1;
+ int padsz;
+
+ ASSERT(align > 0 && (align & mask) == 0);
+ if ((mbc->chain_offset & mask) == 0)
+ return (0);
+ padsz = align - (mbc->chain_offset & mask);
+ return (smb_mbc_encodef(mbc, "#.", padsz));
+ }
+
+ /*
* Put data into mbuf chain allocating as needed.
* Adds room to end of mbuf chain if needed.
*/
static int
mbc_marshal_make_room(mbuf_chain_t *mbc, int32_t bytes_needed)
*** 1066,1148 ****
mbc_marshal_store_byte(mbc, data >> 56);
return (0);
}
/*
! * When need to convert from UTF-8 (internal format) to a single
! * byte string (external format ) when marshalling a string.
*/
static int
! mbc_marshal_put_ascii_string(mbuf_chain_t *mbc, char *mbs, int repc)
{
! smb_wchar_t wide_char;
! int nbytes;
! int length;
! if ((length = smb_sbequiv_strlen(mbs)) == -1)
return (DECODE_NO_MORE_DATA);
! length += sizeof (char);
!
! if ((repc > 0) && (repc < length))
! length = repc;
! if (mbc_marshal_make_room(mbc, length))
return (DECODE_NO_MORE_DATA);
- while (*mbs) {
/*
! * We should restore oem chars here.
*/
! nbytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX);
! if (nbytes == -1)
! return (DECODE_NO_MORE_DATA);
! mbc_marshal_store_byte(mbc, (uint8_t)wide_char);
!
! if (wide_char & 0xFF00)
! mbc_marshal_store_byte(mbc, wide_char >> 8);
!
! mbs += nbytes;
}
! mbc_marshal_store_byte(mbc, 0);
! return (0);
}
static int
! mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *ascii, int repc)
{
! smb_wchar_t wchar;
! int consumed;
! int length;
! if ((length = smb_wcequiv_strlen(ascii)) == -1)
return (DECODE_NO_MORE_DATA);
! length += sizeof (smb_wchar_t);
! if ((repc > 0) && (repc < length))
! length = repc;
!
! if (mbc_marshal_make_room(mbc, length))
return (DECODE_NO_MORE_DATA);
! while (length > 0) {
! consumed = smb_mbtowc(&wchar, ascii, MTS_MB_CHAR_MAX);
! if (consumed == -1)
! break; /* Invalid sequence */
/*
! * Note that consumed will be 0 when the null terminator
! * is encountered and ascii will not be advanced beyond
! * that point. Length will continue to be decremented so
! * we won't get stuck here.
*/
! ascii += consumed;
mbc_marshal_store_byte(mbc, wchar);
mbc_marshal_store_byte(mbc, wchar >> 8);
! length -= sizeof (smb_wchar_t);
}
! return (0);
}
static int /*ARGSUSED*/
uiorefnoop(caddr_t p, int size, int adj)
{
--- 1079,1231 ----
mbc_marshal_store_byte(mbc, data >> 56);
return (0);
}
/*
! * Marshal a UTF-8 string (str) into mbc, converting to OEM codeset.
! * Also write a null unless the repc count limits the length we put.
! * When (repc > 0) the length we marshal must be exactly repc, and
! * truncate or pad the mbc data as necessary.
! * See also: msgbuf_put_oem_string
*/
static int
! mbc_marshal_put_oem_string(mbuf_chain_t *mbc, char *mbs, int repc)
{
! uint8_t *oembuf = NULL;
! uint8_t *s;
! int oemlen;
! int rlen;
! int rc;
! /*
! * Compute length of converted OEM string,
! * NOT including null terminator
! */
! if ((oemlen = smb_sbequiv_strlen(mbs)) == -1)
return (DECODE_NO_MORE_DATA);
! /*
! * If repc not specified, put whole string + NULL,
! * otherwise will truncate or pad as needed.
! */
! if (repc <= 0)
! repc = oemlen + 1;
! if (mbc_marshal_make_room(mbc, repc))
return (DECODE_NO_MORE_DATA);
/*
! * Convert into a temporary buffer
! * Free oembuf before return.
*/
! oembuf = smb_mem_zalloc(oemlen + 1);
! ASSERT(oembuf != NULL);
! rlen = smb_mbstooem(oembuf, mbs, oemlen);
! if (rlen < 0) {
! rc = DECODE_NO_MORE_DATA;
! goto out;
! }
! if (rlen > oemlen)
! rlen = oemlen;
! oembuf[rlen] = '\0';
! /*
! * Copy the converted string into the message,
! * truncated or paded as required.
! */
! s = oembuf;
! while (repc > 0) {
! mbc_marshal_store_byte(mbc, *s);
! if (*s != '\0')
! s++;
! repc--;
}
+ rc = 0;
! out:
! if (oembuf != NULL)
! smb_mem_free(oembuf);
! return (rc);
}
+ /*
+ * Marshal a UTF-8 string (str) into mbc, converting to UTF-16.
+ * Also write a null unless the repc count limits the length.
+ * When (repc > 0) the length we marshal must be exactly repc,
+ * and truncate or pad the mbc data as necessary.
+ * See also: msgbuf_put_unicode_string
+ */
static int
! mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *mbs, int repc)
{
! smb_wchar_t *wcsbuf = NULL;
! smb_wchar_t *wp;
! size_t wcslen, wcsbytes;
! size_t rlen;
! int rc;
! /* align to word boundary */
! if (mbc->chain_offset & 1) {
! if (mbc_marshal_make_room(mbc, 1))
return (DECODE_NO_MORE_DATA);
+ mbc_marshal_store_byte(mbc, 0);
+ }
! /*
! * Compute length of converted UTF-16 string,
! * NOT including null terminator (in bytes).
! */
! wcsbytes = smb_wcequiv_strlen(mbs);
! if (wcsbytes == (size_t)-1)
! return (DECODE_NO_MORE_DATA);
! /*
! * If repc not specified, put whole string + NULL,
! * otherwise will truncate or pad as needed.
! */
! if (repc <= 0)
! repc = wcsbytes + 2;
! if (mbc_marshal_make_room(mbc, repc))
return (DECODE_NO_MORE_DATA);
!
/*
! * Convert into a temporary buffer
! * Free wcsbuf before return.
*/
! wcslen = wcsbytes / 2;
! wcsbuf = smb_mem_zalloc(wcsbytes + 2);
! ASSERT(wcsbuf != NULL);
! rlen = smb_mbstowcs(wcsbuf, mbs, wcslen);
! if (rlen == (size_t)-1) {
! rc = DECODE_NO_MORE_DATA;
! goto out;
! }
! if (rlen > wcslen)
! rlen = wcslen;
! wcsbuf[rlen] = 0;
!
! /*
! * Copy the converted string into the message,
! * truncated or paded as required. Preserve
! * little-endian order while copying.
! */
! wp = wcsbuf;
! while (repc > 1) {
! smb_wchar_t wchar = LE_IN16(wp);
mbc_marshal_store_byte(mbc, wchar);
mbc_marshal_store_byte(mbc, wchar >> 8);
! if (wchar != 0)
! wp++;
! repc -= sizeof (smb_wchar_t);
}
! if (repc > 0)
! mbc_marshal_store_byte(mbc, 0);
!
! rc = 0;
! out:
! if (wcsbuf != NULL)
! smb_mem_free(wcsbuf);
! return (rc);
}
static int /*ARGSUSED*/
uiorefnoop(caddr_t p, int size, int adj)
{
*** 1373,1477 ****
}
return (0);
}
/*
! * mbc_marshal_get_ascii_string
*
! * The ascii string in smb includes oem chars. Since the
! * system needs utf8 encodes unicode char, conversion is
! * required to convert the oem char to unicode and then
! * to encode the converted wchars to utf8 format.
! * Therefore, the **ascii returned will be in such format
! * instead of the real ASCII format.
*/
static int
! mbc_marshal_get_ascii_string(
! smb_request_t *sr,
! mbuf_chain_t *mbc,
! uint8_t **ascii,
! int max_ascii)
{
! char *rcvbuf;
! char *ch;
! int max;
! int length = 0;
! max = MALLOC_QUANTUM;
! rcvbuf = smb_srm_zalloc(sr, max);
! if (max_ascii == 0)
! max_ascii = 0xffff;
!
! ch = rcvbuf;
for (;;) {
! while (length < max) {
! if (max_ascii-- <= 0) {
! *ch++ = 0;
! goto multibyte_encode;
}
! if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) {
! /* Data will never be available */
! return (DECODE_NO_MORE_DATA);
}
! if ((*ch++ = mbc_marshal_fetch_byte(mbc)) == 0)
! goto multibyte_encode;
! length++;
}
! max += MALLOC_QUANTUM;
! rcvbuf = smb_srm_rezalloc(sr, rcvbuf, max);
! ch = rcvbuf + length;
! }
- multibyte_encode:
/*
! * UTF-8 encode the string for internal system use.
*/
! length = strlen(rcvbuf) + 1;
! *ascii = smb_srm_zalloc(sr, length * MTS_MB_CHAR_MAX);
! return (mbc_marshal_cstou8("CP850", (char *)*ascii,
! (size_t)length * MTS_MB_CHAR_MAX, rcvbuf, (size_t)length));
}
static int
mbc_marshal_get_unicode_string(smb_request_t *sr,
! mbuf_chain_t *mbc, uint8_t **ascii, int max_unicode)
{
! int max;
! uint16_t wchar;
! char *ch;
! int emitted;
! int length = 0;
! if (max_unicode == 0)
! max_unicode = 0xffff;
! max = MALLOC_QUANTUM;
! *ascii = smb_srm_zalloc(sr, max);
! ch = (char *)*ascii;
for (;;) {
! while ((length + MTS_MB_CHAR_MAX) < max) {
! if (max_unicode <= 0)
! goto done;
! max_unicode -= 2;
! if (mbc_marshal_get_short(mbc, &wchar) != 0)
! return (DECODE_NO_MORE_DATA);
!
! if (wchar == 0) goto done;
!
! emitted = smb_wctomb(ch, wchar);
! length += emitted;
! ch += emitted;
}
! max += MALLOC_QUANTUM;
! *ascii = smb_srm_rezalloc(sr, *ascii, max);
! ch = (char *)*ascii + length;
}
! done: *ch = 0;
! return (0);
}
static int /*ARGSUSED*/
mbc_marshal_get_mbufs(mbuf_chain_t *mbc, int32_t bytes, mbuf_t **m)
{
--- 1456,1618 ----
}
return (0);
}
/*
! * mbc_marshal_get_oem_string
*
! * Decode an OEM string, returning its UTF-8 form in strpp,
! * allocated using smb_srm_zalloc (automatically freed).
! * If max_bytes != 0, consume at most max_bytes of the mbc.
! * See also: msgbuf_get_oem_string
*/
static int
! mbc_marshal_get_oem_string(smb_request_t *sr,
! mbuf_chain_t *mbc, char **strpp, int max_bytes)
{
! char *mbs;
! uint8_t *oembuf = NULL;
! int oemlen, oemmax;
! int mbsmax;
! int rlen;
! int rc;
! if (max_bytes == 0)
! max_bytes = 0xffff;
! /*
! * Get the OtW data into a temporary buffer.
! * Free oembuf before return.
! */
! oemlen = 0;
! oemmax = MALLOC_QUANTUM;
! oembuf = smb_mem_alloc(oemmax);
for (;;) {
! uint8_t ch;
!
! if (oemlen >= max_bytes)
! break;
! if ((oemlen + 2) >= oemmax) {
! oemmax += MALLOC_QUANTUM;
! oembuf = smb_mem_realloc(oembuf, oemmax);
}
! if (mbc_marshal_get_char(mbc, &ch) != 0) {
! rc = DECODE_NO_MORE_DATA;
! goto out;
}
! if (ch == 0)
! break;
! oembuf[oemlen++] = ch;
}
! oembuf[oemlen] = '\0';
/*
! * Get the buffer we'll return and convert to UTF-8.
! * May take as much as double the space.
*/
! mbsmax = oemlen * 2;
! mbs = smb_srm_zalloc(sr, mbsmax + 1);
! ASSERT(mbs != NULL);
! rlen = smb_oemtombs(mbs, oembuf, mbsmax);
! if (rlen < 0) {
! rc = DECODE_NO_MORE_DATA;
! goto out;
! }
! if (rlen > mbsmax)
! rlen = mbsmax;
! mbs[rlen] = '\0';
! *strpp = mbs;
! rc = 0;
!
! out:
! if (oembuf != NULL)
! smb_mem_free(oembuf);
! return (rc);
}
+ /*
+ * mbc_marshal_get_unicode_string
+ *
+ * Decode a UTF-16 string, returning its UTF-8 form in strpp,
+ * allocated using smb_srm_zalloc (automatically freed).
+ * If max_bytes != 0, consume at most max_bytes of the mbc.
+ * See also: msgbuf_get_unicode_string
+ */
static int
mbc_marshal_get_unicode_string(smb_request_t *sr,
! mbuf_chain_t *mbc, char **strpp, int max_bytes)
{
! char *mbs;
! uint16_t *wcsbuf = NULL;
! int wcslen; // wchar count
! int wcsmax; // byte count
! size_t mbsmax;
! size_t rlen;
! int rc;
! if (max_bytes == 0)
! max_bytes = 0xffff;
! /*
! * Unicode strings are always word aligned.
! */
! if (mbc->chain_offset & 1) {
! if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0)
! return (DECODE_NO_MORE_DATA);
! mbc->chain_offset++;
! }
! /*
! * Get the OtW data into a temporary buffer.
! * Free wcsbuf before return.
! */
! wcslen = 0;
! wcsmax = MALLOC_QUANTUM;
! wcsbuf = smb_mem_alloc(wcsmax);
for (;;) {
! uint16_t wchar;
! if ((wcslen * 2) >= max_bytes)
! break;
! if (((wcslen * 2) + 4) >= wcsmax) {
! wcsmax += MALLOC_QUANTUM;
! wcsbuf = smb_mem_realloc(wcsbuf, wcsmax);
}
! if (mbc_marshal_get_short(mbc, &wchar) != 0) {
! rc = DECODE_NO_MORE_DATA;
! goto out;
}
! if (wchar == 0)
! break;
! /* Keep in little-endian form. */
! LE_OUT16(wcsbuf + wcslen, wchar);
! wcslen++;
! }
! wcsbuf[wcslen] = 0;
!
! /*
! * Get the buffer we'll return and convert to UTF-8.
! * May take as much 4X number of wide chars.
! */
! mbsmax = wcslen * MTS_MB_CUR_MAX;
! mbs = smb_srm_zalloc(sr, mbsmax + 1);
! ASSERT(mbs != NULL);
! rlen = smb_wcstombs(mbs, wcsbuf, mbsmax);
! if (rlen == (size_t)-1) {
! rc = DECODE_NO_MORE_DATA;
! goto out;
! }
! if (rlen > mbsmax)
! rlen = mbsmax;
! mbs[rlen] = '\0';
! *strpp = mbs;
! rc = 0;
!
! out:
! if (wcsbuf != NULL)
! smb_mem_free(wcsbuf);
! return (rc);
}
static int /*ARGSUSED*/
mbc_marshal_get_mbufs(mbuf_chain_t *mbc, int32_t bytes, mbuf_t **m)
{
*** 1568,1599 ****
{
if (MBC_ROOM_FOR(mbc, skip) == 0)
return (DECODE_NO_MORE_DATA);
mbc->chain_offset += skip;
return (0);
- }
-
- /*
- * Converts oem string to UTF-8 string with an output string of max
- * maxconv bytes. The string may be truncated or not null-terminated if
- * there is not enough room.
- *
- * returns -1, cnt (partial conversion) or 0 (success)
- */
-
- static int
- mbc_marshal_cstou8(char *cs, char *outbuf, size_t maxconv,
- char *inbuf, size_t srcbytes)
- {
- kiconv_t t2u;
- size_t inlen = srcbytes;
- size_t outlen = maxconv;
- int err = 0;
- size_t rc;
-
- if ((t2u = kiconv_open("UTF-8", cs)) == (kiconv_t)-1)
- return (-1);
-
- rc = kiconv(t2u, &inbuf, &inlen, &outbuf, &outlen, &err);
- (void) kiconv_close(t2u);
- return ((int)rc);
}
--- 1709,1714 ----