diff options
-rw-r--r-- | source/include/asn_1.h | 4 | ||||
-rw-r--r-- | source/libsmb/clispnego.c | 67 | ||||
-rw-r--r-- | source/libsmb/ntlmssp.c | 4 | ||||
-rw-r--r-- | source/smbd/sesssetup.c | 178 |
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); |