summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/lib/util.c9
-rw-r--r--source3/smbd/negprot.c6
-rw-r--r--source3/smbd/reply.c69
-rw-r--r--source3/smbd/srvstr.c186
5 files changed, 235 insertions, 37 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 7760b29522..a6e8dd32d9 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -195,7 +195,7 @@ SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \
smbd/posix_acls.o lib/msrpc-client.o lib/msrpc_use.o \
smbd/process.o smbd/service.o smbd/error.o \
- printing/printfsp.o lib/util_seaccess.o
+ printing/printfsp.o lib/util_seaccess.o smbd/srvstr.o
PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/print_cups.o printing/load.o
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 70513c068e..8ad2cfd713 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -354,6 +354,15 @@ void set_message_bcc(char *buf,int num_bytes)
}
/*******************************************************************
+ setup only the byte count for a smb message, using the end of the
+ message as a marker
+********************************************************************/
+void set_message_end(void *outbuf,void *end_ptr)
+{
+ set_message_bcc(outbuf,PTR_DIFF(end_ptr,smb_buf(outbuf)));
+}
+
+/*******************************************************************
reduce a file name, removing .. elements.
********************************************************************/
void dos_clean_name(char *s)
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 74d8eb3983..c2026f46f9 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -201,6 +201,12 @@ static int reply_nt1(char *outbuf)
capabilities |= CAP_RAW_MODE;
}
+
+ /* until the unicode conversion is complete have it disabled by default */
+ if (getenv("SMBD_USE_UNICODE")) {
+ capabilities |= CAP_UNICODE;
+ }
+
#ifdef WITH_MSDFS
if(lp_host_msdfs())
capabilities |= CAP_DFS;
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 4e87782a48..4f98c264b8 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -273,12 +273,11 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
pstring user;
pstring password;
pstring devicename;
- BOOL doencrypt = SMBENCRYPT();
int ecode = -1;
uint16 vuid = SVAL(inbuf,smb_uid);
int passlen = SVAL(inbuf,smb_vwv3);
- char *path;
- char *p;
+ pstring path;
+ char *p, *q;
START_PROFILE(SMBtconX);
*service = *user = *password = *devicename = 0;
@@ -294,7 +293,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
memcpy(password,smb_buf(inbuf),passlen);
password[passlen]=0;
- path = smb_buf(inbuf) + passlen;
+ p = smb_buf(inbuf) + passlen;
+ p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE|STR_CONVERT);
if (passlen != 24) {
if (strequal(password," "))
@@ -302,27 +302,20 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
passlen = strlen(password);
}
- p = strchr(path+2,'\\');
- if (!p) {
+ q = strchr(path+2,'\\');
+ if (!q) {
END_PROFILE(SMBtconX);
return(ERROR(ERRDOS,ERRnosuchshare));
}
- fstrcpy(service,p+1);
- p = strchr(service,'%');
- if (p) {
- *p++ = 0;
- fstrcpy(user,p);
+ fstrcpy(service,q+1);
+ q = strchr(service,'%');
+ if (q) {
+ *q++ = 0;
+ fstrcpy(user,q);
}
- StrnCpy(devicename,path + strlen(path) + 1,6);
- DEBUG(4,("Got device type %s\n",devicename));
+ p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_CONVERT);
- /*
- * Ensure the user and password names are in UNIX codepage format.
- */
-
- dos_to_unix(user,True);
- if (!doencrypt)
- dos_to_unix(password,True);
+ DEBUG(4,("Got device type %s\n",devicename));
/*
* Pass the user through the NT -> unix user mapping
@@ -349,13 +342,13 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
} else {
char *fsname = lp_fstype(SNUM(conn));
- set_message(outbuf,3,3,True);
+ set_message(outbuf,3,0,True);
p = smb_buf(outbuf);
- pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
- pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
+ p += srvstr_push(inbuf, outbuf, p, devicename, -1, STR_CONVERT|STR_TERMINATE);
+ p += srvstr_push(inbuf, outbuf, p, fsname, -1, STR_CONVERT|STR_TERMINATE);
- set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
+ set_message_end(outbuf,p);
/* what does setting this bit do? It is set by NT4 and
may affect the ability to autorun mounted cdroms */
@@ -703,10 +696,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int
BOOL valid_lm_password = False;
pstring user;
pstring orig_user;
+ fstring domain;
+ fstring native_os;
+ fstring native_lanman;
BOOL guest=False;
static BOOL done_sesssetup = False;
BOOL doencrypt = SMBENCRYPT();
- char *domain = "";
START_PROFILE(SMBsesssetupX);
*smb_apasswd = 0;
@@ -835,17 +830,19 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int
}
p += passlen1 + passlen2;
- fstrcpy(user,p);
- p = skip_string(p,1);
+ p += srvstr_pull(inbuf, user, p, sizeof(user), -1, STR_CONVERT|STR_TERMINATE);
/*
* Incoming user and domain are in DOS codepage format. Convert
* to UNIX.
*/
- dos_to_unix(user,True);
- domain = p;
- dos_to_unix(domain, True);
+ p += srvstr_pull(inbuf, domain, p, sizeof(domain),
+ -1, STR_CONVERT|STR_TERMINATE);
+ p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
+ -1, STR_CONVERT|STR_TERMINATE);
+ p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
+ -1, STR_CONVERT|STR_TERMINATE);
DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
- domain,skip_string(p,1),skip_string(p,2)));
+ domain,native_os,native_lanman));
}
DEBUG(3,("sesssetupX:name=[%s]\n",user));
@@ -1027,12 +1024,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int
set_message(outbuf,3,0,True);
} else {
char *p;
- set_message(outbuf,3,3,True);
+ set_message(outbuf,3,0,True);
p = smb_buf(outbuf);
- pstrcpy(p,"Unix"); p = skip_string(p,1);
- pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
- pstrcpy(p,global_myworkgroup); unix_to_dos(p, True); p = skip_string(p,1);
- set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
+ p += srvstr_push(inbuf, outbuf, p, "Unix", -1, STR_TERMINATE|STR_CONVERT);
+ p += srvstr_push(inbuf, outbuf, p, "Samba", -1, STR_TERMINATE|STR_CONVERT);
+ p += srvstr_push(inbuf, outbuf, p, global_myworkgroup, -1, STR_TERMINATE|STR_CONVERT);
+ set_message_end(outbuf,p);
/* perhaps grab OS version here?? */
}
diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c
new file mode 100644
index 0000000000..e420b8fa99
--- /dev/null
+++ b/source3/smbd/srvstr.c
@@ -0,0 +1,186 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.0
+ server specific string routines
+ Copyright (C) Andrew Tridgell 2001
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#define NO_SYSLOG
+
+#include "includes.h"
+
+#define UNICODE_FLAG() (SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
+
+/****************************************************************************
+copy a string from a char* src to a unicode or ascii
+dos code page destination choosing unicode or ascii based on the
+FLAGS2_UNICODE_STRINGS bit in inbuf
+return the number of bytes occupied by the string in the destination
+flags can have:
+ STR_TERMINATE means include the null termination
+ STR_CONVERT means convert from unix to dos codepage
+ STR_UPPER means uppercase in the destination
+ STR_ASCII use ascii even with unicode servers
+dest_len is the maximum length allowed in the destination. If dest_len
+is -1 then no maxiumum is used
+****************************************************************************/
+int srvstr_push(void *inbuf, void *outbuf, void *dest, const char *src, int dest_len, int flags)
+{
+ int len=0;
+
+ /* treat a pstring as "unlimited" length */
+ if (dest_len == -1) {
+ dest_len = sizeof(pstring);
+ }
+
+ if (!(flags & STR_ASCII) && srvstr_align(inbuf, PTR_DIFF(dest, outbuf))) {
+ *(char *)dest = 0;
+ dest++;
+ dest_len--;
+ len++;
+ }
+
+ if ((flags & STR_ASCII) || !UNICODE_FLAG()) {
+ /* the client doesn't want unicode */
+ safe_strcpy(dest, src, dest_len);
+ len = strlen(dest);
+ if (flags & STR_TERMINATE) len++;
+ if (flags & STR_CONVERT) unix_to_dos(dest,True);
+ if (flags & STR_UPPER) strupper(dest);
+ return len;
+ }
+
+ /* the server likes unicode. give it the works */
+ if (flags & STR_CONVERT) {
+ dos_PutUniCode(dest, src, dest_len, flags & STR_TERMINATE);
+ } else {
+ ascii_to_unistr(dest, src, dest_len);
+ }
+ if (flags & STR_UPPER) {
+ strupper_w(dest);
+ }
+ len += strlen(src)*2;
+ if (flags & STR_TERMINATE) len += 2;
+ return len;
+}
+
+
+/****************************************************************************
+return the length that a string would occupy when copied with srvstr_push()
+ STR_TERMINATE means include the null termination
+ STR_CONVERT means convert from unix to dos codepage
+ STR_UPPER means uppercase in the destination
+note that dest is only used for alignment purposes. No data is written.
+****************************************************************************/
+int srvstr_push_size(void *inbuf, void *outbuf,
+ const void *dest, const char *src, int dest_len, int flags)
+{
+ int len = strlen(src);
+ if (flags & STR_TERMINATE) len++;
+ if (!(flags & STR_ASCII) && UNICODE_FLAG()) len *= 2;
+
+ if (!(flags & STR_ASCII) && dest && srvstr_align(inbuf, PTR_DIFF(outbuf, dest))) {
+ len++;
+ }
+
+ return len;
+}
+
+/****************************************************************************
+copy a string from a unicode or ascii source (depending on flg2)
+to a char* destination
+flags can have:
+ STR_CONVERT means convert from dos to unix codepage
+ STR_TERMINATE means the string in src is null terminated
+ STR_UNICODE means to force as unicode
+if STR_TERMINATE is set then src_len is ignored
+src_len is the length of the source area in bytes
+return the number of bytes occupied by the string in src
+****************************************************************************/
+int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_len, int flags)
+{
+ int len;
+
+ if (dest_len == -1) {
+ dest_len = sizeof(pstring);
+ }
+
+ if (srvstr_align(inbuf, PTR_DIFF(src, inbuf))) {
+ src++;
+ if (src_len > 0) src_len--;
+ }
+
+ if (!(flags & STR_UNICODE) && !UNICODE_FLAG()) {
+ /* the server doesn't want unicode */
+ if (flags & STR_TERMINATE) {
+ safe_strcpy(dest, src, dest_len);
+ len = strlen(src)+1;
+ } else {
+ if (src_len > dest_len) src_len = dest_len;
+ len = src_len;
+ memcpy(dest, src, len);
+ dest[len] = 0;
+ }
+ if (flags & STR_CONVERT) dos_to_unix(dest,True);
+ return len;
+ }
+
+ if (flags & STR_TERMINATE) {
+ unistr_to_ascii(dest, src, dest_len);
+ len = strlen(dest)*2 + 2;
+ } else {
+ int i, c;
+ if (dest_len*2 < src_len) src_len = 2*dest_len;
+ for (i=0; i < src_len; i += 2) {
+ c = SVAL(src, i);
+ *dest++ = c;
+ }
+ *dest++ = 0;
+ len = src_len;
+ }
+ if (flags & STR_CONVERT) dos_to_unix(dest,True);
+ return len;
+}
+
+/****************************************************************************
+return the length that a string would occupy (not including the null)
+when copied with srvstr_pull()
+if src_len is -1 then assume the source is null terminated
+****************************************************************************/
+int srvstr_pull_size(void *inbuf, const void *src, int src_len)
+{
+ if (srvstr_align(inbuf, PTR_DIFF(src, inbuf))) {
+ src++;
+ if (src_len > 0) src_len--;
+ }
+
+ if (!UNICODE_FLAG()) {
+ return strlen(src);
+ }
+ return strlen_w(src);
+}
+
+/****************************************************************************
+return an alignment of either 0 or 1
+if unicode is not negotiated then return 0
+otherwise return 1 if offset is off
+****************************************************************************/
+int srvstr_align(void *inbuf, int offset)
+{
+ if (!UNICODE_FLAG()) return 0;
+ return offset & 1;
+}