summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2001-02-20 08:09:06 +0000
committerAndrew Tridgell <tridge@samba.org>2001-02-20 08:09:06 +0000
commit6492d6b2f6a2743f5e794447911cbbba7e031d5d (patch)
treea9a9f4b60af0cf57bc947b3967265248a80e2490 /source3/libsmb
parentd62754e9487d62bf11bc0a4970a1bca2dd5d6727 (diff)
downloadsamba-6492d6b2f6a2743f5e794447911cbbba7e031d5d.tar.gz
samba-6492d6b2f6a2743f5e794447911cbbba7e031d5d.tar.bz2
samba-6492d6b2f6a2743f5e794447911cbbba7e031d5d.zip
initial client side unicode support (needed for netapp filer)
I've currently got this code disabled by default as it is incomplete. You enable it by setting a USE_UNICODE environment variable. Once the support is complete this check will be removed and the CAP_UNICODE capability bit will be the sole determination of whether the client library code uses unicode right now I have converted session_setup and tconx. I will do more fns over the next few days. see clistr.c for the new client side string interface. Luckily it tends to make the code smaller and neater while adding unicode support. (This used to be commit e1a04e621f1c28d8e6e543d43741ca0272e2237f)
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;
+}