1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-28 07:21:54 +03:00
samba-mirror/source3/libsmb/clirap.c

1009 lines
27 KiB
C
Raw Normal View History

/*
Unix SMB/CIFS implementation.
client RAP calls
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Gerald (Jerry) Carter 2004
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
/****************************************************************************
Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
****************************************************************************/
bool cli_api_pipe(struct cli_state *cli, const char *pipe_name,
uint16 *setup, uint32 setup_count, uint32 max_setup_count,
char *params, uint32 param_count, uint32 max_param_count,
char *data, uint32 data_count, uint32 max_data_count,
char **rparam, uint32 *rparam_count,
char **rdata, uint32 *rdata_count)
{
cli_send_trans(cli, SMBtrans,
pipe_name,
0,0, /* fid, flags */
setup, setup_count, max_setup_count,
params, param_count, max_param_count,
data, data_count, max_data_count);
return (cli_receive_trans(cli, SMBtrans,
rparam, (unsigned int *)rparam_count,
rdata, (unsigned int *)rdata_count));
}
/****************************************************************************
Call a remote api
****************************************************************************/
bool cli_api(struct cli_state *cli,
char *param, int prcnt, int mprcnt,
char *data, int drcnt, int mdrcnt,
char **rparam, unsigned int *rprcnt,
char **rdata, unsigned int *rdrcnt)
{
cli_send_trans(cli,SMBtrans,
PIPE_LANMAN, /* Name */
0,0, /* fid, flags */
NULL,0,0, /* Setup, length, max */
param, prcnt, mprcnt, /* Params, length, max */
data, drcnt, mdrcnt /* Data, length, max */
);
return (cli_receive_trans(cli,SMBtrans,
rparam, rprcnt,
rdata, rdrcnt));
}
/****************************************************************************
Perform a NetWkstaUserLogon.
****************************************************************************/
bool cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
{
char *rparam = NULL;
char *rdata = NULL;
char *p;
unsigned int rdrcnt,rprcnt;
char param[1024];
memset(param, 0, sizeof(param));
/* send a SMBtrans command with api NetWkstaUserLogon */
p = param;
SSVAL(p,0,132); /* api number */
p += 2;
strlcpy(p,"OOWb54WrLh",sizeof(param)-PTR_DIFF(p,param));
p = skip_string(param,sizeof(param),p);
strlcpy(p,"WB21BWDWWDDDDDDDzzzD",sizeof(param)-PTR_DIFF(p,param));
p = skip_string(param,sizeof(param),p);
SSVAL(p,0,1);
p += 2;
strlcpy(p,user,sizeof(param)-PTR_DIFF(p,param));
strupper_m(p);
p += 21;
p++;
p += 15;
p++;
strlcpy(p, workstation,sizeof(param)-PTR_DIFF(p,param));
strupper_m(p);
p += 16;
SSVAL(p, 0, CLI_BUFFER_SIZE);
p += 2;
SSVAL(p, 0, CLI_BUFFER_SIZE);
p += 2;
if (cli_api(cli,
param, PTR_DIFF(p,param),1024, /* param, length, max */
NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
&rparam, &rprcnt, /* return params, return size */
&rdata, &rdrcnt /* return data, return size */
)) {
cli->rap_error = rparam? SVAL(rparam,0) : -1;
p = rdata;
if (cli->rap_error == 0) {
DEBUG(4,("NetWkstaUserLogon success\n"));
cli->privileges = SVAL(p, 24);
/* The cli->eff_name field used to be set here
but it wasn't used anywhere else. */
} else {
DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
}
}
SAFE_FREE(rparam);
SAFE_FREE(rdata);
return (cli->rap_error == 0);
}
/****************************************************************************
Call a NetShareEnum - try and browse available connections on a host.
****************************************************************************/
int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
{
char *rparam = NULL;
char *rdata = NULL;
char *p;
unsigned int rdrcnt,rprcnt;
char param[1024];
int count = -1;
/* now send a SMBtrans command with api RNetShareEnum */
p = param;
SSVAL(p,0,0); /* api number */
p += 2;
strlcpy(p,"WrLeh",sizeof(param)-PTR_DIFF(p,param));
p = skip_string(param,sizeof(param),p);
strlcpy(p,"B13BWz",sizeof(param)-PTR_DIFF(p,param));
p = skip_string(param,sizeof(param),p);
SSVAL(p,0,1);
/*
* Win2k needs a *smaller* buffer than 0xFFFF here -
* it returns "out of server memory" with 0xFFFF !!! JRA.
*/
SSVAL(p,2,0xFFE0);
p += 4;
if (cli_api(cli,
param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
NULL, 0, 0xFFE0, /* data, length, maxlen - Win2k needs a small buffer here too ! */
&rparam, &rprcnt, /* return params, length */
&rdata, &rdrcnt)) /* return data, length */
{
int res = rparam? SVAL(rparam,0) : -1;
if (res == 0 || res == ERRmoredata) {
int converter=SVAL(rparam,2);
int i;
char *rdata_end = rdata + rdrcnt;
count=SVAL(rparam,4);
p = rdata;
for (i=0;i<count;i++,p+=20) {
char *sname;
int type;
int comment_offset;
const char *cmnt;
const char *p1;
char *s1, *s2;
size_t len;
TALLOC_CTX *frame = talloc_stackframe();
if (p + 20 > rdata_end) {
TALLOC_FREE(frame);
break;
}
sname = p;
type = SVAL(p,14);
comment_offset = IVAL(p,16) & 0xFFFF;
if (comment_offset < 0 || comment_offset > (int)rdrcnt) {
TALLOC_FREE(frame);
break;
}
cmnt = comment_offset?(rdata+comment_offset-converter):"";
/* Work out the comment length. */
for (p1 = cmnt, len = 0; *p1 &&
p1 < rdata_end; len++)
p1++;
if (!*p1) {
len++;
}
pull_string_talloc(frame,rdata,0,
&s1,sname,14,STR_ASCII);
pull_string_talloc(frame,rdata,0,
&s2,cmnt,len,STR_ASCII);
if (!s1 || !s2) {
TALLOC_FREE(frame);
continue;
}
fn(s1, type, s2, state);
TALLOC_FREE(frame);
}
} else {
DEBUG(4,("NetShareEnum res=%d\n", res));
}
} else {
DEBUG(4,("NetShareEnum failed\n"));
}
SAFE_FREE(rparam);
SAFE_FREE(rdata);
return count;
}
/****************************************************************************
Call a NetServerEnum for the specified workgroup and servertype mask. This
function then calls the specified callback function for each name returned.
The callback function takes 4 arguments: the machine name, the server type,
the comment and a state pointer.
****************************************************************************/
bool cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
void (*fn)(const char *, uint32, const char *, void *),
void *state)
{
char *rparam = NULL;
char *rdata = NULL;
unsigned int rdrcnt,rprcnt;
char *p;
char param[1024];
int uLevel = 1;
int count = -1;
size_t len;
errno = 0; /* reset */
/* send a SMBtrans command with api NetServerEnum */
p = param;
SSVAL(p,0,0x68); /* api number */
p += 2;
strlcpy(p,"WrLehDz", sizeof(param)-PTR_DIFF(p,param));
p = skip_string(param,sizeof(param),p);
strlcpy(p,"B16BBDz", sizeof(param)-PTR_DIFF(p,param));
p = skip_string(param,sizeof(param),p);
SSVAL(p,0,uLevel);
SSVAL(p,2,CLI_BUFFER_SIZE);
p += 4;
SIVAL(p,0,stype);
p += 4;
len = push_ascii(p, workgroup, sizeof(param)-PTR_DIFF(p,param)-1,
STR_TERMINATE|STR_UPPER);
if (len == (size_t)-1) {
return false;
}
p += len;
if (cli_api(cli,
param, PTR_DIFF(p,param), 8, /* params, length, max */
NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
&rparam, &rprcnt, /* return params, return size */
&rdata, &rdrcnt /* return data, return size */
)) {
int res = rparam? SVAL(rparam,0) : -1;
char *rdata_end = rdata + rdrcnt;
r19231: I encountered a WinXP/Home system which, acting as the master browser for its workgroup, decided periodically to stop sending recognized responses to a NetServerEnum2 request for the workgroup. Instead of returning the list of servers (only itself; nothing else in the workgroup), it returns a status code of 8 which is unsupported by samba3, samba4, and ethereal. The code for this request assumed that if an unexpected status code was received, the connection had a problem, i.e. that cli_errno() would show a problem. That turns out not to be the case. This patch changes the behavior so tha any time a response is received and cli_errno() == 0, we continue processing the reply and base our response on the returned count (zero). The pre-existing code then converts this count=0 into an ENOENT errno which can be properly handled by the application (whereas an error return with errno=0 can't be). This packet dump has only 2 frames. Sorry about the text version but it's most easily attached to this log message. I also have it saved as .pcap if anyone wants it. Derrell No. Time Source Destination Protocol Info 1 14:31:59.802668 192.168.1.106 192.168.1.100 LANMAN NetServerEnum2 Request, Server, SQL Server, Domain Controller, Backup Controller, Time Source, Apple Server, Novell Server, Domain Member Server, Print Queue Server, Dialin Server, Xenix Server, NT Workstation, Windows for Workgroups, Unknown server type:14, NT Server Frame 1 (196 bytes on wire, 196 bytes captured) Arrival Time: Oct 10, 2006 14:31:59.802668000 Time delta from previous packet: 0.000000000 seconds Time since reference or first frame: 0.000000000 seconds Frame Number: 1 Packet Length: 196 bytes Capture Length: 196 bytes Protocols in frame: eth:ip:tcp:nbss:smb Ethernet II, Src: IntelCor_4a:47:bb (00:13:20:4a:47:bb), Dst: Micro-St_74:16:e7 (00:0c:76:74:16:e7) Destination: Micro-St_74:16:e7 (00:0c:76:74:16:e7) Source: IntelCor_4a:47:bb (00:13:20:4a:47:bb) Type: IP (0x0800) Internet Protocol, Src: 192.168.1.106 (192.168.1.106), Dst: 192.168.1.100 (192.168.1.100) Version: 4 Header length: 20 bytes Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00) 0000 00.. = Differentiated Services Codepoint: Default (0x00) .... ..0. = ECN-Capable Transport (ECT): 0 .... ...0 = ECN-CE: 0 Total Length: 182 Identification: 0xb838 (47160) Flags: 0x04 (Don't Fragment) 0... = Reserved bit: Not set .1.. = Don't fragment: Set ..0. = More fragments: Not set Fragment offset: 0 Time to live: 64 Protocol: TCP (0x06) Header checksum: 0xfdea [correct] Good: True Bad : False Source: 192.168.1.106 (192.168.1.106) Destination: 192.168.1.100 (192.168.1.100) Transmission Control Protocol, Src Port: 44932 (44932), Dst Port: netbios-ssn (139), Seq: 851982066, Ack: 1274726157, Len: 130 Source port: 44932 (44932) Destination port: netbios-ssn (139) Sequence number: 851982066 Next sequence number: 851982196 Acknowledgement number: 1274726157 Header length: 32 bytes Flags: 0x0018 (PSH, ACK) 0... .... = Congestion Window Reduced (CWR): Not set .0.. .... = ECN-Echo: Not set ..0. .... = Urgent: Not set ...1 .... = Acknowledgment: Set .... 1... = Push: Set .... .0.. = Reset: Not set .... ..0. = Syn: Not set .... ...0 = Fin: Not set Window size: 6432 Checksum: 0xb4e0 [correct] Options: (12 bytes) NOP NOP Time stamp: tsval 1184074739, tsecr 11576161 NetBIOS Session Service Message Type: Session message Flags: 0x00 .... ...0 = Add 0 to length Length: 126 SMB (Server Message Block Protocol) SMB Header Server Component: SMB Response in: 2 SMB Command: Trans (0x25) NT Status: STATUS_SUCCESS (0x00000000) Flags: 0x08 0... .... = Request/Response: Message is a request to the server .0.. .... = Notify: Notify client only on open ..0. .... = Oplocks: OpLock not requested/granted ...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized .... 1... = Case Sensitivity: Path names are caseless .... ..0. = Receive Buffer Posted: Receive buffer has not been posted .... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported Flags2: 0xc801 1... .... .... .... = Unicode Strings: Strings are Unicode .1.. .... .... .... = Error Code Type: Error codes are NT error codes ..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only ...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs .... 1... .... .... = Extended Security Negotiation: Extended security negotiation is supported .... .... .0.. .... = Long Names Used: Path names in request are not long file names .... .... .... .0.. = Security Signatures: Security signatures are not supported .... .... .... ..0. = Extended Attributes: Extended attributes are not supported .... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response Process ID High: 0 Signature: 0000000000000000 Reserved: 0000 Tree ID: 2048 Process ID: 12967 User ID: 2048 Multiplex ID: 6 Trans Request (0x25) Word Count (WCT): 14 Total Parameter Count: 36 Total Data Count: 0 Max Parameter Count: 8 Max Data Count: 65535 Max Setup Count: 0 Reserved: 00 Flags: 0x0000 .... .... .... ..0. = One Way Transaction: Two way transaction .... .... .... ...0 = Disconnect TID: Do NOT disconnect TID Timeout: Return immediately (0) Reserved: 0000 Parameter Count: 36 Parameter Offset: 90 Data Count: 0 Data Offset: 126 Setup Count: 0 Reserved: 00 Byte Count (BCC): 63 Transaction Name: \PIPE\LANMAN SMB Pipe Protocol Microsoft Windows Lanman Remote API Protocol Function Code: NetServerEnum2 (104) Parameter Descriptor: WrLehDz Return Descriptor: B16BBDz Detail Level: 1 Receive Buffer Length: 65535 Server Type: 0x0000fffe .... .... .... .... .... .... .... ...0 = Workstation: This is NOT a Workstation .... .... .... .... .... .... .... ..1. = Server: This is a Server .... .... .... .... .... .... .... .1.. = SQL: This is an SQL server .... .... .... .... .... .... .... 1... = Domain Controller: This is a Domain Controller .... .... .... .... .... .... ...1 .... = Backup Controller: This is a Backup Controller .... .... .... .... .... .... ..1. .... = Time Source: This is a Time Source .... .... .... .... .... .... .1.. .... = Apple: This is an Apple host .... .... .... .... .... .... 1... .... = Novell: This is a Novell server .... .... .... .... .... ...1 .... .... = Member: This is a Domain Member server .... .... .... .... .... ..1. .... .... = Print: This is a Print Queue server .... .... .... .... .... .1.. .... .... = Dialin: This is a Dialin server .... .... .... .... .... 1... .... .... = Xenix: This is a Xenix server .... .... .... .... ...1 .... .... .... = NT Workstation: This is an NT Workstation .... .... .... .... ..1. .... .... .... = WfW: This is a WfW host .... .... .... .... 1... .... .... .... = NT Server: This is an NT Server .... .... .... ...0 .... .... .... .... = Potential Browser: This is NOT a Potential Browser .... .... .... ..0. .... .... .... .... = Backup Browser: This is NOT a Backup Browser .... .... .... .0.. .... .... .... .... = Master Browser: This is NOT a Master Browser .... .... .... 0... .... .... .... .... = Domain Master Browser: This is NOT a Domain Master Browser .... .... ...0 .... .... .... .... .... = OSF: This is NOT an OSF host .... .... ..0. .... .... .... .... .... = VMS: This is NOT a VMS host .... .... .0.. .... .... .... .... .... = Windows 95+: This is NOT a Windows 95 or above host .0.. .... .... .... .... .... .... .... = Local: This is NOT a local list only request 0... .... .... .... .... .... .... .... = Domain Enum: This is NOT a Domain Enum request Enumeration Domain: WORKGROUP No. Time Source Destination Protocol Info 2 14:31:59.803918 192.168.1.100 192.168.1.106 LANMAN NetServerEnum2 Response Frame 2 (134 bytes on wire, 134 bytes captured) Arrival Time: Oct 10, 2006 14:31:59.803918000 Time delta from previous packet: 0.001250000 seconds Time since reference or first frame: 0.001250000 seconds Frame Number: 2 Packet Length: 134 bytes Capture Length: 134 bytes Protocols in frame: eth:ip:tcp:nbss:smb Ethernet II, Src: Micro-St_74:16:e7 (00:0c:76:74:16:e7), Dst: IntelCor_4a:47:bb (00:13:20:4a:47:bb) Destination: IntelCor_4a:47:bb (00:13:20:4a:47:bb) Source: Micro-St_74:16:e7 (00:0c:76:74:16:e7) Type: IP (0x0800) Internet Protocol, Src: 192.168.1.100 (192.168.1.100), Dst: 192.168.1.106 (192.168.1.106) Version: 4 Header length: 20 bytes Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00) 0000 00.. = Differentiated Services Codepoint: Default (0x00) .... ..0. = ECN-Capable Transport (ECT): 0 .... ...0 = ECN-CE: 0 Total Length: 120 Identification: 0xea10 (59920) Flags: 0x04 (Don't Fragment) 0... = Reserved bit: Not set .1.. = Don't fragment: Set ..0. = More fragments: Not set Fragment offset: 0 Time to live: 128 Protocol: TCP (0x06) Header checksum: 0x8c50 [correct] Good: True Bad : False Source: 192.168.1.100 (192.168.1.100) Destination: 192.168.1.106 (192.168.1.106) Transmission Control Protocol, Src Port: netbios-ssn (139), Dst Port: 44932 (44932), Seq: 1274726157, Ack: 851982196, Len: 68 Source port: netbios-ssn (139) Destination port: 44932 (44932) Sequence number: 1274726157 Next sequence number: 1274726225 Acknowledgement number: 851982196 Header length: 32 bytes Flags: 0x0018 (PSH, ACK) 0... .... = Congestion Window Reduced (CWR): Not set .0.. .... = ECN-Echo: Not set ..0. .... = Urgent: Not set ...1 .... = Acknowledgment: Set .... 1... = Push: Set .... .0.. = Reset: Not set .... ..0. = Syn: Not set .... ...0 = Fin: Not set Window size: 64606 Checksum: 0x1e0d [correct] Options: (12 bytes) NOP NOP Time stamp: tsval 11576161, tsecr 1184074739 NetBIOS Session Service Message Type: Session message Flags: 0x00 .... ...0 = Add 0 to length Length: 64 SMB (Server Message Block Protocol) SMB Header Server Component: SMB Response to: 1 Time from request: 0.001250000 seconds SMB Command: Trans (0x25) NT Status: STATUS_SUCCESS (0x00000000) Flags: 0x88 1... .... = Request/Response: Message is a response to the client/redirector .0.. .... = Notify: Notify client only on open ..0. .... = Oplocks: OpLock not requested/granted ...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized .... 1... = Case Sensitivity: Path names are caseless .... ..0. = Receive Buffer Posted: Receive buffer has not been posted .... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported Flags2: 0xc801 1... .... .... .... = Unicode Strings: Strings are Unicode .1.. .... .... .... = Error Code Type: Error codes are NT error codes ..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only ...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs .... 1... .... .... = Extended Security Negotiation: Extended security negotiation is supported .... .... .0.. .... = Long Names Used: Path names in request are not long file names .... .... .... .0.. = Security Signatures: Security signatures are not supported .... .... .... ..0. = Extended Attributes: Extended attributes are not supported .... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response Process ID High: 0 Signature: 0000000000000000 Reserved: 0000 Tree ID: 2048 Process ID: 12967 User ID: 2048 Multiplex ID: 6 Trans Response (0x25) Word Count (WCT): 10 Total Parameter Count: 8 Total Data Count: 0 Reserved: 0000 Parameter Count: 8 Parameter Offset: 56 Parameter Displacement: 0 Data Count: 0 Data Offset: 64 Data Displacement: 0 Setup Count: 0 Reserved: 00 Byte Count (BCC): 9 Padding: 00 SMB Pipe Protocol Microsoft Windows Lanman Remote API Protocol Function Code: NetServerEnum2 (104) Status: Unknown (8) Convert: 0 Entry Count: 0 Available Entries: 0 (This used to be commit 88fa5ac7347cbae92abe17da8d3af00e85110c43)
2006-10-11 04:33:48 +04:00
if (res == 0 || res == ERRmoredata ||
(res != -1 && cli_errno(cli) == 0)) {
int i;
int converter=SVAL(rparam,2);
count=SVAL(rparam,4);
p = rdata;
for (i = 0;i < count;i++, p += 26) {
char *sname;
int comment_offset;
const char *cmnt;
const char *p1;
char *s1, *s2;
TALLOC_CTX *frame = talloc_stackframe();
if (p + 26 > rdata_end) {
TALLOC_FREE(frame);
break;
}
sname = p;
comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
cmnt = comment_offset?(rdata+comment_offset):"";
if (comment_offset < 0 || comment_offset > (int)rdrcnt) {
TALLOC_FREE(frame);
continue;
}
/* Work out the comment length. */
for (p1 = cmnt, len = 0; *p1 &&
p1 < rdata_end; len++)
p1++;
if (!*p1) {
len++;
}
stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
pull_string_talloc(frame,rdata,0,
&s1,sname,16,STR_ASCII);
pull_string_talloc(frame,rdata,0,
&s2,cmnt,len,STR_ASCII);
if (!s1 || !s2) {
TALLOC_FREE(frame);
continue;
}
fn(s1, stype, s2, state);
TALLOC_FREE(frame);
}
}
}
SAFE_FREE(rparam);
SAFE_FREE(rdata);
if (count < 0) {
errno = cli_errno(cli);
} else {
if (!count) {
/* this is a very special case, when the domain master for the
work group isn't part of the work group itself, there is something
wild going on */
errno = ENOENT;
}
}
return(count > 0);
}
/****************************************************************************
Send a SamOEMChangePassword command.
****************************************************************************/
bool cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
const char *old_password)
{
char param[1024];
unsigned char data[532];
char *p = param;
unsigned char old_pw_hash[16];
unsigned char new_pw_hash[16];
unsigned int data_len;
unsigned int param_len = 0;
char *rparam = NULL;
char *rdata = NULL;
unsigned int rprcnt, rdrcnt;
if (strlen(user) >= sizeof(fstring)-1) {
DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
return False;
}
SSVAL(p,0,214); /* SamOEMChangePassword command. */
p += 2;
strlcpy(p, "zsT", sizeof(param)-PTR_DIFF(p,param));
p = skip_string(param,sizeof(param),p);
strlcpy(p, "B516B16", sizeof(param)-PTR_DIFF(p,param));
p = skip_string(param,sizeof(param),p);
strlcpy(p,user, sizeof(param)-PTR_DIFF(p,param));
p = skip_string(param,sizeof(param),p);
SSVAL(p,0,532);
p += 2;
param_len = PTR_DIFF(p,param);
/*
* Get the Lanman hash of the old password, we
* use this as the key to make_oem_passwd_hash().
*/
E_deshash(old_password, old_pw_hash);
encode_pw_buffer(data, new_password, STR_ASCII);
#ifdef DEBUG_PASSWORD
DEBUG(100,("make_oem_passwd_hash\n"));
dump_data(100, data, 516);
#endif
SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
/*
* Now place the old password hash in the data.
*/
E_deshash(new_password, new_pw_hash);
E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
data_len = 532;
if (cli_send_trans(cli,SMBtrans,
PIPE_LANMAN, /* name */
0,0, /* fid, flags */
NULL,0,0, /* setup, length, max */
param,param_len,2, /* param, length, max */
(char *)data,data_len,0 /* data, length, max */
) == False) {
DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
user ));
return False;
}
if (!cli_receive_trans(cli,SMBtrans,
&rparam, &rprcnt,
&rdata, &rdrcnt)) {
DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
user ));
return False;
}
if (rparam) {
cli->rap_error = SVAL(rparam,0);
}
SAFE_FREE(rparam);
SAFE_FREE(rdata);
return (cli->rap_error == 0);
}
/****************************************************************************
Send a qpathinfo call.
****************************************************************************/
bool cli_qpathinfo(struct cli_state *cli, const char *fname,
time_t *change_time,
time_t *access_time,
time_t *write_time,
SMB_OFF_T *size, uint16 *mode)
{
unsigned int data_len = 0;
unsigned int param_len = 0;
unsigned int rparam_len, rdata_len;
uint16 setup = TRANSACT2_QPATHINFO;
char param[1024];
char *rparam=NULL, *rdata=NULL;
int count=8;
bool ret;
time_t (*date_fn)(struct cli_state *, const void *);
char *p;
p = param;
memset(p, 0, 6);
SSVAL(p, 0, SMB_INFO_STANDARD);
p += 6;
p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
param_len = PTR_DIFF(p, param);
do {
ret = (cli_send_trans(cli, SMBtrans2,
NULL, /* Name */
-1, 0, /* fid, flags */
&setup, 1, 0, /* setup, length, max */
param, param_len, 10, /* param, length, max */
NULL, data_len, cli->max_xmit /* data, length, max */
) &&
cli_receive_trans(cli, SMBtrans2,
&rparam, &rparam_len,
&rdata, &rdata_len));
if (!cli_is_dos_error(cli)) break;
if (!ret) {
/* we need to work around a Win95 bug - sometimes
it gives ERRSRV/ERRerror temprarily */
uint8 eclass;
uint32 ecode;
cli_dos_error(cli, &eclass, &ecode);
if (eclass != ERRSRV || ecode != ERRerror) break;
smb_msleep(100);
}
} while (count-- && ret==False);
if (!ret || !rdata || rdata_len < 22) {
return False;
}
if (cli->win95) {
date_fn = cli_make_unix_date;
} else {
date_fn = cli_make_unix_date2;
}
if (change_time) {
*change_time = date_fn(cli, rdata+0);
}
if (access_time) {
*access_time = date_fn(cli, rdata+4);
}
if (write_time) {
*write_time = date_fn(cli, rdata+8);
}
if (size) {
*size = IVAL(rdata, 12);
}
if (mode) {
*mode = SVAL(rdata,l1_attrFile);
}
SAFE_FREE(rdata);
SAFE_FREE(rparam);
return True;
}
/****************************************************************************
Send a setpathinfo call.
****************************************************************************/
bool cli_setpathinfo(struct cli_state *cli, const char *fname,
time_t create_time,
time_t access_time,
time_t write_time,
time_t change_time,
uint16 mode)
{
unsigned int data_len = 0;
unsigned int param_len = 0;
unsigned int rparam_len, rdata_len;
uint16 setup = TRANSACT2_SETPATHINFO;
char param[1024];
char data[1024];
char *rparam=NULL, *rdata=NULL;
int count=8;
bool ret;
char *p;
memset(param, 0, sizeof(param));
memset(data, 0, sizeof(data));
p = param;
/* Add the information level */
SSVAL(p, 0, SMB_FILE_BASIC_INFORMATION);
/* Skip reserved */
p += 6;
/* Add the file name */
p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
param_len = PTR_DIFF(p, param);
p = data;
/*
* Add the create, last access, modification, and status change times
*/
put_long_date(p, create_time);
p += 8;
put_long_date(p, access_time);
p += 8;
put_long_date(p, write_time);
p += 8;
put_long_date(p, change_time);
p += 8;
/* Add attributes */
SIVAL(p, 0, mode);
p += 4;
/* Add padding */
SIVAL(p, 0, 0);
p += 4;
data_len = PTR_DIFF(p, data);
do {
ret = (cli_send_trans(cli, SMBtrans2,
NULL, /* Name */
-1, 0, /* fid, flags */
&setup, 1, 0, /* setup, length, max */
param, param_len, 10, /* param, length, max */
data, data_len, cli->max_xmit /* data, length, max */
) &&
cli_receive_trans(cli, SMBtrans2,
&rparam, &rparam_len,
&rdata, &rdata_len));
if (!cli_is_dos_error(cli)) break;
if (!ret) {
/* we need to work around a Win95 bug - sometimes
it gives ERRSRV/ERRerror temprarily */
uint8 eclass;
uint32 ecode;
cli_dos_error(cli, &eclass, &ecode);
if (eclass != ERRSRV || ecode != ERRerror) break;
smb_msleep(100);
}
} while (count-- && ret==False);
if (!ret) {
return False;
}
SAFE_FREE(rdata);
SAFE_FREE(rparam);
return True;
}
/****************************************************************************
Send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level.
****************************************************************************/
bool cli_qpathinfo2(struct cli_state *cli, const char *fname,
struct timespec *create_time,
struct timespec *access_time,
struct timespec *write_time,
struct timespec *change_time,
SMB_OFF_T *size, uint16 *mode,
SMB_INO_T *ino)
{
unsigned int data_len = 0;
unsigned int param_len = 0;
uint16 setup = TRANSACT2_QPATHINFO;
char param[1024];
char *rparam=NULL, *rdata=NULL;
char *p;
p = param;
memset(p, 0, 6);
SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
p += 6;
p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
param_len = PTR_DIFF(p, param);
if (!cli_send_trans(cli, SMBtrans2,
NULL, /* name */
-1, 0, /* fid, flags */
&setup, 1, 0, /* setup, length, max */
param, param_len, 10, /* param, length, max */
NULL, data_len, cli->max_xmit /* data, length, max */
)) {
return False;
}
if (!cli_receive_trans(cli, SMBtrans2,
&rparam, &param_len,
&rdata, &data_len)) {
return False;
}
if (!rdata || data_len < 22) {
return False;
}
if (create_time) {
*create_time = interpret_long_date(rdata+0);
}
if (access_time) {
*access_time = interpret_long_date(rdata+8);
}
if (write_time) {
*write_time = interpret_long_date(rdata+16);
}
if (change_time) {
*change_time = interpret_long_date(rdata+24);
}
if (mode) {
*mode = SVAL(rdata, 32);
}
if (size) {
*size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
}
if (ino) {
*ino = IVAL(rdata, 64);
}
SAFE_FREE(rdata);
SAFE_FREE(rparam);
return True;
}
/****************************************************************************
Send a qfileinfo QUERY_FILE_NAME_INFO call.
****************************************************************************/
bool cli_qfilename(struct cli_state *cli, int fnum, char *name, size_t namelen)
{
unsigned int data_len = 0;
unsigned int param_len = 0;
uint16 setup = TRANSACT2_QFILEINFO;
char param[4];
char *rparam=NULL, *rdata=NULL;
param_len = 4;
SSVAL(param, 0, fnum);
SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
if (!cli_send_trans(cli, SMBtrans2,
NULL, /* name */
-1, 0, /* fid, flags */
&setup, 1, 0, /* setup, length, max */
param, param_len, 2, /* param, length, max */
NULL, data_len, cli->max_xmit /* data, length, max */
)) {
return False;
}
if (!cli_receive_trans(cli, SMBtrans2,
&rparam, &param_len,
&rdata, &data_len)) {
return False;
}
if (!rdata || data_len < 4) {
return False;
}
clistr_pull(cli, name, rdata+4, namelen, IVAL(rdata, 0), STR_UNICODE);
return True;
}
/****************************************************************************
Send a qfileinfo call.
****************************************************************************/
bool cli_qfileinfo(struct cli_state *cli, int fnum,
uint16 *mode, SMB_OFF_T *size,
struct timespec *create_time,
struct timespec *access_time,
struct timespec *write_time,
struct timespec *change_time,
SMB_INO_T *ino)
{
unsigned int data_len = 0;
unsigned int param_len = 0;
uint16 setup = TRANSACT2_QFILEINFO;
char param[4];
char *rparam=NULL, *rdata=NULL;
/* if its a win95 server then fail this - win95 totally screws it
up */
if (cli->win95) return False;
param_len = 4;
SSVAL(param, 0, fnum);
SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
if (!cli_send_trans(cli, SMBtrans2,
NULL, /* name */
-1, 0, /* fid, flags */
&setup, 1, 0, /* setup, length, max */
param, param_len, 2, /* param, length, max */
NULL, data_len, cli->max_xmit /* data, length, max */
)) {
return False;
}
if (!cli_receive_trans(cli, SMBtrans2,
&rparam, &param_len,
&rdata, &data_len)) {
return False;
}
if (!rdata || data_len < 68) {
return False;
}
if (create_time) {
*create_time = interpret_long_date(rdata+0);
}
if (access_time) {
*access_time = interpret_long_date(rdata+8);
}
if (write_time) {
*write_time = interpret_long_date(rdata+16);
}
if (change_time) {
*change_time = interpret_long_date(rdata+24);
}
if (mode) {
*mode = SVAL(rdata, 32);
}
if (size) {
*size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
}
if (ino) {
*ino = IVAL(rdata, 64);
}
SAFE_FREE(rdata);
SAFE_FREE(rparam);
return True;
}
/****************************************************************************
Send a qpathinfo BASIC_INFO call.
****************************************************************************/
bool cli_qpathinfo_basic( struct cli_state *cli, const char *name,
SMB_STRUCT_STAT *sbuf, uint32 *attributes )
{
unsigned int param_len = 0;
unsigned int data_len = 0;
uint16 setup = TRANSACT2_QPATHINFO;
char param[1024+6];
char *rparam=NULL, *rdata=NULL;
char *p;
char *path;
int len;
TALLOC_CTX *frame = talloc_stackframe();
path = talloc_strdup(frame, name);
if (!path) {
TALLOC_FREE(frame);
return false;
}
/* cleanup */
len = strlen(path);
if ( path[len-1] == '\\' || path[len-1] == '/') {
path[len-1] = '\0';
}
p = param;
memset(p, 0, 6);
SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO);
p += 6;
p += clistr_push(cli, p, path, sizeof(param)-6, STR_TERMINATE);
param_len = PTR_DIFF(p, param);
TALLOC_FREE(frame);
if (!cli_send_trans(cli, SMBtrans2,
NULL, /* name */
-1, 0, /* fid, flags */
&setup, 1, 0, /* setup, length, max */
param, param_len, 2, /* param, length, max */
NULL, 0, cli->max_xmit /* data, length, max */
)) {
return False;
}
if (!cli_receive_trans(cli, SMBtrans2,
&rparam, &param_len,
&rdata, &data_len)) {
return False;
}
if (data_len < 36) {
SAFE_FREE(rdata);
SAFE_FREE(rparam);
return False;
}
set_atimespec(sbuf, interpret_long_date( rdata+8 )); /* Access time. */
set_mtimespec(sbuf, interpret_long_date( rdata+16 )); /* Write time. */
set_ctimespec(sbuf, interpret_long_date( rdata+24 )); /* Change time. */
*attributes = IVAL( rdata, 32 );
SAFE_FREE(rparam);
SAFE_FREE(rdata);
return True;
}
/****************************************************************************
Send a qfileinfo call.
****************************************************************************/
bool cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
{
unsigned int data_len = 0;
unsigned int param_len = 0;
uint16 setup = TRANSACT2_QFILEINFO;
char param[4];
char *rparam=NULL, *rdata=NULL;
*poutdata = NULL;
*poutlen = 0;
/* if its a win95 server then fail this - win95 totally screws it
up */
if (cli->win95)
return False;
param_len = 4;
SSVAL(param, 0, fnum);
SSVAL(param, 2, level);
if (!cli_send_trans(cli, SMBtrans2,
NULL, /* name */
-1, 0, /* fid, flags */
&setup, 1, 0, /* setup, length, max */
param, param_len, 2, /* param, length, max */
NULL, data_len, cli->max_xmit /* data, length, max */
)) {
return False;
}
if (!cli_receive_trans(cli, SMBtrans2,
&rparam, &param_len,
&rdata, &data_len)) {
return False;
}
*poutdata = (char *)memdup(rdata, data_len);
if (!*poutdata) {
SAFE_FREE(rdata);
SAFE_FREE(rparam);
return False;
}
*poutlen = data_len;
SAFE_FREE(rdata);
SAFE_FREE(rparam);
return True;
}
/****************************************************************************
Send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call.
****************************************************************************/
NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
{
unsigned int data_len = 0;
unsigned int param_len = 0;
uint16 setup = TRANSACT2_QPATHINFO;
char param[1024+6];
char *rparam=NULL, *rdata=NULL;
int count=8;
char *p;
bool ret;
unsigned int len;
p = param;
memset(p, 0, 6);
SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
p += 6;
p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
param_len = PTR_DIFF(p, param);
do {
ret = (cli_send_trans(cli, SMBtrans2,
NULL, /* Name */
-1, 0, /* fid, flags */
&setup, 1, 0, /* setup, length, max */
param, param_len, 10, /* param, length, max */
NULL, data_len, cli->max_xmit /* data, length, max */
) &&
cli_receive_trans(cli, SMBtrans2,
&rparam, &param_len,
&rdata, &data_len));
if (!ret && cli_is_dos_error(cli)) {
/* we need to work around a Win95 bug - sometimes
it gives ERRSRV/ERRerror temprarily */
uint8 eclass;
uint32 ecode;
cli_dos_error(cli, &eclass, &ecode);
if (eclass != ERRSRV || ecode != ERRerror) break;
smb_msleep(100);
}
} while (count-- && ret==False);
if (!ret || !rdata || data_len < 4) {
return NT_STATUS_UNSUCCESSFUL;
}
len = IVAL(rdata, 0);
if (len > data_len - 4) {
return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
SAFE_FREE(rdata);
SAFE_FREE(rparam);
return NT_STATUS_OK;
}