A problem in handling multibyte character (and more)
kawasa_r at itg.hitachi.co.jp
kawasa_r at itg.hitachi.co.jp
Thu Jan 15 15:35:06 GMT 2004
We've fixed three problems in samba3.0.0 so far. So I post patches for them. Maybe some of these problems are already fixed in the latest version, though.
[Problem-1]
The smbd is crushed when the file "test.txt" under the directory "test" is copied as "******(multi byte characters)test.txt" in the same directory.
[Cause]
In this case, the file name is exchanged from UTF-8(default setting of unix charset) to UCS-2,
then it is exchanged from capital letter to small letter.
If the invalid multi-byte character is included in the file name, exchange from UTF-8 to UCS-2 is failed. But smbd does not detect this error, so it try to exchange UTF-8 character(not UCS-2) from capital letter to small letter then segmentation violation is occurred.
(Invalid multi-byte character is created in the process of samba-300/source/smbd/open.c:line 76 to 77.)
[Countermeasure]
Check the result of iconv() which exchanges character code.
-------------
Index: samba-300/source/lib/charcnv.c
===================================================================
RCS file: /cvs/samba-300/source/lib/charcnv.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- samba-300/source/lib/charcnv.c 1 Oct 2003 04:26:41 -0000 1.1
+++ samba-300/source/lib/charcnv.c 19 Nov 2003 04:22:24 -0000 1.2
@@ -373,7 +373,7 @@
**/
size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
- void const *src, size_t srclen, void **dest)
+ void const *src, size_t srclen, void **dest, int *as_is)
{
size_t i_len, o_len, destlen = MAX(srclen, 512);
size_t retval;
@@ -382,6 +382,7 @@
smb_iconv_t descriptor;
*dest = NULL;
+ *as_is = 0;
if (src == NULL || srclen == (size_t)-1)
return (size_t)-1;
@@ -466,6 +467,7 @@
use_as_is:
+ *as_is = 1;
/* conversion not supported, use as is */
{
if (srclen && (destlen != srclen)) {
@@ -502,9 +504,10 @@
void const *src, size_t srclen, void **dest)
{
size_t dest_len;
+ int as_is = 0;
*dest = NULL;
- dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest);
+ dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest, &as_is);
if (dest_len == (size_t)-1)
return (size_t)-1;
if (*dest == NULL)
@@ -516,11 +519,19 @@
{
size_t size;
smb_ucs2_t *buffer;
+ int as_is = 0;
- size = push_ucs2_allocate(&buffer, src);
+ size = push_ucs2_allocate(&buffer, src, &as_is);
if (size == -1) {
smb_panic("failed to create UCS2 buffer");
}
+ if (as_is) {
+ if (dest != src) {
+ size = convert_string(CH_UNIX, CH_UNIX, buffer, size, dest, destlen);
+ }
+ free(buffer);
+ return size;
+ }
if (!strupper_w(buffer) && (dest == src)) {
free(buffer);
return srclen;
@@ -582,12 +593,20 @@
{
size_t size;
smb_ucs2_t *buffer;
-
+ int as_is = 0;
+
size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen,
- (void **) &buffer);
+ (void **) &buffer, &as_is);
if (size == -1) {
smb_panic("failed to create UCS2 buffer");
}
+ if (as_is) {
+ if (dest != src) {
+ size = convert_string(CH_UNIX, CH_UNIX, buffer, size, dest, destlen);
+ }
+ free(buffer);
+ return size;
+ }
if (!strlower_w(buffer) && (dest == src)) {
free(buffer);
return srclen;
@@ -606,8 +625,9 @@
size_t size;
smb_ucs2_t *buffer;
char *out_buffer;
+ int as_is = 0;
- size = push_ucs2_allocate(&buffer, s);
+ size = push_ucs2_allocate(&buffer, s, &as_is);
if (size == -1) {
return NULL;
}
@@ -826,12 +846,12 @@
* or -1 in case of error.
**/
-size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
+size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src, int *as_is)
{
size_t src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
+ return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest, as_is);
}
/**
@@ -897,9 +917,10 @@
size_t push_utf8_allocate(char **dest, const char *src)
{
size_t src_len = strlen(src)+1;
+ int as_is = 0;
*dest = NULL;
- return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
+ return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, &as_is);
}
/**
@@ -984,9 +1005,10 @@
size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
{
+ int as_is = 0;
size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
*dest = NULL;
- return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
+ return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest, &as_is);
}
/**
@@ -1014,9 +1036,10 @@
size_t pull_utf8_allocate(void **dest, const char *src)
{
+ int as_is = 0;
size_t src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, dest);
+ return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, dest, &as_is);
}
/**
Index: samba-300/source/libsmb/climessage.c
===================================================================
RCS file: /cvs/samba-300/source/libsmb/climessage.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- samba-300/source/libsmb/climessage.c 1 Oct 2003 04:26:42 -0000 1.1
+++ samba-300/source/libsmb/climessage.c 19 Nov 2003 04:24:56 -0000 1.2
@@ -75,6 +75,7 @@
char *msgdos;
int lendos;
char *p;
+ int as_is = 0;
memset(cli->outbuf,'\0',smb_size);
set_message(cli->outbuf,1,0,True);
@@ -87,7 +88,7 @@
p = smb_buf(cli->outbuf);
*p++ = 1;
- if ((lendos = convert_string_allocate(NULL,CH_UNIX, CH_DOS, msg,len, (void **) &msgdos)) < 0 || !msgdos) {
+ if ((lendos = convert_string_allocate(NULL,CH_UNIX, CH_DOS, msg,len, (void **) &msgdos, &as_is)) < 0 || !msgdos) {
DEBUG(3,("Conversion failed, sending message in UNIX charset\n"));
SSVAL(p, 0, len); p += 2;
memcpy(p, msg, len);
Index: samba-300/source/smbd/mangle_hash.c
===================================================================
RCS file: /cvs/samba-300/source/smbd/mangle_hash.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- samba-300/source/smbd/mangle_hash.c 1 Oct 2003 04:26:43 -0000 1.1
+++ samba-300/source/smbd/mangle_hash.c 19 Nov 2003 04:25:21 -0000 1.2
@@ -314,6 +314,7 @@
smb_ucs2_t *ucs2name;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
size_t size;
+ int as_is = 0;
if (!fname || !*fname)
return False;
@@ -325,7 +326,7 @@
if (strlen(f) > 12)
return False;
- size = push_ucs2_allocate(&ucs2name, f);
+ size = push_ucs2_allocate(&ucs2name, f, &as_is);
if (size == (size_t)-1) {
DEBUG(0,("is_8_3: internal error push_ucs2_allocate() failed!\n"));
goto done;
@@ -729,10 +730,11 @@
static void name_map(char *OutName, BOOL need83, BOOL cache83)
{
smb_ucs2_t *OutName_ucs2;
+ int as_is = 0;
DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName,
need83 ? "True" : "False", cache83 ? "True" : "False"));
- if (push_ucs2_allocate(&OutName_ucs2, OutName) == (size_t)-1) {
+ if (push_ucs2_allocate(&OutName_ucs2, OutName, &as_is) == (size_t)-1) {
DEBUG(0, ("push_ucs2_allocate failed!\n"));
return;
}
Index: samba-300/source/smbd/message.c
===================================================================
RCS file: /cvs/samba-300/source/smbd/message.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- samba-300/source/smbd/message.c 1 Oct 2003 04:26:43 -0000 1.1
+++ samba-300/source/smbd/message.c 19 Nov 2003 04:25:25 -0000 1.2
@@ -43,6 +43,7 @@
int fd;
char *msg;
int len;
+ int as_is = 0;
if (! (*lp_msg_command()))
{
@@ -64,7 +65,7 @@
* Incoming message is in DOS codepage format. Convert to UNIX.
*/
- if ((len = convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg)) < 0 || !msg) {
+ if ((len = convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg, &as_is)) < 0 || !msg) {
DEBUG(3,("Conversion failed, delivering message in DOS codepage format\n"));
for (i = 0; i < msgpos;) {
if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') {
Index: samba-300/source/libsmb/smbencrypt.c
===================================================================
RCS file: /cvs/samba-300/source/libsmb/smbencrypt.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- samba-300/source/libsmb/smbencrypt.c 1 Oct 2003 04:26:42 -0000 1.1
+++ samba-300/source/libsmb/smbencrypt.c 19 Nov 2003 04:25:07 -0000 1.2
@@ -127,14 +127,16 @@
size_t domain_byte_len;
HMACMD5Context ctx;
+ int as_is = 0;
- user_byte_len = push_ucs2_allocate(&user, user_in);
+ user_byte_len = push_ucs2_allocate(&user, user_in, &as_is);
if (user_byte_len == (size_t)-1) {
DEBUG(0, ("push_uss2_allocate() for user returned -1 (probably malloc() failure)\n"));
return False;
}
- domain_byte_len = push_ucs2_allocate(&domain, domain_in);
+ as_is = 0;
+ domain_byte_len = push_ucs2_allocate(&domain, domain_in, &as_is);
if (domain_byte_len == (size_t)-1) {
DEBUG(0, ("push_uss2_allocate() for domain returned -1 (probably malloc() failure)\n"));
return False;
Index: samba-300/source/lib/util_str.c
===================================================================
RCS file: /cvs/samba-300/source/lib/util_str.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- samba-300/source/lib/util_str.c 1 Oct 2003 04:26:42 -0000 1.1
+++ samba-300/source/lib/util_str.c 19 Nov 2003 04:24:31 -0000 1.2
@@ -184,6 +184,7 @@
size_t size;
smb_ucs2_t *buffer_s, *buffer_t;
int ret;
+ int as_is = 0;
for (ps = s, pt = t; ; ps++, pt++) {
char us, ut;
@@ -208,14 +209,15 @@
return +1;
}
- size = push_ucs2_allocate(&buffer_s, s);
+ size = push_ucs2_allocate(&buffer_s, s, &as_is);
if (size == (size_t)-1) {
return strcmp(s, t);
/* Not quite the right answer, but finding the right one
under this failure case is expensive, and it's pretty close */
}
- size = push_ucs2_allocate(&buffer_t, t);
+ as_is = 0;
+ size = push_ucs2_allocate(&buffer_t, t, &as_is);
if (size == (size_t)-1) {
SAFE_FREE(buffer_s);
return strcmp(s, t);
[Problem-2]
When network error is occurred in case of receiving data from client, the smbd process does not finish until disconnecting time is over keepalive time.
[Cause]
In case of receiving data from client, the read() system call does not check error occurrence.
[Countermeasure]
Before read() is issued, add select() system call for checking timeout of network error.
-------------
Index: samba-300/source/lib/util_sock.c
===================================================================
RCS file: /cvs/samba-300/source/lib/util_sock.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- samba-300/source/lib/util_sock.c 1 Oct 2003 04:26:42 -0000 1.1
+++ samba-300/source/lib/util_sock.c 30 Oct 2003 14:27:10 -0000 1.2
@@ -327,9 +327,28 @@
ssize_t ret;
size_t total=0;
+ fd_set fds ;
+ ssize_t selrtn ;
+ struct timeval tv ;
+
smb_read_error = 0;
+ tv.tv_sec = 180 ;
+ tv.tv_usec = 0 ;
+
while (total < N) {
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds) ;
+
+ selrtn = sys_select_intr(fd + 1,&fds,NULL,NULL,&tv);
+ if (selrtn == -1 || selrtn == 0) {
+ DEBUG(0,("read_socket_data: timeout read. (read_data=%d) select error = %s.\n",
+ (int)(N - total), strerror(errno) ));
+ smb_read_error = READ_ERROR;
+ return -1 ;
+ }
+
ret = sys_read(fd,buffer + total,N - total);
if (ret == 0) {
[Problem-3]
The secrets.tbd file could not be changed by accessed NetBIOS name even if "%L" is set to "private dir" parameter in smb.conf.
[Cause]
When smbd is accessed fro client, it issues tdb_reopen_all() function.
But in this time, smbd does not receive NetBIOS name, so NetBIOS name is not set even if "%L" is set to "private dir" parameter.
[Countermeasure]
Re-open secrets.tdb when smbd received "session request" message from client.
-------------
Index: samba-300/source/smbd/reply.c
===================================================================
RCS file: /cvs/samba-300/source/smbd/reply.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- samba-300/source/smbd/reply.c 1 Oct 2003 04:26:43 -0000 1.1
+++ samba-300/source/smbd/reply.c 1 Oct 2003 07:33:31 -0000 1.2
@@ -116,6 +116,9 @@
reload_services(True);
reopen_logs();
+ if (!secrets_reopen())
+ DEBUG(0,("secrets_reopen failed.\n"));
+
claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
already_got_session = True;
Index: samba-300/source/passdb/secrets.c
===================================================================
RCS file: /cvs/samba-300/source/passdb/secrets.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- samba-300/source/passdb/secrets.c 1 Oct 2003 04:26:42 -0000 1.1
+++ samba-300/source/passdb/secrets.c 1 Oct 2003 07:33:18 -0000 1.2
@@ -49,6 +49,17 @@
return True;
}
+/* reopen the secrets database */
+BOOL secrets_reopen(void)
+{
+ if(tdb) {
+ tdb_close(tdb);
+ tdb = NULL;
+ }
+
+ return secrets_init();
+}
+
/* read a entry from the secrets database - the caller must free the result
if size is non-null then the size of the entry is put in there
*/
More information about the samba-technical
mailing list