1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-01 05:47:28 +03:00

s3:loadparm: Ensure to truncate FS Volume Label at multibyte boundary

For FS_VOLUME_INFO/FS_INFO operation, a maximum of 32 characters are
sent back. However, since Samba chops off any share name with >32
bytes at 32, it is possible that a multi-byte share name can get chopped
off between a full character. This causes the string decoding for unicode
failure which sends back NT_STATUS_ILLEGAL_CHARACTER (EILSEQ) to the client
applications.

On Windows, Notepad doesn't like it, and refuses to open a file in this
case and fails with the following error:

  Invalid character. For multibyte character sets, only the leading byte is
  included without the trailing byte. For Unicode character sets, include
  the characters 0xFFFF and 0xFFFE.

Proposed fix:
- Find the last starting point of a multibyte codepoint if the character
  at 32nd byte is a subsequent byte of a MB codepoint.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13947

Signed-off-by: Shyamsunder Rathi <shyam.rathi@nutanix.com>
Reviewed-by: Hemanth Thummala <hemanth.thummala@nutanix.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 0fa490e8476a2a5020ff2c253167b8a9454e8b97)
This commit is contained in:
Shyamsunder Rathi 2019-05-12 23:06:17 -07:00 committed by Karolin Seeger
parent 643c75aa2d
commit 4406c82955

View File

@ -4246,15 +4246,47 @@ const char *volume_label(TALLOC_CTX *ctx, int snum)
{
char *ret;
const char *label = lp_volume(ctx, snum);
size_t end = 32;
if (!*label) {
label = lp_servicename(ctx, snum);
}
/* This returns a 33 byte guarenteed null terminated string. */
ret = talloc_strndup(ctx, label, 32);
/*
* Volume label can be a max of 32 bytes. Make sure to truncate
* it at a codepoint boundary if it's longer than 32 and contains
* multibyte characters. Windows insists on a volume label being
* a valid mb sequence, and errors out if not.
*/
if (strlen(label) > 32) {
/*
* A MB char can be a max of 5 bytes, thus
* we should have a valid mb character at a
* minimum position of (32-5) = 27.
*/
while (end >= 27) {
/*
* Check if a codepoint starting from next byte
* is valid. If yes, then the current byte is the
* end of a MB or ascii sequence and the label can
* be safely truncated here. If not, keep going
* backwards till a valid codepoint is found.
*/
size_t len = 0;
const char *s = &label[end];
codepoint_t c = next_codepoint(s, &len);
if (c != INVALID_CODEPOINT) {
break;
}
end--;
}
}
/* This returns a max of 33 byte guarenteed null terminated string. */
ret = talloc_strndup(ctx, label, end);
if (!ret) {
return "";
}
}
return ret;
}