summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim McDonough <jmcd@samba.org>2002-08-15 12:18:25 +0000
committerJim McDonough <jmcd@samba.org>2002-08-15 12:18:25 +0000
commit1f9b3d46c7c99e84b2983220f79613b7420c5ced (patch)
treeda5a30c7caba2bfc38bba135ecb46f61b9d5a7a9
parent8bca3085836255536794444248e7ff3a2460c045 (diff)
downloadsamba-1f9b3d46c7c99e84b2983220f79613b7420c5ced.tar.gz
Fix NTLMSSP challenge command and auth response. We can now service joins
from win2k AND still use SPNEGO (provided you don't build with kerberos...I still have to fix that, as we are not properly falling back).
-rw-r--r--source/libsmb/clispnego.c61
-rw-r--r--source/smbd/sesssetup.c68
2 files changed, 98 insertions, 31 deletions
diff --git a/source/libsmb/clispnego.c b/source/libsmb/clispnego.c
index 469b946088c..16702c375b2 100644
--- a/source/libsmb/clispnego.c
+++ b/source/libsmb/clispnego.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
simple kerberos5/SPNEGO routines
Copyright (C) Andrew Tridgell 2001
+ Copyright (C) Jim McDonough 2002
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
@@ -439,6 +440,28 @@ BOOL spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth)
return True;
}
+/*
+ generate a minimal SPNEGO NTLMSSP response packet. Doesn't contain much.
+*/
+DATA_BLOB spnego_gen_auth_response(void)
+{
+ ASN1_DATA data;
+ DATA_BLOB ret;
+
+ memset(&data, 0, sizeof(data));
+
+ asn1_push_tag(&data, ASN1_CONTEXT(1));
+ asn1_push_tag(&data, ASN1_SEQUENCE(0));
+ asn1_push_tag(&data, ASN1_CONTEXT(0));
+ asn1_write_enumerated(&data, 0);
+ asn1_pop_tag(&data);
+ asn1_pop_tag(&data);
+ asn1_pop_tag(&data);
+
+ ret = data_blob(data.data, data.length);
+ asn1_free(&data);
+ return ret;
+}
/*
this is a tiny msrpc packet generator. I am only using this to
@@ -449,6 +472,7 @@ BOOL spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth)
format specifiers are:
U = unicode string (input is unix string)
+ a = address (1 byte type, 1 byte length, unicode string, all inline)
B = data blob (pointer + length)
b = data blob in header (pointer + length)
d = word (4 bytes)
@@ -473,6 +497,11 @@ BOOL msrpc_gen(DATA_BLOB *blob,
head_size += 8;
data_size += str_charnum(s) * 2;
break;
+ case 'a':
+ n = va_arg(ap, int);
+ s = va_arg(ap, char *);
+ data_size += (str_charnum(s) * 2) + 4;
+ break;
case 'B':
b = va_arg(ap, uint8 *);
head_size += 8;
@@ -512,6 +541,19 @@ BOOL msrpc_gen(DATA_BLOB *blob,
push_string(NULL, blob->data+data_ofs, s, n*2, STR_UNICODE|STR_NOALIGN);
data_ofs += n*2;
break;
+ case 'a':
+ n = va_arg(ap, int);
+ SSVAL(blob->data, data_ofs, n); data_ofs += 2;
+ s = va_arg(ap, char *);
+ n = str_charnum(s);
+ SSVAL(blob->data, data_ofs, n*2); data_ofs += 2;
+ if (0 < n) {
+ push_string(NULL, blob->data+data_ofs, s, n*2,
+ STR_UNICODE|STR_NOALIGN);
+ }
+ data_ofs += n*2;
+ break;
+
case 'B':
b = va_arg(ap, uint8 *);
n = va_arg(ap, int);
@@ -550,6 +592,7 @@ BOOL msrpc_gen(DATA_BLOB *blob,
format specifiers are:
U = unicode string (output is unix string)
+ A = ascii string
B = data blob
b = data blob in header
d = word (4 bytes)
@@ -584,6 +627,24 @@ BOOL msrpc_parse(DATA_BLOB *blob,
STR_UNICODE|STR_NOALIGN);
(*ps) = strdup(p);
break;
+ case 'A':
+ len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
+ len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
+ ptr = IVAL(blob->data, head_ofs); head_ofs += 4;
+
+ /* make sure its in the right format - be strict */
+ if (len1 != len2 || ptr + len1 > blob->length) {
+ return False;
+ }
+ ps = va_arg(ap, char **);
+ if (0 < len1) {
+ pull_string(NULL, p, blob->data + ptr, -1,
+ len1, STR_ASCII|STR_NOALIGN);
+ (*ps) = strdup(p);
+ } else {
+ (*ps) = NULL;
+ }
+ break;
case 'B':
len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index d45b04202e9..bb78129667c 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -3,6 +3,7 @@
handle SMBsessionsetup
Copyright (C) Andrew Tridgell 1998-2001
Copyright (C) Andrew Bartlett 2001
+ Copyright (C) Jim McDonough 2002
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
@@ -206,7 +207,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
send a security blob via a session setup reply
****************************************************************************/
static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
- DATA_BLOB blob)
+ DATA_BLOB blob, uint32 errcode)
{
char *p;
@@ -215,7 +216,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
/* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
that we aren't finished yet */
- SIVAL(outbuf, smb_rcls, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
+ SIVAL(outbuf, smb_rcls, errcode);
SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
SSVAL(outbuf, smb_vwv3, blob.length);
p = smb_buf(outbuf);
@@ -242,11 +243,12 @@ static int reply_spnego_negotiate(connection_struct *conn,
DATA_BLOB secblob;
int i;
uint32 ntlmssp_command, neg_flags, chal_flags;
- DATA_BLOB chal, spnego_chal, extra_data;
+ DATA_BLOB chal, spnego_chal;
const uint8 *cryptkey;
BOOL got_kerberos = False;
NTSTATUS nt_status;
extern pstring global_myname;
+ char *cliname=NULL, *domname=NULL;
/* parse out the OIDs and the first sec blob */
if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
@@ -277,19 +279,16 @@ static int reply_spnego_negotiate(connection_struct *conn,
file_save("secblob.dat", secblob.data, secblob.length);
#endif
- if (!msrpc_parse(&secblob, "CddB",
+ if (!msrpc_parse(&secblob, "CddAA",
"NTLMSSP",
&ntlmssp_command,
&neg_flags,
- &extra_data)) {
+ &cliname,
+ &domname)) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- DEBUG(5, ("Extra data: \n"));
- dump_data(5, extra_data.data, extra_data.length);
-
data_blob_free(&secblob);
- data_blob_free(&extra_data);
if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
@@ -318,36 +317,39 @@ static int reply_spnego_negotiate(connection_struct *conn,
NTLMSSP_CHAL_TARGET_INFO;
{
- DATA_BLOB domain_blob, netbios_blob, realm_blob;
+ DATA_BLOB domain_blob, struct_blob;
+ fstring dnsname, dnsdomname;
msrpc_gen(&domain_blob,
"U",
lp_workgroup());
- msrpc_gen(&netbios_blob,
- "U",
- global_myname);
-
- msrpc_gen(&realm_blob,
- "U",
- lp_realm());
-
+ fstrcpy(dnsdomname, lp_realm());
+ strlower(dnsdomname);
+
+ fstrcpy(dnsname, global_myname);
+ fstrcat(dnsname, ".");
+ fstrcat(dnsname, lp_realm());
+ strlower(dnsname);
+
+ msrpc_gen(&struct_blob, "aaaaa",
+ 2, lp_workgroup(),
+ 1, global_myname,
+ 4, dnsdomname,
+ 3, dnsname,
+ 0, NULL);
- msrpc_gen(&chal, "CddddbBBBB",
+ msrpc_gen(&chal, "CdUdbddB",
"NTLMSSP",
NTLMSSP_CHALLENGE,
- 0,
- 0x30, /* ?? */
+ lp_workgroup(),
chal_flags,
cryptkey, 8,
- domain_blob.data, domain_blob.length,
- domain_blob.data, domain_blob.length,
- netbios_blob.data, netbios_blob.length,
- realm_blob.data, realm_blob.length);
+ 0, 0,
+ struct_blob.data, struct_blob.length);
data_blob_free(&domain_blob);
- data_blob_free(&netbios_blob);
- data_blob_free(&realm_blob);
+ data_blob_free(&struct_blob);
}
if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
@@ -357,7 +359,7 @@ static int reply_spnego_negotiate(connection_struct *conn,
}
/* now tell the client to send the auth packet */
- reply_sesssetup_blob(conn, outbuf, spnego_chal);
+ reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
data_blob_free(&chal);
data_blob_free(&spnego_chal);
@@ -374,7 +376,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
int length, int bufsize,
DATA_BLOB blob1)
{
- DATA_BLOB auth;
+ DATA_BLOB auth, response;
char *workgroup = NULL, *user = NULL, *machine = NULL;
DATA_BLOB lmhash, nthash, sess_key;
DATA_BLOB plaintext_password = data_blob(NULL, 0);
@@ -494,8 +496,12 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
SSVAL(outbuf,smb_uid,sess_vuid);
SSVAL(inbuf,smb_uid,sess_vuid);
-
- return chain_reply(inbuf,outbuf,length,bufsize);
+
+ response = spnego_gen_auth_response();
+ reply_sesssetup_blob(conn, outbuf, response, 0);
+
+ /* and tell smbd that we have already replied to this packet */
+ return -1;
}