summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/include/asn_1.h4
-rw-r--r--source/libsmb/clispnego.c67
-rw-r--r--source/libsmb/ntlmssp.c4
-rw-r--r--source/smbd/sesssetup.c178
4 files changed, 80 insertions, 173 deletions
diff --git a/source/include/asn_1.h b/source/include/asn_1.h
index 7783ab4c2f6..9cd873c18a2 100644
--- a/source/include/asn_1.h
+++ b/source/include/asn_1.h
@@ -55,4 +55,8 @@ typedef struct {
#define OID_KERBEROS5_OLD "1 2 840 48018 1 2 2"
#define OID_KERBEROS5 "1 2 840 113554 1 2 2"
+#define SPNGEO_NEG_RESULT_ACCEPT 0
+#define SPNGEO_NEG_RESULT_INCOMPLETE 1
+#define SPNGEO_NEG_RESULT_REJECT 2
+
#endif /* _ASN_1_H */
diff --git a/source/libsmb/clispnego.c b/source/libsmb/clispnego.c
index f4a414ef525..3e28baa417c 100644
--- a/source/libsmb/clispnego.c
+++ b/source/libsmb/clispnego.c
@@ -387,51 +387,6 @@ BOOL spnego_parse_challenge(DATA_BLOB blob,
/*
- generate a spnego NTLMSSP challenge packet given two security blobs
- The second challenge is optional
-*/
-BOOL spnego_gen_challenge(DATA_BLOB *blob,
- DATA_BLOB *chal1, DATA_BLOB *chal2)
-{
- ASN1_DATA data;
-
- ZERO_STRUCT(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,1);
- asn1_pop_tag(&data);
-
- asn1_push_tag(&data,ASN1_CONTEXT(1));
- asn1_write_OID(&data, OID_NTLMSSP);
- asn1_pop_tag(&data);
-
- asn1_push_tag(&data,ASN1_CONTEXT(2));
- asn1_write_OctetString(&data, chal1->data, chal1->length);
- asn1_pop_tag(&data);
-
- /* the second challenge is optional (XP doesn't send it) */
- if (chal2) {
- asn1_push_tag(&data,ASN1_CONTEXT(3));
- asn1_write_OctetString(&data, chal2->data, chal2->length);
- asn1_pop_tag(&data);
- }
-
- asn1_pop_tag(&data);
- asn1_pop_tag(&data);
-
- if (data.has_error) {
- return False;
- }
-
- *blob = data_blob(data.data, data.length);
- asn1_free(&data);
- return True;
-}
-
-/*
generate a SPNEGO NTLMSSP auth packet. This will contain the encrypted passwords
*/
DATA_BLOB spnego_gen_auth(DATA_BLOB blob)
@@ -485,23 +440,37 @@ BOOL spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth)
/*
generate a minimal SPNEGO NTLMSSP response packet. Doesn't contain much.
*/
-DATA_BLOB spnego_gen_auth_response(DATA_BLOB *ntlmssp_reply)
+DATA_BLOB spnego_gen_auth_response(DATA_BLOB *ntlmssp_reply, NTSTATUS nt_status)
{
ASN1_DATA data;
DATA_BLOB ret;
+ uint8 negResult;
- memset(&data, 0, sizeof(data));
+ if (NT_STATUS_IS_OK(nt_status)) {
+ negResult = SPNGEO_NEG_RESULT_ACCEPT;
+ } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ negResult = SPNGEO_NEG_RESULT_INCOMPLETE;
+ } else {
+ negResult = SPNGEO_NEG_RESULT_REJECT;
+ }
+
+ ZERO_STRUCT(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, ntlmssp_reply->length ? 1 : 0);
+ asn1_write_enumerated(&data, negResult);
asn1_pop_tag(&data);
- if (ntlmssp_reply->length) {
+ if (negResult == SPNGEO_NEG_RESULT_INCOMPLETE) {
+ asn1_push_tag(&data,ASN1_CONTEXT(1));
+ asn1_write_OID(&data, OID_NTLMSSP);
+ asn1_pop_tag(&data);
+
asn1_push_tag(&data,ASN1_CONTEXT(2));
asn1_write_OctetString(&data, ntlmssp_reply->data, ntlmssp_reply->length);
asn1_pop_tag(&data);
}
+
asn1_pop_tag(&data);
asn1_pop_tag(&data);
diff --git a/source/libsmb/ntlmssp.c b/source/libsmb/ntlmssp.c
index 6837674736a..5b608e0a7a9 100644
--- a/source/libsmb/ntlmssp.c
+++ b/source/libsmb/ntlmssp.c
@@ -275,10 +275,6 @@ NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state,
nt_status = ntlmssp_state->check_password(ntlmssp_state);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- }
-
*reply = data_blob(NULL, 0);
return nt_status;
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index e68695ee52a..23a44d8df7c 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -213,7 +213,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, NTSTATUS errcode)
+ DATA_BLOB blob, NTSTATUS nt_status)
{
char *p;
@@ -222,60 +222,65 @@ 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(errcode));
+ nt_status = nt_status_squash(nt_status);
+ SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
SSVAL(outbuf, smb_vwv3, blob.length);
p = smb_buf(outbuf);
memcpy(p, blob.data, blob.length);
- p += blob.length;
- p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
- p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
- p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
- set_message_end(outbuf,p);
+
+ add_signature(outbuf);
return send_smb(smbd_server_fd(),outbuf);
}
/****************************************************************************
-send an NTLMSSP blob via a session setup reply, wrapped in SPNEGO
-****************************************************************************/
-static BOOL reply_spnego_ntlmssp_blob(connection_struct *conn, char *outbuf,
- DATA_BLOB *ntlmssp_blob, NTSTATUS errcode)
-{
- DATA_BLOB response;
- response = spnego_gen_auth_response(ntlmssp_blob);
- reply_sesssetup_blob(conn, outbuf, response, errcode);
- data_blob_free(&response);
- return True;
-}
-
-/****************************************************************************
- send an OK via a session setup reply, wrapped in SPNEGO.
+ send a session setup reply, wrapped in SPNEGO.
get vuid and check first.
-****************************************************************************/
-static BOOL reply_spnego_ntlmssp_ok(connection_struct *conn, char *outbuf,
- AUTH_NTLMSSP_STATE *auth_ntlmssp_state)
+ end the NTLMSSP exchange context if we are OK/complete fail
+***************************************************************************/
+static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf,
+ AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
+ DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
{
- int sess_vuid;
- DATA_BLOB null_blob = data_blob(NULL, 0);
+ DATA_BLOB response;
+ struct auth_serversupplied_info *server_info;
+ server_info = (*auth_ntlmssp_state)->server_info;
- sess_vuid = register_vuid(auth_ntlmssp_state->server_info, auth_ntlmssp_state->ntlmssp_state->user /* check this for weird */);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ nt_status = do_map_to_guest(nt_status,
+ &server_info,
+ (*auth_ntlmssp_state)->ntlmssp_state->user,
+ (*auth_ntlmssp_state)->ntlmssp_state->domain);
+ }
- if (sess_vuid == -1) {
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ if (NT_STATUS_IS_OK(nt_status)) {
+ int sess_vuid;
+ sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user /* check this for weird */);
+
+ if (sess_vuid == -1) {
+ nt_status = NT_STATUS_LOGON_FAILURE;
+ } else {
+
+ set_message(outbuf,4,0,True);
+ SSVAL(outbuf, smb_vwv3, 0);
+
+ if ((*auth_ntlmssp_state)->server_info->guest) {
+ SSVAL(outbuf,smb_vwv2,1);
+ }
+
+ SSVAL(outbuf,smb_uid,sess_vuid);
+ }
}
- set_message(outbuf,4,0,True);
- SSVAL(outbuf, smb_vwv3, 0);
+ response = spnego_gen_auth_response(ntlmssp_blob, nt_status);
+ reply_sesssetup_blob(conn, outbuf, response, nt_status);
+ data_blob_free(&response);
- if (auth_ntlmssp_state->server_info->guest) {
- SSVAL(outbuf,smb_vwv2,1);
+ if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ auth_ntlmssp_end(&global_ntlmssp_state);
}
- add_signature(outbuf);
-
- SSVAL(outbuf,smb_uid,sess_vuid);
- reply_spnego_ntlmssp_blob(conn, outbuf, &null_blob, NT_STATUS_OK);
return True;
}
@@ -291,7 +296,7 @@ static int reply_spnego_negotiate(connection_struct *conn,
char *OIDs[ASN1_MAX_OIDS];
DATA_BLOB secblob;
int i;
- DATA_BLOB chal, spnego_chal;
+ DATA_BLOB chal;
BOOL got_kerberos = False;
NTSTATUS nt_status;
@@ -333,41 +338,13 @@ static int reply_spnego_negotiate(connection_struct *conn,
data_blob_free(&secblob);
- if (!NT_STATUS_IS_OK(nt_status)) {
- nt_status = do_map_to_guest(nt_status,
- &global_ntlmssp_state->server_info,
- global_ntlmssp_state->ntlmssp_state->user,
- global_ntlmssp_state->ntlmssp_state->domain);
- }
-
- if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- if (!spnego_gen_challenge(&spnego_chal, &chal, NULL)) {
- DEBUG(3,("Failed to generate challenge\n"));
- data_blob_free(&chal);
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
-
- /* now tell the client to send the auth packet */
- reply_sesssetup_blob(conn, outbuf, spnego_chal, nt_status);
+ reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
+ &chal, nt_status);
- data_blob_free(&chal);
- data_blob_free(&spnego_chal);
+ data_blob_free(&chal);
- /* and tell smbd that we have already replied to this packet */
- return -1;
-
- } else if (NT_STATUS_IS_OK(nt_status)) {
- reply_spnego_ntlmssp_ok(conn, outbuf,
- global_ntlmssp_state);
- auth_ntlmssp_end(&global_ntlmssp_state);
-
- /* and tell smbd that we have already replied to this packet */
- return -1;
- }
-
- auth_ntlmssp_end(&global_ntlmssp_state);
-
- return ERROR_NT(nt_status_squash(nt_status));
+ /* already replied */
+ return -1;
}
@@ -389,20 +366,14 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
}
nt_status = auth_ntlmssp_update(global_ntlmssp_state,
- auth, &auth_reply);
+ auth, &auth_reply);
data_blob_free(&auth);
- if (NT_STATUS_IS_OK(nt_status)) {
- reply_spnego_ntlmssp_ok(conn, outbuf,
- global_ntlmssp_state);
- auth_ntlmssp_end(&global_ntlmssp_state);
- data_blob_free(&auth_reply);
-
- } else { /* !NT_STATUS_IS_OK(nt_status) */
- auth_ntlmssp_end(&global_ntlmssp_state);
- return ERROR_NT(nt_status_squash(nt_status));
- }
+ reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
+ &auth_reply, nt_status);
+
+ data_blob_free(&auth_reply);
/* and tell smbd that we have already replied to this packet */
return -1;
@@ -410,41 +381,6 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
/****************************************************************************
-reply to a session setup spnego anonymous packet
-****************************************************************************/
-static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
- int length, int bufsize)
-{
- int sess_vuid;
- auth_serversupplied_info *server_info = NULL;
- NTSTATUS nt_status;
-
- nt_status = check_guest_password(&server_info);
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- return ERROR_NT(nt_status_squash(nt_status));
- }
-
- sess_vuid = register_vuid(server_info, lp_guestaccount());
-
- free_server_info(&server_info);
-
- if (sess_vuid == -1) {
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
-
- set_message(outbuf,4,0,True);
- SSVAL(outbuf, smb_vwv3, 0);
- add_signature(outbuf);
-
- SSVAL(outbuf,smb_uid,sess_vuid);
- SSVAL(inbuf,smb_uid,sess_vuid);
-
- return chain_reply(inbuf,outbuf,length,bufsize);
-}
-
-
-/****************************************************************************
reply to a session setup command
****************************************************************************/
static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
@@ -454,6 +390,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
uint8 *p;
DATA_BLOB blob1;
int ret;
+ size_t bufrem;
DEBUG(3,("Doing spnego session setup\n"));
@@ -464,12 +401,13 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
p = (uint8 *)smb_buf(inbuf);
if (SVAL(inbuf, smb_vwv7) == 0) {
- /* an anonymous request */
- return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
+ /* an invalid request */
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
+ bufrem = smb_bufrem(inbuf, p);
/* pull the spnego blob */
- blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
+ blob1 = data_blob(p, MIN(bufrem, SVAL(inbuf, smb_vwv7)));
#if 0
file_save("negotiate.dat", blob1.data, blob1.length);