1
0
mirror of https://github.com/samba-team/samba.git synced 2025-12-03 04:23:50 +03:00

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 commit is contained in:
Andrew Tridgell
-
parent 519010345f
commit e1a04e621f
7 changed files with 864 additions and 592 deletions

View File

@@ -120,7 +120,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
libsmb/clirap.o libsmb/clierror.o libsmb/climessage.o \
libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \
libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \
libsmb/namequery.o libsmb/nmblib.o \
libsmb/namequery.o libsmb/nmblib.o libsmb/clistr.o \
libsmb/nterr.o libsmb/smbdes.o libsmb/smbencrypt.o \
libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
libsmb/passchange.o libsmb/unexpected.o $(RPC_PARSE_OBJ1)

View File

@@ -29,6 +29,12 @@
will be a multiple of the page size on almost any system */
#define CLI_BUFFER_SIZE (0xFFFF)
/* clistr flags - see clistr.c */
#define CLISTR_TERMINATE 1
#define CLISTR_CONVERT 2
#define CLISTR_UPPER 4
/*
* These definitions depend on smb.h
*/

File diff suppressed because it is too large Load Diff

View File

@@ -852,7 +852,7 @@ size_t strlen_w(const smb_ucs2_t *src)
{
size_t len;
for(len = 0; *src; len++)
for(len = 0; *src++; len++)
;
return len;

View File

@@ -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);
}
@@ -191,20 +187,14 @@ BOOL cli_session_setup(struct cli_state *cli,
* 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);
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;
}

View File

@@ -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);
}
}

161
source/libsmb/clistr.c Normal file
View File

@@ -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;
}