summaryrefslogtreecommitdiff
path: root/source3/param
diff options
context:
space:
mode:
authorShyamsunder Rathi <shyam.rathi@nutanix.com>2019-05-12 23:06:17 -0700
committerAndreas Schneider <asn@cryptomilk.org>2019-05-16 17:55:18 +0000
commit0fa490e8476a2a5020ff2c253167b8a9454e8b97 (patch)
tree1bc69a034577c8b2021974374080a882b1e0dbe7 /source3/param
parent16cf1d1a531896c7cd2fb96a72d1e630b13e012f (diff)
downloadsamba-0fa490e8476a2a5020ff2c253167b8a9454e8b97.tar.gz
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>
Diffstat (limited to 'source3/param')
-rw-r--r--source3/param/loadparm.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 5af1621fb9b..5104a3408f1 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -4244,15 +4244,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;
}