summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2002-09-25 15:19:00 +0000
committerGerald Carter <jerry@samba.org>2002-09-25 15:19:00 +0000
commita834a73e341059be154426390304a42e4a011f72 (patch)
tree7f53b0f7819238e0ee0396daccf5d924cb9b8d29 /source3/libsmb
parent115a39775cb923d026dde58633b6ba6aef3a1943 (diff)
downloadsamba-a834a73e341059be154426390304a42e4a011f72.tar.gz
samba-a834a73e341059be154426390304a42e4a011f72.tar.bz2
samba-a834a73e341059be154426390304a42e4a011f72.zip
sync'ing up for 3.0alpha20 release
(This used to be commit 65e7b5273bb58802bf0c389b77f7fcae0a1f6139)
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/asn1.c21
-rw-r--r--source3/libsmb/cliconnect.c279
-rw-r--r--source3/libsmb/clientgen.c144
-rw-r--r--source3/libsmb/clierror.c4
-rw-r--r--source3/libsmb/clifile.c2
-rw-r--r--source3/libsmb/clikrb5.c23
-rw-r--r--source3/libsmb/clilist.c48
-rw-r--r--source3/libsmb/clireadwrite.c2
-rw-r--r--source3/libsmb/clispnego.c92
-rw-r--r--source3/libsmb/libsmb_cache.c4
-rw-r--r--source3/libsmb/libsmbclient.c12
-rw-r--r--source3/libsmb/namecache.c53
-rw-r--r--source3/libsmb/nterr.c2
-rw-r--r--source3/libsmb/smbencrypt.c60
-rw-r--r--source3/libsmb/trust_passwd.c5
15 files changed, 474 insertions, 277 deletions
diff --git a/source3/libsmb/asn1.c b/source3/libsmb/asn1.c
index b4ad3ad0b8..b7cfca41fb 100644
--- a/source3/libsmb/asn1.c
+++ b/source3/libsmb/asn1.c
@@ -174,6 +174,16 @@ BOOL asn1_write_BOOLEAN(ASN1_DATA *data, BOOL v)
return !data->has_error;
}
+/* write a BOOLEAN - hmm, I suspect this one is the correct one, and the
+ above boolean is bogus. Need to check */
+BOOL asn1_write_BOOLEAN2(ASN1_DATA *data, BOOL v)
+{
+ asn1_push_tag(data, ASN1_BOOLEAN);
+ asn1_write_uint8(data, v);
+ asn1_pop_tag(data);
+ return !data->has_error;
+}
+
/* check a BOOLEAN */
BOOL asn1_check_BOOLEAN(ASN1_DATA *data, BOOL v)
{
@@ -244,15 +254,12 @@ BOOL asn1_start_tag(ASN1_DATA *data, uint8 tag)
asn1_read_uint8(data, &b);
if (b & 0x80) {
int n = b & 0x7f;
- if (n > 2) {
- data->has_error = True;
- return False;
- }
asn1_read_uint8(data, &b);
nesting->taglen = b;
- if (n == 2) {
+ while (n > 1) {
asn1_read_uint8(data, &b);
nesting->taglen = (nesting->taglen << 8) | b;
+ n--;
}
} else {
nesting->taglen = b;
@@ -366,6 +373,7 @@ BOOL asn1_read_GeneralString(ASN1_DATA *data, char **s)
BOOL asn1_read_OctetString(ASN1_DATA *data, DATA_BLOB *blob)
{
int len;
+ ZERO_STRUCTP(blob);
if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return False;
len = asn1_tag_remaining(data);
*blob = data_blob(NULL, len);
@@ -382,7 +390,8 @@ BOOL asn1_read_Integer(ASN1_DATA *data, int *i)
if (!asn1_start_tag(data, ASN1_INTEGER)) return False;
while (asn1_tag_remaining(data)>0) {
- *i = (*i << 8) + asn1_read_uint8(data, &b);
+ asn1_read_uint8(data, &b);
+ *i = (*i << 8) + b;
}
return asn1_end_tag(data);
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 93cf3d95db..62acccdfb7 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -50,14 +50,12 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, char *user,
fstring pword;
char *p;
- if (passlen > sizeof(pword)-1) {
+ if (passlen > sizeof(pword)-1)
return False;
- }
/* if in share level security then don't send a password now */
- if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
+ if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
passlen = 0;
- }
if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
/* Encrypted mode needed, and non encrypted password supplied. */
@@ -99,9 +97,8 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, char *user,
show_msg(cli->inbuf);
- if (cli_is_error(cli)) {
+ if (cli_is_error(cli))
return False;
- }
/* use the returned vuid from now on */
cli->vuid = SVAL(cli->inbuf,smb_uid);
@@ -118,17 +115,14 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli)
{
uint32 capabilities = CAP_NT_SMBS;
- if (!cli->force_dos_errors) {
+ if (!cli->force_dos_errors)
capabilities |= CAP_STATUS32;
- }
- if (cli->use_level_II_oplocks) {
+ if (cli->use_level_II_oplocks)
capabilities |= CAP_LEVEL_II_OPLOCKS;
- }
- if (cli->capabilities & CAP_UNICODE) {
+ if (cli->capabilities & CAP_UNICODE)
capabilities |= CAP_UNICODE;
- }
return capabilities;
}
@@ -167,9 +161,8 @@ static BOOL cli_session_setup_guest(struct cli_state *cli)
show_msg(cli->inbuf);
- if (cli_is_error(cli)) {
+ if (cli_is_error(cli))
return False;
- }
cli->vuid = SVAL(cli->inbuf,smb_uid);
@@ -223,9 +216,8 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user,
show_msg(cli->inbuf);
- if (cli_is_error(cli)) {
+ if (cli_is_error(cli))
return False;
- }
cli->vuid = SVAL(cli->inbuf,smb_uid);
p = smb_buf(cli->inbuf);
@@ -237,15 +229,41 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user,
return True;
}
+static void set_signing_on_cli (struct cli_state *cli, char* pass, uint8 response[24])
+{
+ uint8 zero_sig[8];
+ ZERO_STRUCT(zero_sig);
+
+ DEBUG(5, ("Server returned security sig:\n"));
+ dump_data(5, &cli->inbuf[smb_ss_field], 8);
-/**
+ if (cli->sign_info.use_smb_signing) {
+ DEBUG(5, ("smb signing already active on connection\n"));
+ } else if (memcmp(&cli->inbuf[smb_ss_field], zero_sig, 8) != 0) {
+
+ DEBUG(3, ("smb signing enabled!\n"));
+ cli->sign_info.use_smb_signing = True;
+ cli_calculate_mac_key(cli, pass, response);
+ } else {
+ DEBUG(5, ("smb signing NOT enabled!\n"));
+ }
+}
+
+static void set_temp_signing_on_cli(struct cli_state *cli)
+{
+ if (cli->sign_info.negotiated_smb_signing)
+ cli->sign_info.temp_smb_signing = True;
+}
+
+
+/****************************************************************************
do a NT1 NTLM/LM encrypted session setup
@param cli client state to create do session setup on
@param user username
@param pass *either* cleartext password (passlen !=24) or LM response.
@param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
@param workgroup The user's domain.
-*/
+****************************************************************************/
static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
char *pass, int passlen,
@@ -256,11 +274,10 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
uchar pword[24];
uchar ntpword[24];
char *p;
- BOOL tried_signing = False;
+ BOOL have_plaintext = False;
- if (passlen > sizeof(pword) || ntpasslen > sizeof(ntpword)) {
+ if (passlen > sizeof(pword) || ntpasslen > sizeof(ntpword))
return False;
- }
if (passlen != 24) {
/* non encrypted password supplied. Ignore ntpass. */
@@ -268,19 +285,18 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
ntpasslen = 24;
SMBencrypt(pass,cli->secblob.data,pword);
SMBNTencrypt(pass,cli->secblob.data,ntpword);
- if (!cli->sign_info.use_smb_signing && cli->sign_info.negotiated_smb_signing) {
- cli_calculate_mac_key(cli, pass, ntpword);
- tried_signing = True;
- }
+
+ have_plaintext = True;
+ set_temp_signing_on_cli(cli);
} else {
- /* pre-encrypted password supplied. Only used for security=server, can't do
+ /* pre-encrypted password supplied. Only used for
+ security=server, can't do
signing becouse we don't have oringial key */
memcpy(pword, pass, 24);
- if (ntpasslen == 24) {
+ if (ntpasslen == 24)
memcpy(ntpword, ntpass, 24);
- } else {
+ else
ZERO_STRUCT(ntpword);
- }
}
/* send a session setup command */
@@ -301,31 +317,22 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
p = smb_buf(cli->outbuf);
memcpy(p,pword,passlen); p += passlen;
memcpy(p,ntpword,ntpasslen); p += ntpasslen;
- p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
- p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
+ p += clistr_push(cli, p, user, -1, STR_TERMINATE);
+ p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE);
p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
- cli_send_smb(cli);
- if (!cli_receive_smb(cli)) {
- if (tried_signing) {
- /* We only use it if we have a successful non-guest connect */
- cli->sign_info.use_smb_signing = False;
- }
+ if (!cli_send_smb(cli))
return False;
- }
- show_msg(cli->inbuf);
+ if (!cli_receive_smb(cli))
+ return False;
- if (tried_signing && (cli_is_error(cli) || SVAL(cli->inbuf,smb_vwv2) /* guest */)) {
- /* We only use it if we have a successful non-guest connect */
- cli->sign_info.use_smb_signing = False;
- }
+ show_msg(cli->inbuf);
- if (cli_is_error(cli)) {
+ if (cli_is_error(cli))
return False;
- }
/* use the returned vuid from now on */
cli->vuid = SVAL(cli->inbuf,smb_uid);
@@ -337,6 +344,11 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
fstrcpy(cli->user_name, user);
+ if (have_plaintext) {
+ /* Have plaintext orginal */
+ set_signing_on_cli(cli, pass, ntpword);
+ }
+
return True;
}
@@ -360,6 +372,9 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
set_message(cli->outbuf,12,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
+
+ set_temp_signing_on_cli(cli);
+
cli_setup_packet(cli);
SCVAL(cli->outbuf,smb_vwv0,0xFF);
@@ -375,8 +390,8 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
-
cli_send_smb(cli);
+
if (!cli_receive_smb(cli))
return blob2;
@@ -404,7 +419,6 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
return blob2;
}
-
#ifdef HAVE_KRB5
/****************************************************************************
Do a spnego/kerberos encrypted session setup.
@@ -417,7 +431,7 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, char *principal, c
DEBUG(2,("Doing kerberos session setup\n"));
/* generate the encapsulated kerberos5 ticket */
- negTokenTarg = spnego_gen_negTokenTarg(cli, principal);
+ negTokenTarg = spnego_gen_negTokenTarg(principal, 0);
if (!negTokenTarg.data) return False;
@@ -443,28 +457,32 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, char *principal, c
static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
char *pass, char *workgroup)
{
- const char *mechs[] = {OID_NTLMSSP, NULL};
- DATA_BLOB msg1;
- DATA_BLOB blob, chal1, chal2, auth;
+ DATA_BLOB msg1, struct_blob;
+ DATA_BLOB blob, chal1, chal2, auth, challenge_blob;
uint8 challenge[8];
uint8 nthash[24], lmhash[24], sess_key[16];
- uint32 neg_flags;
+ uint32 neg_flags, chal_flags, ntlmssp_command, unkn1, unkn2;
+ pstring server_domain; /* FIX THIS, SHOULD be UCS2-LE */
neg_flags = NTLMSSP_NEGOTIATE_UNICODE |
- NTLMSSP_NEGOTIATE_LM_KEY |
+ NTLMSSP_NEGOTIATE_128 |
NTLMSSP_NEGOTIATE_NTLM;
memset(sess_key, 0, 16);
+ DEBUG(10, ("sending NTLMSSP_NEGOTIATE\n"));
+
/* generate the ntlmssp negotiate packet */
- msrpc_gen(&blob, "CddB",
+ msrpc_gen(&blob, "CddAA",
"NTLMSSP",
NTLMSSP_NEGOTIATE,
neg_flags,
- sess_key, 16);
-
+ workgroup, strlen(workgroup),
+ cli->calling.name, strlen(cli->calling.name) + 1);
+ DEBUG(10, ("neg_flags: %0X, workgroup: %s, calling name %s\n",
+ neg_flags, workgroup, cli->calling.name));
/* and wrap it in a SPNEGO wrapper */
- msg1 = gen_negTokenTarg(mechs, blob);
+ msg1 = gen_negTokenInit(OID_NTLMSSP, blob);
data_blob_free(&blob);
/* now send that blob on its way */
@@ -472,9 +490,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
data_blob_free(&msg1);
- if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_MORE_PROCESSING_REQUIRED))
return False;
- }
#if 0
file_save("chal.dat", blob.data, blob.length);
@@ -488,10 +505,38 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
data_blob_free(&blob);
- /* encrypt the password with the challenge */
- memcpy(challenge, chal1.data + 24, 8);
+ /*
+ * Ok, chal1 and chal2 are actually two identical copies of
+ * the NTLMSSP Challenge BLOB, and they contain, encoded in them
+ * the challenge to use.
+ */
+
+ if (!msrpc_parse(&chal1, "CdUdbddB",
+ "NTLMSSP",
+ &ntlmssp_command,
+ &server_domain,
+ &chal_flags,
+ &challenge_blob, 8,
+ &unkn1, &unkn2,
+ &struct_blob)) {
+ DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n"));
+ return False;
+ }
+
+ if (ntlmssp_command != NTLMSSP_CHALLENGE) {
+ DEBUG(0, ("NTLMSSP Response != NTLMSSP_CHALLENGE. Got %0X\n",
+ ntlmssp_command));
+ return False;
+ }
+
+ DEBUG(10, ("Challenge:\n"));
+ dump_data(10, challenge_blob.data, 8);
+
+ /* encrypt the password with the challenge which is in the blob */
+ memcpy(challenge, challenge_blob.data, 8);
SMBencrypt(pass, challenge,lmhash);
SMBNTencrypt(pass, challenge,nthash);
+ data_blob_free(&challenge_blob);
#if 0
file_save("nthash.dat", nthash, 24);
@@ -511,7 +556,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
workgroup,
user,
cli->calling.name,
- sess_key, 16,
+ sess_key, 0,
neg_flags);
/* wrap it in SPNEGO */
@@ -525,7 +570,12 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
data_blob_free(&auth);
data_blob_free(&blob);
- return !cli_is_error(cli);
+ if (cli_is_error(cli))
+ return False;
+
+ set_signing_on_cli(cli, pass, nthash);
+
+ return True;
}
/****************************************************************************
@@ -537,17 +587,14 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user,
{
char *principal;
char *OIDs[ASN1_MAX_OIDS];
- uint8 guid[16];
int i;
BOOL got_kerberos_mechanism = False;
-
- /* spnego security cannot use SMB signing (for now). */
- cli->sign_info.use_smb_signing = False;
+ DATA_BLOB blob;
DEBUG(2,("Doing spnego session setup (blob length=%d)\n", cli->secblob.length));
/* the server might not even do spnego */
- if (cli->secblob.length == 16) {
+ if (cli->secblob.length <= 16) {
DEBUG(3,("server didn't supply a full spnego negprot\n"));
goto ntlmssp;
}
@@ -556,11 +603,16 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user,
file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
#endif
+ /* there is 16 bytes of GUID before the real spnego packet starts */
+ blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
+
/* the server sent us the first part of the SPNEGO exchange in the negprot
reply */
- if (!spnego_parse_negTokenInit(cli->secblob, guid, OIDs, &principal)) {
+ if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
+ data_blob_free(&blob);
return False;
}
+ data_blob_free(&blob);
/* make sure the server understands kerberos */
for (i=0;OIDs[i];i++) {
@@ -620,35 +672,38 @@ BOOL cli_session_setup(struct cli_state *cli,
flow a bit easier to understand (tridge) */
/* if its an older server then we have to use the older request format */
- if (cli->protocol < PROTOCOL_NT1) {
+
+ if (cli->protocol < PROTOCOL_NT1)
return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
- }
/* if no user is supplied then we have to do an anonymous connection.
passwords are ignored */
- if (!user || !*user) {
+
+ if (!user || !*user)
return cli_session_setup_guest(cli);
- }
/* if the server is share level then send a plaintext null
password at this point. The password is sent in the tree
connect */
- if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
+
+ if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
return cli_session_setup_plaintext(cli, user, "", workgroup);
- }
/* if the server doesn't support encryption then we have to use
plaintext. The second password is ignored */
- if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
+
+ if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0)
return cli_session_setup_plaintext(cli, user, pass, workgroup);
- }
+ /* Indidicate signing */
+
/* if the server supports extended security then use SPNEGO */
- if (cli->capabilities & CAP_EXTENDED_SECURITY) {
+
+ if (cli->capabilities & CAP_EXTENDED_SECURITY)
return cli_session_setup_spnego(cli, user, pass, workgroup);
- }
/* otherwise do a NT1 style session setup */
+
return cli_session_setup_nt1(cli, user,
pass, passlen, ntpass, ntpasslen,
workgroup);
@@ -738,15 +793,13 @@ BOOL cli_send_tconX(struct cli_state *cli,
if (!cli_receive_smb(cli))
return False;
- if (cli_is_error(cli)) {
+ if (cli_is_error(cli))
return False;
- }
clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
- if (strcasecmp(share,"IPC$")==0) {
+ if (strcasecmp(share,"IPC$")==0)
fstrcpy(cli->dev, "IPC");
- }
if (cli->protocol >= PROTOCOL_NT1 &&
smb_buflen(cli->inbuf) == 3) {
@@ -786,9 +839,8 @@ void cli_negprot_send(struct cli_state *cli)
char *p;
int numprots;
- if (cli->protocol < PROTOCOL_NT1) {
+ if (cli->protocol < PROTOCOL_NT1)
cli->use_spnego = False;
- }
memset(cli->outbuf,'\0',smb_size);
@@ -827,9 +879,8 @@ BOOL cli_negprot(struct cli_state *cli)
return False;
}
- if (cli->protocol < PROTOCOL_NT1) {
+ if (cli->protocol < PROTOCOL_NT1)
cli->use_spnego = False;
- }
memset(cli->outbuf,'\0',smb_size);
@@ -891,12 +942,8 @@ BOOL cli_negprot(struct cli_state *cli)
smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
}
- /* A way to attempt to force SMB signing */
- if (getenv("CLI_FORCE_SMB_SIGNING"))
+ if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
cli->sign_info.negotiated_smb_signing = True;
-
- if (cli->sign_info.negotiated_smb_signing && !(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
- cli->sign_info.negotiated_smb_signing = False;
} else if (cli->protocol >= PROTOCOL_LANMAN1) {
cli->use_spnego = False;
@@ -920,9 +967,8 @@ BOOL cli_negprot(struct cli_state *cli)
cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
/* a way to force ascii SMB */
- if (getenv("CLI_FORCE_ASCII")) {
+ if (getenv("CLI_FORCE_ASCII"))
cli->capabilities &= ~CAP_UNICODE;
- }
return True;
}
@@ -938,15 +984,6 @@ BOOL cli_session_request(struct cli_state *cli,
int len = 4;
extern pstring user_socket_options;
- /* 445 doesn't have session request */
- if (cli->port == 445) return True;
-
- if (cli->sign_info.use_smb_signing) {
- DEBUG(0, ("Cannot send session resquest again, particularly after setting up SMB Signing\n"));
- return False;
- }
-
- /* send a session request (RFC 1002) */
memcpy(&(cli->calling), calling, sizeof(*calling));
memcpy(&(cli->called ), called , sizeof(*called ));
@@ -960,6 +997,16 @@ BOOL cli_session_request(struct cli_state *cli,
name_mangle(cli->calling.name, p, cli->calling.name_type);
len += name_len(p);
+ /* 445 doesn't have session request */
+ if (cli->port == 445)
+ return True;
+
+ if (cli->sign_info.use_smb_signing) {
+ DEBUG(0, ("Cannot send session resquest again, particularly after setting up SMB Signing\n"));
+ return False;
+ }
+
+ /* send a session request (RFC 1002) */
/* setup the packet length
* Remove four bytes from the length count, since the length
* field in the NBT Session Service header counts the number
@@ -1066,7 +1113,8 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
port, cli->timeout);
}
- if (cli->fd != -1) cli->port = port;
+ if (cli->fd != -1)
+ cli->port = port;
}
if (cli->fd == -1) {
DEBUG(1,("Error connecting to %s (%s)\n",
@@ -1141,11 +1189,10 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
return NT_STATUS_UNSUCCESSFUL;
}
- if (dest_ip) {
+ if (dest_ip)
ip = *dest_ip;
- } else {
+ else
ZERO_STRUCT(ip);
- }
again:
@@ -1162,8 +1209,7 @@ again:
char *p;
DEBUG(1,("session request to %s failed (%s)\n",
called.name, cli_errstr(cli)));
- cli_shutdown(cli);
- if ((p=strchr(called.name, '.'))) {
+ if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
*p = 0;
goto again;
}
@@ -1174,11 +1220,10 @@ again:
return NT_STATUS_UNSUCCESSFUL;
}
- if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO) {
+ if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
cli->use_spnego = False;
- } else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
+ else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
cli->use_kerberos = True;
- }
if (!cli_negprot(cli)) {
DEBUG(1,("failed negprot\n"));
@@ -1261,18 +1306,22 @@ BOOL attempt_netbios_session_request(struct cli_state *cli, char *srchost, char
DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
with error %s.\n", desthost, cli_errstr(cli) ));
- cli_shutdown(cli);
return False;
}
- cli_shutdown(cli);
+ /*
+ * We need to close the connection here but can't call cli_shutdown as
+ * will free an allocated cli struct. cli_close_connection was invented
+ * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
+ */
+
+ cli_close_connection(cli);
if (!cli_initialise(cli) ||
!cli_connect(cli, desthost, pdest_ip) ||
!cli_session_request(cli, &calling, &smbservername)) {
DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
- cli_shutdown(cli);
return False;
}
}
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index c9500ead5d..793dd19644 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -32,49 +32,48 @@ int cli_set_port(struct cli_state *cli, int port)
}
/****************************************************************************
- read an smb from a fd ignoring all keepalive packets. Note that the buffer
- *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
- The timeout is in milliseconds
-
- This is exactly the same as receive_smb except that it never returns
- a session keepalive packet (just as receive_smb used to do).
- receive_smb was changed to return keepalives as the oplock processing means this call
- should never go into a blocking read.
+ Read an smb from a fd ignoring all keepalive packets. Note that the buffer
+ *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
+ The timeout is in milliseconds
+
+ This is exactly the same as receive_smb except that it never returns
+ a session keepalive packet (just as receive_smb used to do).
+ receive_smb was changed to return keepalives as the oplock processing means this call
+ should never go into a blocking read.
****************************************************************************/
static BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
{
- BOOL ret;
-
- for(;;)
- {
- ret = receive_smb(fd, buffer, timeout);
-
- if (!ret)
- {
- DEBUG(10,("client_receive_smb failed\n"));
- show_msg(buffer);
- return ret;
- }
-
- /* Ignore session keepalive packets. */
- if(CVAL(buffer,0) != SMBkeepalive)
- break;
- }
- show_msg(buffer);
- return ret;
-}
+ BOOL ret;
+
+ for(;;) {
+ ret = receive_smb(fd, buffer, timeout);
+ if (!ret) {
+ DEBUG(10,("client_receive_smb failed\n"));
+ show_msg(buffer);
+ return ret;
+ }
+
+ /* Ignore session keepalive packets. */
+ if(CVAL(buffer,0) != SMBkeepalive)
+ break;
+ }
+ show_msg(buffer);
+ return ret;
+}
/****************************************************************************
-recv an smb
+ Recv an smb.
****************************************************************************/
+
BOOL cli_receive_smb(struct cli_state *cli)
{
BOOL ret;
/* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
- if (cli->fd == -1) return False;
+ if (cli->fd == -1)
+ return False;
again:
ret = client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
@@ -151,34 +150,32 @@ void cli_setup_packet(struct cli_state *cli)
uint16 flags2;
SCVAL(cli->outbuf,smb_flg,0x8);
flags2 = FLAGS2_LONG_PATH_COMPONENTS;
- if (cli->capabilities & CAP_UNICODE) {
+ if (cli->capabilities & CAP_UNICODE)
flags2 |= FLAGS2_UNICODE_STRINGS;
- }
- if (cli->capabilities & CAP_STATUS32) {
+ if (cli->capabilities & CAP_STATUS32)
flags2 |= FLAGS2_32_BIT_ERROR_CODES;
- }
- if (cli->use_spnego) {
+ if (cli->use_spnego)
flags2 |= FLAGS2_EXTENDED_SECURITY;
- }
- if (cli->sign_info.use_smb_signing)
+ if (cli->sign_info.use_smb_signing
+ || cli->sign_info.temp_smb_signing)
flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
SSVAL(cli->outbuf,smb_flg2, flags2);
}
}
/****************************************************************************
-setup the bcc length of the packet from a pointer to the end of the data
+ Setup the bcc length of the packet from a pointer to the end of the data.
****************************************************************************/
+
void cli_setup_bcc(struct cli_state *cli, void *p)
{
set_message_bcc(cli->outbuf, PTR_DIFF(p, smb_buf(cli->outbuf)));
}
-
-
/****************************************************************************
-initialise credentials of a client structure
+ Initialise credentials of a client structure.
****************************************************************************/
+
void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr)
{
/* copy_nt_creds(&cli->usr, usr); */
@@ -193,10 +190,10 @@ void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr)
cli->ntlmssp_flags,cli->ntlmssp_cli_flgs));
}
-
/****************************************************************************
-initialise a client structure
+ Initialise a client structure.
****************************************************************************/
+
struct cli_state *cli_initialise(struct cli_state *cli)
{
BOOL alloced_cli = False;
@@ -215,9 +212,8 @@ struct cli_state *cli_initialise(struct cli_state *cli)
alloced_cli = True;
}
- if (cli->initialised) {
- cli_shutdown(cli);
- }
+ if (cli->initialised)
+ cli_close_connection(cli);
ZERO_STRUCTP(cli);
@@ -234,7 +230,9 @@ struct cli_state *cli_initialise(struct cli_state *cli)
cli->outbuf = (char *)malloc(cli->bufsize);
cli->inbuf = (char *)malloc(cli->bufsize);
cli->oplock_handler = cli_oplock_ack;
- cli->use_spnego = True;
+ if (lp_use_spnego()) {
+ cli->use_spnego = True;
+ }
/* Set the CLI_FORCE_DOSERR environment variable to test
client routines using DOS errors instead of STATUS32
@@ -243,6 +241,10 @@ struct cli_state *cli_initialise(struct cli_state *cli)
cli->force_dos_errors = True;
}
+ /* A way to attempt to force SMB signing */
+ if (getenv("CLI_FORCE_SMB_SIGNING"))
+ cli->sign_info.negotiated_smb_signing = True;
+
if (!cli->outbuf || !cli->inbuf)
goto error;
@@ -273,43 +275,75 @@ struct cli_state *cli_initialise(struct cli_state *cli)
}
/****************************************************************************
-shutdown a client structure
+ Close a client connection and free the memory without destroying cli itself.
****************************************************************************/
-void cli_shutdown(struct cli_state *cli)
+
+void cli_close_connection(struct cli_state *cli)
{
- BOOL allocated;
SAFE_FREE(cli->outbuf);
SAFE_FREE(cli->inbuf);
data_blob_free(&cli->secblob);
- if (cli->mem_ctx)
+ if (cli->mem_ctx) {
talloc_destroy(cli->mem_ctx);
+ cli->mem_ctx = NULL;
+ }
if (cli->fd != -1)
close(cli->fd);
- allocated = cli->allocated;
+ cli->fd = -1;
+}
+
+/****************************************************************************
+ Shutdown a client structure.
+****************************************************************************/
+
+void cli_shutdown(struct cli_state *cli)
+{
+ BOOL allocated = cli->allocated;
+ cli_close_connection(cli);
ZERO_STRUCTP(cli);
if (allocated) {
free(cli);
}
}
-
/****************************************************************************
-set socket options on a open connection
+ Set socket options on a open connection.
****************************************************************************/
+
void cli_sockopt(struct cli_state *cli, char *options)
{
set_socket_options(cli->fd, options);
}
/****************************************************************************
-set the PID to use for smb messages. Return the old pid.
+ Set the PID to use for smb messages. Return the old pid.
****************************************************************************/
+
uint16 cli_setpid(struct cli_state *cli, uint16 pid)
{
uint16 ret = cli->pid;
cli->pid = pid;
return ret;
}
+
+/****************************************************************************
+Send a keepalive packet to the server
+****************************************************************************/
+BOOL cli_send_keepalive(struct cli_state *cli)
+{
+ if (cli->fd == -1) {
+ DEBUG(3, ("cli_send_keepalive: fd == -1\n"));
+ return False;
+ }
+ if (!send_keepalive(cli->fd)) {
+ close(cli->fd);
+ cli->fd = -1;
+ DEBUG(0,("Error sending keepalive packet to client.\n"));
+ return False;
+ }
+ return True;
+}
+
diff --git a/source3/libsmb/clierror.c b/source3/libsmb/clierror.c
index 591c04db22..e1507c6048 100644
--- a/source3/libsmb/clierror.c
+++ b/source3/libsmb/clierror.c
@@ -156,7 +156,7 @@ void cli_dos_error(struct cli_state *cli, uint8 *eclass, uint32 *ecode)
/* Return a UNIX errno from a dos error class, error number tuple */
-int cli_errno_from_dos(uint8 eclass, uint32 num)
+static int cli_errno_from_dos(uint8 eclass, uint32 num)
{
if (eclass == ERRDOS) {
switch (num) {
@@ -205,7 +205,7 @@ static struct {
{NT_STATUS(0), 0}
};
-int cli_errno_from_nt(NTSTATUS status)
+static int cli_errno_from_nt(NTSTATUS status)
{
int i;
DEBUG(10,("cli_errno_from_nt: 32 bit codes: code=%08x\n", NT_STATUS_V(status)));
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index a47c956a55..07b1ff6b6f 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -94,7 +94,7 @@ uint32 unix_perms_to_wire(mode_t perms)
ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0);
#endif
#ifdef S_ISUID
- ret |= ((perms & S_ISVTX) ? UNIX_SET_UID : 0);
+ ret |= ((perms & S_ISUID) ? UNIX_SET_UID : 0);
#endif
return ret;
}
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index 685c4a25e0..e7143d065d 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -64,6 +64,14 @@ static krb5_error_code krb5_mk_req2(krb5_context context,
goto cleanup_creds;
}
+ /* cope with the ticket being in the future due to clock skew */
+ if ((unsigned)credsp->times.starttime > time(NULL)) {
+ time_t t = time(NULL);
+ int time_offset = (unsigned)credsp->times.starttime - t;
+ DEBUG(4,("Advancing clock by %d seconds to cope with clock skew\n", time_offset));
+ krb5_set_real_time(context, t + time_offset + 1, 0);
+ }
+
in_data.length = 0;
retval = krb5_mk_req_extended(context, auth_context, ap_req_options,
&in_data, credsp, outbuf);
@@ -86,7 +94,7 @@ cleanup_princ:
/*
get a kerberos5 ticket for the given service
*/
-DATA_BLOB krb5_get_ticket(char *principal)
+DATA_BLOB krb5_get_ticket(char *principal, time_t time_offset)
{
krb5_error_code retval;
krb5_data packet;
@@ -94,7 +102,12 @@ DATA_BLOB krb5_get_ticket(char *principal)
krb5_context context;
krb5_auth_context auth_context = NULL;
DATA_BLOB ret;
- krb5_enctype enc_types[] = {ENCTYPE_DES_CBC_MD5, ENCTYPE_NULL};
+ krb5_enctype enc_types[] = {
+#ifdef ENCTYPE_ARCFOUR_HMAC
+ ENCTYPE_ARCFOUR_HMAC,
+#endif
+ ENCTYPE_DES_CBC_MD5,
+ ENCTYPE_NULL};
retval = krb5_init_context(&context);
if (retval) {
@@ -103,6 +116,10 @@ DATA_BLOB krb5_get_ticket(char *principal)
goto failed;
}
+ if (time_offset != 0) {
+ krb5_set_real_time(context, time(NULL) + time_offset, 0);
+ }
+
if ((retval = krb5_cc_default(context, &ccdef))) {
DEBUG(1,("krb5_cc_default failed (%s)\n",
error_message(retval)));
@@ -137,7 +154,7 @@ failed:
#else /* HAVE_KRB5 */
/* this saves a few linking headaches */
- DATA_BLOB krb5_get_ticket(char *principal)
+ DATA_BLOB krb5_get_ticket(char *principal, time_t time_offset)
{
DEBUG(0,("NO KERBEROS SUPPORT\n"));
return data_blob(NULL, 0);
diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
index 17a759f9e3..3eacc25380 100644
--- a/source3/libsmb/clilist.c
+++ b/source3/libsmb/clilist.c
@@ -22,13 +22,13 @@
#include "includes.h"
-
/****************************************************************************
-interpret a long filename structure - this is mostly guesses at the moment
-The length of the structure is returned
-The structure of a long filename depends on the info level. 260 is used
-by NT and 2 is used by OS/2
+ Interpret a long filename structure - this is mostly guesses at the moment.
+ The length of the structure is returned
+ The structure of a long filename depends on the info level. 260 is used
+ by NT and 2 is used by OS/2
****************************************************************************/
+
static int interpret_long_filename(struct cli_state *cli,
int level,char *p,file_info *finfo)
{
@@ -41,8 +41,7 @@ static int interpret_long_filename(struct cli_state *cli,
memcpy(finfo,&def_finfo,sizeof(*finfo));
- switch (level)
- {
+ switch (level) {
case 1: /* OS/2 understands this */
/* these dates are converted to GMT by
make_unix_date */
@@ -126,16 +125,16 @@ static int interpret_long_filename(struct cli_state *cli,
namelen, 0);
return SVAL(base, 0);
}
- }
+ }
DEBUG(1,("Unknown long filename format %d\n",level));
return(SVAL(p,0));
}
-
/****************************************************************************
- do a directory listing, calling fn on each file found
- ****************************************************************************/
+ Do a directory listing, calling fn on each file found.
+****************************************************************************/
+
int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
void (*fn)(file_info *, const char *, void *), void *state)
{
@@ -307,12 +306,11 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
return(total_received);
}
-
-
/****************************************************************************
-interpret a short filename structure
-The length of the structure is returned
+ Interpret a short filename structure.
+ The length of the structure is returned.
****************************************************************************/
+
static int interpret_short_filename(struct cli_state *cli, char *p,file_info *finfo)
{
extern file_info def_finfo;
@@ -334,10 +332,11 @@ static int interpret_short_filename(struct cli_state *cli, char *p,file_info *fi
/****************************************************************************
- do a directory listing, calling fn on each file found
- this uses the old SMBsearch interface. It is needed for testing Samba,
- but should otherwise not be used
- ****************************************************************************/
+ Do a directory listing, calling fn on each file found.
+ this uses the old SMBsearch interface. It is needed for testing Samba,
+ but should otherwise not be used.
+****************************************************************************/
+
int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
void (*fn)(file_info *, const char *, void *), void *state)
{
@@ -453,16 +452,15 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
return(num_received);
}
-
/****************************************************************************
- do a directory listing, calling fn on each file found
- this auto-switches between old and new style
- ****************************************************************************/
+ Do a directory listing, calling fn on each file found.
+ This auto-switches between old and new style.
+****************************************************************************/
+
int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
void (*fn)(file_info *, const char *, void *), void *state)
{
- if (cli->protocol <= PROTOCOL_LANMAN1) {
+ if (cli->protocol <= PROTOCOL_LANMAN1)
return cli_list_old(cli, Mask, attribute, fn, state);
- }
return cli_list_new(cli, Mask, attribute, fn, state);
}
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index 756a6cce2f..875df11dca 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -127,7 +127,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_
return total;
}
-#if 0 /* relies on client_recieve_smb(), now a static in libsmb/clientgen.c */
+#if 0 /* relies on client_receive_smb(), now a static in libsmb/clientgen.c */
/* This call is INCOMPATIBLE with SMB signing. If you remove the #if 0
you must fix ensure you don't attempt to sign the packets - data
diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index 16702c375b..55f49c5987 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -73,13 +73,56 @@ DATA_BLOB spnego_gen_negTokenInit(uint8 guid[16],
return ret;
}
+/*
+ Generate a negTokenInit as used by the client side ... It has a mechType
+ (OID), and a mechToken (a security blob) ...
+
+ Really, we need to break out the NTLMSSP stuff as well, because it could be
+ raw in the packets!
+*/
+DATA_BLOB gen_negTokenInit(const char *OID, DATA_BLOB blob)
+{
+ ASN1_DATA data;
+ DATA_BLOB ret;
+
+ memset(&data, 0, sizeof(data));
+
+ asn1_push_tag(&data, ASN1_APPLICATION(0));
+ asn1_write_OID(&data,OID_SPNEGO);
+ asn1_push_tag(&data, ASN1_CONTEXT(0));
+ asn1_push_tag(&data, ASN1_SEQUENCE(0));
+
+ asn1_push_tag(&data, ASN1_CONTEXT(0));
+ asn1_push_tag(&data, ASN1_SEQUENCE(0));
+ asn1_write_OID(&data, OID);
+ asn1_pop_tag(&data);
+ asn1_pop_tag(&data);
+
+ asn1_push_tag(&data, ASN1_CONTEXT(2));
+ asn1_write_OctetString(&data,blob.data,blob.length);
+ asn1_pop_tag(&data);
+
+ asn1_pop_tag(&data);
+ asn1_pop_tag(&data);
+
+ asn1_pop_tag(&data);
+
+ if (data.has_error) {
+ DEBUG(1,("Failed to build negTokenInit at offset %d\n", (int)data.ofs));
+ asn1_free(&data);
+ }
+
+ ret = data_blob(data.data, data.length);
+ asn1_free(&data);
+
+ return ret;
+}
/*
parse a negTokenInit packet giving a GUID, a list of supported
OIDs (the mechanisms) and a principal name string
*/
BOOL spnego_parse_negTokenInit(DATA_BLOB blob,
- uint8 guid[16],
char *OIDs[ASN1_MAX_OIDS],
char **principal)
{
@@ -89,7 +132,6 @@ BOOL spnego_parse_negTokenInit(DATA_BLOB blob,
asn1_load(&data, blob);
- asn1_read(&data, guid, 16);
asn1_start_tag(&data,ASN1_APPLICATION(0));
asn1_check_OID(&data,OID_SPNEGO);
asn1_start_tag(&data,ASN1_CONTEXT(0));
@@ -279,13 +321,13 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket)
generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
kerberos session setup
*/
-DATA_BLOB spnego_gen_negTokenTarg(struct cli_state *cli, char *principal)
+DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset)
{
DATA_BLOB tkt, tkt_wrapped, targ;
const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL};
/* get a kerberos ticket for the service */
- tkt = krb5_get_ticket(principal);
+ tkt = krb5_get_ticket(principal, time_offset);
/* wrap that up in a nice GSS-API wrapping */
tkt_wrapped = spnego_gen_krb5_wrap(tkt);
@@ -473,8 +515,10 @@ DATA_BLOB spnego_gen_auth_response(void)
U = unicode string (input is unix string)
a = address (1 byte type, 1 byte length, unicode string, all inline)
+ A = ASCII string (pointer + length) Actually same as B
B = data blob (pointer + length)
b = data blob in header (pointer + length)
+ D
d = word (4 bytes)
C = constant ascii string
*/
@@ -502,6 +546,7 @@ BOOL msrpc_gen(DATA_BLOB *blob,
s = va_arg(ap, char *);
data_size += (str_charnum(s) * 2) + 4;
break;
+ case 'A':
case 'B':
b = va_arg(ap, uint8 *);
head_size += 8;
@@ -553,7 +598,8 @@ BOOL msrpc_gen(DATA_BLOB *blob,
}
data_ofs += n*2;
break;
-
+
+ case 'A':
case 'B':
b = va_arg(ap, uint8 *);
n = va_arg(ap, int);
@@ -688,37 +734,39 @@ BOOL msrpc_parse(DATA_BLOB *blob,
void debug_ntlmssp_flags(uint32 neg_flags)
{
+ DEBUG(3,("Got NTLMSSP neg_flags=0x%08x\n", neg_flags));
+
if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_UNICODE\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_UNICODE\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_OEM)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_OEM\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_OEM\n"));
if (neg_flags & NTLMSSP_REQUEST_TARGET)
- DEBUG(4, (" NTLMSSP_REQUEST_TARGET\n"));
- if (neg_flags & NTLMSSP_NEGOTIATE_SIGN)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_SIGN\n"));
+ DEBUGADD(4, (" NTLMSSP_REQUEST_TARGET\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_SIGN)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_SEAL\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SIGN\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_SEAL)
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SEAL\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_LM_KEY\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_LM_KEY\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_NETWARE\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NETWARE\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_NTLM)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_NTLM\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_NTLM2\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM2\n"));
if (neg_flags & NTLMSSP_CHAL_TARGET_INFO)
- DEBUG(4, (" NTLMSSP_CHAL_TARGET_INFO\n"));
+ DEBUGADD(4, (" NTLMSSP_CHAL_TARGET_INFO\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_128)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_128\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_128\n"));
if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
- DEBUG(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
+ DEBUGADD(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
}
diff --git a/source3/libsmb/libsmb_cache.c b/source3/libsmb/libsmb_cache.c
index 34b818ee74..df02cf3718 100644
--- a/source3/libsmb/libsmb_cache.c
+++ b/source3/libsmb/libsmb_cache.c
@@ -89,7 +89,7 @@ static int smbc_add_cached_server(SMBCCTX * context, SMBCSRV * new,
goto failed;
}
- DLIST_ADD(((struct smbc_server_cache *)context->server_cache), srvcache);
+ DLIST_ADD((context->server_cache), srvcache);
return 0;
failed:
@@ -139,7 +139,7 @@ static int smbc_remove_cached_server(SMBCCTX * context, SMBCSRV * server)
if (server == srv->server) {
/* remove this sucker */
- DLIST_REMOVE(((struct smbc_server_cache *)context->server_cache), srv);
+ DLIST_REMOVE(context->server_cache, srv);
SAFE_FREE(srv->server_name);
SAFE_FREE(srv->share_name);
SAFE_FREE(srv->workgroup);
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c
index 0ffc1c1378..44cba611d2 100644
--- a/source3/libsmb/libsmbclient.c
+++ b/source3/libsmb/libsmbclient.c
@@ -180,14 +180,13 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share,
static int smbc_errno(SMBCCTX *context, struct cli_state *c)
{
- int ret;
-
+ int ret = cli_errno(c);
+
if (cli_is_dos_error(c)) {
uint8 eclass;
uint32 ecode;
cli_dos_error(c, &eclass, &ecode);
- ret = cli_errno_from_dos(eclass, ecode);
DEBUG(3,("smbc_error %d %d (0x%x) -> %d\n",
(int)eclass, (int)ecode, (int)ecode, ret));
@@ -195,10 +194,9 @@ static int smbc_errno(SMBCCTX *context, struct cli_state *c)
NTSTATUS status;
status = cli_nt_error(c);
- ret = cli_errno_from_nt(status);
DEBUG(3,("smbc errno %s -> %d\n",
- get_nt_error_msg(status), ret));
+ nt_errstr(status), ret));
}
return ret;
@@ -213,7 +211,7 @@ static int smbc_errno(SMBCCTX *context, struct cli_state *c)
*/
int smbc_check_server(SMBCCTX * context, SMBCSRV * server)
{
- if ( cli_send_keepalive(&server->cli) == False )
+ if ( send_keepalive(server->cli.fd) == False )
return 1;
/* connection is ok */
@@ -380,7 +378,7 @@ SMBCSRV *smbc_server(SMBCCTX *context,
fstring remote_name;
struct in_addr rem_ip;
- if (!inet_aton(server, &rem_ip)) {
+ if ((rem_ip.s_addr=inet_addr(server)) == INADDR_NONE) {
DEBUG(4, ("Could not convert IP address %s to struct in_addr\n", server));
errno = ENOENT;
return NULL;
diff --git a/source3/libsmb/namecache.c b/source3/libsmb/namecache.c
index fc09d8eac2..2252e8e59c 100644
--- a/source3/libsmb/namecache.c
+++ b/source3/libsmb/namecache.c
@@ -29,24 +29,24 @@ static TDB_CONTEXT *namecache_tdb;
struct nc_value {
time_t expiry; /* When entry expires */
int count; /* Number of addresses */
- struct in_addr ip_list[0]; /* Address list */
+ struct in_addr ip_list[1]; /* Address list */
};
/* Initialise namecache system */
-void namecache_enable(void)
+BOOL namecache_enable(void)
{
/* Check if we have been here before, or name caching disabled
by setting the name cache timeout to zero. */
if (done_namecache_init)
- return;
+ return False;
done_namecache_init = True;
if (lp_name_cache_timeout() == 0) {
DEBUG(5, ("namecache_init: disabling netbios name cache\n"));
- return;
+ return False;
}
/* Open namecache tdb in read/write or readonly mode */
@@ -58,13 +58,15 @@ void namecache_enable(void)
if (!namecache_tdb) {
DEBUG(5, ("namecache_init: could not open %s\n",
lock_path("namecache.tdb")));
- return;
+ return False;
}
DEBUG(5, ("namecache_init: enabling netbios namecache, timeout %d "
"seconds\n", lp_name_cache_timeout()));
enable_namecache = True;
+
+ return True;
}
/* Return a key for a name and name type. The caller must free
@@ -91,17 +93,20 @@ static TDB_DATA namecache_value(struct in_addr *ip_list, int num_names,
{
TDB_DATA retval;
struct nc_value *value;
- int size;
+ int size = sizeof(struct nc_value);
- size = sizeof(struct nc_value) + sizeof(struct in_addr) *
- num_names;
+ if (num_names > 0)
+ size += sizeof(struct in_addr) * (num_names-1);
value = (struct nc_value *)malloc(size);
-
+
+ memset(value, 0, size);
+
value->expiry = expiry;
value->count = num_names;
- memcpy(value->ip_list, ip_list, num_names * sizeof(struct in_addr));
+ if (ip_list)
+ memcpy(value->ip_list, ip_list, sizeof(struct in_addr) * num_names);
retval.dptr = (char *)value;
retval.dsize = size;
@@ -160,6 +165,9 @@ BOOL namecache_fetch(const char *name, int name_type, struct in_addr **ip_list,
time_t now;
int i;
+ *ip_list = NULL;
+ *num_names = 0;
+
if (!enable_namecache)
return False;
@@ -209,20 +217,23 @@ BOOL namecache_fetch(const char *name, int name_type, struct in_addr **ip_list,
/* Extract and return namelist */
- *ip_list = (struct in_addr *)malloc(
- sizeof(struct in_addr) * data->count);
-
- memcpy(*ip_list, data->ip_list, sizeof(struct in_addr) *
- data->count);
+ DEBUG(5, ("namecache_fetch: returning %d address%s for %s#%02x: ",
+ data->count, data->count == 1 ? "" : "es", name, name_type));
- *num_names = data->count;
+ if (data->count) {
- DEBUG(5, ("namecache_fetch: returning %d address%s for %s#%02x: ",
- *num_names, *num_names == 1 ? "" : "es", name, name_type));
+ *ip_list = (struct in_addr *)malloc(
+ sizeof(struct in_addr) * data->count);
+
+ memcpy(*ip_list, data->ip_list, sizeof(struct in_addr) * data->count);
+
+ *num_names = data->count;
+
+ for (i = 0; i < *num_names; i++)
+ DEBUGADD(5, ("%s%s", inet_ntoa((*ip_list)[i]),
+ i == (*num_names - 1) ? "" : ", "));
- for (i = 0; i < *num_names; i++)
- DEBUGADD(5, ("%s%s", inet_ntoa((*ip_list)[i]),
- i == (*num_names - 1) ? "" : ", "));
+ }
DEBUGADD(5, ("\n"));
diff --git a/source3/libsmb/nterr.c b/source3/libsmb/nterr.c
index e2da6318e1..02fd53fc05 100644
--- a/source3/libsmb/nterr.c
+++ b/source3/libsmb/nterr.c
@@ -28,7 +28,7 @@ typedef const struct
NTSTATUS nt_errcode;
} nt_err_code_struct;
-nt_err_code_struct nt_errs[] =
+static nt_err_code_struct nt_errs[] =
{
{ "NT_STATUS_OK", NT_STATUS_OK },
{ "NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL },
diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c
index dfa355a7ec..db265c4bf7 100644
--- a/source3/libsmb/smbencrypt.c
+++ b/source3/libsmb/smbencrypt.c
@@ -116,39 +116,63 @@ void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar p16[16])
}
/* Does both the NTLMv2 owfs of a user's password */
-void ntv2_owf_gen(const uchar owf[16],
- const char *user_n, const char *domain_n, uchar kr_buf[16])
+BOOL ntv2_owf_gen(const uchar owf[16],
+ const char *user_in, const char *domain_in, uchar kr_buf[16])
{
- pstring user_u;
- pstring dom_u;
+ smb_ucs2_t *user;
+ smb_ucs2_t *domain;
+
+ int user_byte_len;
+ int domain_byte_len;
+
HMACMD5Context ctx;
- int user_l = strlen(user_n);
- int domain_l = strlen(domain_n);
+ user_byte_len = push_ucs2_allocate(&user, user_in);
+ if (user_byte_len < 0) {
+ DEBUG(0, ("push_uss2_allocate() for user returned %d (probably malloc() failure)\n", user_byte_len));
+ return False;
+ }
- push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
- push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
+ domain_byte_len = push_ucs2_allocate(&domain, domain_in);
+ if (domain_byte_len < 0) {
+ DEBUG(0, ("push_uss2_allocate() for domain returned %d (probably malloc() failure)\n", user_byte_len));
+ return False;
+ }
+
+ strupper_w(user);
+ strupper_w(domain);
+
+ /* We don't want null termination */
+ user_byte_len = user_byte_len - 2;
+ domain_byte_len = domain_byte_len - 2;
+
+ SMB_ASSERT(user_byte_len >= 0);
+ SMB_ASSERT(domain_byte_len >= 0);
hmac_md5_init_limK_to_64(owf, 16, &ctx);
- hmac_md5_update((const unsigned char *)user_u, user_l * 2, &ctx);
- hmac_md5_update((const unsigned char *)dom_u, domain_l * 2, &ctx);
+ hmac_md5_update((const unsigned char *)user, user_byte_len, &ctx);
+ hmac_md5_update((const unsigned char *)domain, domain_byte_len, &ctx);
hmac_md5_final(kr_buf, &ctx);
#ifdef DEBUG_PASSWORD
DEBUG(100, ("ntv2_owf_gen: user, domain, owfkey, kr\n"));
- dump_data(100, user_u, user_l * 2);
- dump_data(100, dom_u, domain_l * 2);
+ dump_data(100, (const char *)user, user_byte_len);
+ dump_data(100, (const char *)domain, domain_byte_len);
dump_data(100, owf, 16);
dump_data(100, kr_buf, 16);
#endif
+
+ SAFE_FREE(user);
+ SAFE_FREE(domain);
+ return True;
}
/* Does the des encryption from the NT or LM MD4 hash. */
void SMBOWFencrypt(const uchar passwd[16], const uchar *c8, uchar p24[24])
{
uchar p21[21];
-
- memset(p21,'\0',21);
+
+ ZERO_STRUCT(p21);
memcpy(p21, passwd, 16);
E_P24(p21, c8, p24);
@@ -362,6 +386,12 @@ void cli_caclulate_sign_mac(struct cli_state *cli)
unsigned char calc_md5_mac[16];
struct MD5Context md5_ctx;
+ if (cli->sign_info.temp_smb_signing) {
+ memcpy(&cli->outbuf[smb_ss_field], "SignRequest", 8);
+ cli->sign_info.temp_smb_signing = False;
+ return;
+ }
+
if (!cli->sign_info.use_smb_signing) {
return;
}
@@ -380,6 +410,8 @@ void cli_caclulate_sign_mac(struct cli_state *cli)
MD5Final(calc_md5_mac, &md5_ctx);
memcpy(&cli->outbuf[smb_ss_field], calc_md5_mac, 8);
+/* cli->outbuf[smb_ss_field+2]=0;
+ Uncomment this to test if the remote server actually verifies signitures...*/
cli->sign_info.send_seq_num++;
cli->sign_info.reply_seq_num = cli->sign_info.send_seq_num;
cli->sign_info.send_seq_num++;
diff --git a/source3/libsmb/trust_passwd.c b/source3/libsmb/trust_passwd.c
index fe6b673e39..4d7acd1988 100644
--- a/source3/libsmb/trust_passwd.c
+++ b/source3/libsmb/trust_passwd.c
@@ -35,8 +35,9 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_
unsigned char new_trust_passwd_hash[16])
{
NTSTATUS result;
- result = cli_nt_setup_creds(cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
- SEC_CHAN_WKSTA : SEC_CHAN_BDC, orig_trust_passwd_hash);
+ uint32 neg_flags = 0x000001ff;
+
+ result = cli_nt_setup_creds(cli, get_sec_chan(), orig_trust_passwd_hash, &neg_flags, 2);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(1,("just_change_the_password: unable to setup creds (%s)!\n",