summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/cliconnect.c75
-rw-r--r--source3/libsmb/clientgen.c18
-rw-r--r--source3/libsmb/clistr.c161
3 files changed, 213 insertions, 41 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 8a56a08b1d..74a10ddf8b 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -104,8 +104,7 @@ BOOL cli_session_setup(struct cli_state *cli,
/*
* Plaintext mode needed, assume plaintext supplied.
*/
- fstrcpy(pword, pass);
- unix_to_dos(pword,True);
+ passlen = clistr_push(cli, pword, pass, -1, CLISTR_CONVERT|CLISTR_TERMINATE);
fstrcpy(ntpword, "");
ntpasslen = 0;
}
@@ -124,7 +123,10 @@ BOOL cli_session_setup(struct cli_state *cli,
if (cli->protocol < PROTOCOL_NT1)
{
- set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
+ set_message(cli->outbuf,10,
+ clistr_align(cli, 1) +
+ clistr_push_size(cli, user, -1, CLISTR_TERMINATE|CLISTR_CONVERT) +
+ passlen,True);
CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
cli_setup_packet(cli);
@@ -135,11 +137,10 @@ BOOL cli_session_setup(struct cli_state *cli,
SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
SSVAL(cli->outbuf,smb_vwv7,passlen);
p = smb_buf(cli->outbuf);
+ p += clistr_align(cli, PTR_DIFF(p,cli->outbuf));
memcpy(p,pword,passlen);
p += passlen;
- pstrcpy(p,user);
- unix_to_dos(p,True);
- strupper(p);
+ clistr_push(cli, p, user, -1, CLISTR_CONVERT|CLISTR_UPPER|CLISTR_TERMINATE);
}
else
{
@@ -156,20 +157,15 @@ BOOL cli_session_setup(struct cli_state *cli,
SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
SSVAL(cli->outbuf,smb_vwv11,CAP_NT_SMBS|(cli->use_level_II_oplocks ? CAP_LEVEL_II_OPLOCKS : 0));
p = smb_buf(cli->outbuf);
+ p += clistr_align(cli, PTR_DIFF(p,cli->outbuf));
memcpy(p,pword,passlen);
p += SVAL(cli->outbuf,smb_vwv7);
memcpy(p,ntpword,ntpasslen);
p += SVAL(cli->outbuf,smb_vwv8);
- pstrcpy(p,user);
- unix_to_dos(p,True);
- strupper(p);
- p = skip_string(p,1);
- pstrcpy(p,workgroup);
- unix_to_dos(p,True);
- strupper(p);
- p = skip_string(p,1);
- pstrcpy(p,"Unix");p = skip_string(p,1);
- pstrcpy(p,"Samba");p = skip_string(p,1);
+ p += clistr_push(cli, p, user, -1, CLISTR_CONVERT|CLISTR_TERMINATE|CLISTR_UPPER);
+ p += clistr_push(cli, p, workgroup, -1, CLISTR_CONVERT|CLISTR_TERMINATE|CLISTR_UPPER);
+ p += clistr_push(cli, p, "Unix", -1, CLISTR_CONVERT|CLISTR_TERMINATE);
+ p += clistr_push(cli, p, "Samba", -1, CLISTR_CONVERT|CLISTR_TERMINATE);
set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
}
@@ -187,24 +183,18 @@ BOOL cli_session_setup(struct cli_state *cli,
cli->vuid = SVAL(cli->inbuf,smb_uid);
if (cli->protocol >= PROTOCOL_NT1) {
- /*
- * Save off some of the connected server
- * info.
- */
- char *server_domain,*server_os,*server_type;
- server_os = smb_buf(cli->inbuf);
- server_type = skip_string(server_os,1);
- server_domain = skip_string(server_type,1);
- fstrcpy(cli->server_os, server_os);
- dos_to_unix(cli->server_os, True);
- fstrcpy(cli->server_type, server_type);
- dos_to_unix(cli->server_type, True);
- fstrcpy(cli->server_domain, server_domain);
- dos_to_unix(cli->server_domain, True);
+ /*
+ * Save off some of the connected server
+ * info.
+ */
+ char *p = smb_buf(cli->inbuf);
+ p += clistr_align(cli, PTR_DIFF(p,cli->outbuf));
+ p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, CLISTR_TERMINATE|CLISTR_CONVERT);
+ p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, CLISTR_TERMINATE|CLISTR_CONVERT);
+ p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, CLISTR_TERMINATE|CLISTR_CONVERT);
}
fstrcpy(cli->user_name, user);
- dos_to_unix(cli->user_name, True);
return True;
}
@@ -257,12 +247,11 @@ BOOL cli_send_tconX(struct cli_state *cli,
unix_to_dos(dos_pword,True);
SMBencrypt((uchar *)dos_pword,(uchar *)cli->cryptkey,(uchar *)pword);
} else {
- if(!(cli->sec_mode & 2)) {
+ if((cli->sec_mode & 3) == 0) {
/*
* Non-encrypted passwords - convert to DOS codepage before using.
*/
- fstrcpy(pword,pass);
- unix_to_dos(pword,True);
+ passlen = clistr_push(cli, pword, pass, -1, CLISTR_CONVERT|CLISTR_TERMINATE);
} else {
memcpy(pword, pass, passlen);
}
@@ -274,7 +263,10 @@ BOOL cli_send_tconX(struct cli_state *cli,
strupper(fullshare);
set_message(cli->outbuf,4,
- 2 + strlen(fullshare) + passlen + strlen(dev),True);
+ clistr_push_size(cli, fullshare, -1, CLISTR_TERMINATE | CLISTR_CONVERT) +
+ passlen +
+ 1+strlen(dev),
+ True);
CVAL(cli->outbuf,smb_com) = SMBtconX;
cli_setup_packet(cli);
@@ -284,10 +276,10 @@ BOOL cli_send_tconX(struct cli_state *cli,
p = smb_buf(cli->outbuf);
memcpy(p,pword,passlen);
p += passlen;
- fstrcpy(p,fullshare);
- p = skip_string(p,1);
- pstrcpy(p,dev);
- unix_to_dos(p,True);
+ p += clistr_push(cli, p, fullshare, -1, CLISTR_CONVERT | CLISTR_TERMINATE);
+ fstrcpy(p, dev); p += strlen(dev)+1;
+
+ set_message(cli->outbuf,4,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
SCVAL(cli->inbuf,smb_rcls, 1);
@@ -302,7 +294,7 @@ BOOL cli_send_tconX(struct cli_state *cli,
fstrcpy(cli->dev, "A:");
if (cli->protocol >= PROTOCOL_NT1) {
- fstrcpy(cli->dev, smb_buf(cli->inbuf));
+ clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, CLISTR_TERMINATE | CLISTR_CONVERT);
}
if (strcasecmp(share,"IPC$")==0) {
@@ -461,6 +453,9 @@ BOOL cli_negprot(struct cli_state *cli)
cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
+ /* this ensures cli_use_unicode is setup - delete this call later (tridge) */
+ cli_setup_packet(cli);
+
return True;
}
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 1938049806..d7649074db 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -95,19 +95,35 @@ BOOL cli_send_smb(struct cli_state *cli)
return True;
}
+int cli_use_unicode = 0;
+
/****************************************************************************
setup basics in a outgoing packet
****************************************************************************/
void cli_setup_packet(struct cli_state *cli)
{
+ static int initialised;
+
+ /* the USE_UNICODE check will be deleted once our client side unicode
+ support is complete (tridge) */
+ if (!initialised) {
+ initialised = 1;
+ if (getenv("USE_UNICODE")) cli_use_unicode = 1;
+ }
+
cli->rap_error = 0;
cli->nt_error = 0;
SSVAL(cli->outbuf,smb_pid,cli->pid);
SSVAL(cli->outbuf,smb_uid,cli->vuid);
SSVAL(cli->outbuf,smb_mid,cli->mid);
if (cli->protocol > PROTOCOL_CORE) {
+ uint16 flags2;
SCVAL(cli->outbuf,smb_flg,0x8);
- SSVAL(cli->outbuf,smb_flg2,0x1);
+ flags2 = FLAGS2_LONG_PATH_COMPONENTS;
+ if (cli_use_unicode && cli->capabilities & CAP_UNICODE) {
+ flags2 |= FLAGS2_UNICODE_STRINGS;
+ }
+ SSVAL(cli->outbuf,smb_flg2, flags2);
}
}
diff --git a/source3/libsmb/clistr.c b/source3/libsmb/clistr.c
new file mode 100644
index 0000000000..839dec7592
--- /dev/null
+++ b/source3/libsmb/clistr.c
@@ -0,0 +1,161 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.0
+ client 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"
+
+/* we will delete this variable once our client side unicode support is complete */
+extern int cli_use_unicode;
+
+/****************************************************************************
+copy a string from a char* src to a unicode or ascii
+dos code page destination choosing unicode or ascii based on the
+cli->capabilities flag
+return the number of bytes occupied by the string in the destination
+flags can have:
+ CLISTR_TERMINATE means include the null termination
+ CLISTR_CONVERT means convert from unix to dos codepage
+ CLISTR_UPPER means uppercase in the destination
+dest_len is the maximum length allowed in the destination. If dest_len
+is -1 then no maxiumum is used
+****************************************************************************/
+int clistr_push(struct cli_state *cli, void *dest, char *src, int dest_len, int flags)
+{
+ int len;
+
+ /* treat a pstring as "unlimited" length */
+ if (dest_len == -1) {
+ dest_len = sizeof(pstring);
+ }
+
+ if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) {
+ /* the server doesn't want unicode */
+ safe_strcpy(dest, src, dest_len);
+ len = strlen(dest);
+ if (flags & CLISTR_TERMINATE) len++;
+ if (flags & CLISTR_CONVERT) unix_to_dos(dest,True);
+ if (flags & CLISTR_UPPER) strupper(dest);
+ return len;
+ }
+
+ /* the server likes unicode. give it the works */
+ if (flags & CLISTR_CONVERT) {
+ dos_PutUniCode(dest, src, dest_len, flags & CLISTR_TERMINATE);
+ } else {
+ ascii_to_unistr(dest, src, dest_len);
+ }
+ if (flags & CLISTR_UPPER) {
+ strupper_w(dest);
+ }
+ len = strlen(src)*2;
+ if (flags & CLISTR_TERMINATE) len += 2;
+ return len;
+}
+
+
+/****************************************************************************
+return the length that a string would occupy when copied with clistr_push()
+ CLISTR_TERMINATE means include the null termination
+ CLISTR_CONVERT means convert from unix to dos codepage
+ CLISTR_UPPER means uppercase in the destination
+****************************************************************************/
+int clistr_push_size(struct cli_state *cli, char *src, int dest_len, int flags)
+{
+ int len = strlen(src);
+ if (flags & CLISTR_TERMINATE) len++;
+ if (cli_use_unicode && (cli->capabilities & CAP_UNICODE)) len *= 2;
+ return len;
+}
+
+/****************************************************************************
+copy a string from a unicode or ascii source (depending on
+cli->capabilities) to a char* destination
+flags can have:
+ CLISTR_CONVERT means convert from dos to unix codepage
+ CLISTR_TERMINATE means the string in src is null terminated
+if CLISTR_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 clistr_pull(struct cli_state *cli, char *dest, void *src, int dest_len, int src_len, int flags)
+{
+ int len;
+
+ if (dest_len == -1) {
+ dest_len = sizeof(pstring);
+ }
+
+ if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) {
+ /* the server doesn't want unicode */
+ if (flags & CLISTR_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 & CLISTR_CONVERT) dos_to_unix(dest,True);
+ return len;
+ }
+
+ if (flags & CLISTR_TERMINATE) {
+ unistr_to_ascii(dest, src, dest_len);
+ len = strlen(dest)*2 + 2;
+ } else {
+ int i, c;
+ if (dest_len < src_len) src_len = dest_len;
+ for (i=0; i < src_len; i += 2) {
+ c = SVAL(src, i);
+ *dest++ = c;
+ }
+ *dest++ = 0;
+ len = src_len;
+ }
+ if (flags & CLISTR_CONVERT) dos_to_unix(dest,True);
+ return len;
+}
+
+/****************************************************************************
+return the length that a string would occupy (not including the null)
+when copied with clistr_pull()
+if src_len is -1 then assume the source is null terminated
+****************************************************************************/
+int clistr_pull_size(struct cli_state *cli, void *src, int src_len)
+{
+ if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) {
+ 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 clistr_align(struct cli_state *cli, int offset)
+{
+ if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) return 0;
+ return offset & 1;
+}