[SCM] Samba Shared Repository - branch v3-2-test updated -
initial-v3-2-test-2254-g8767a0d
Jeremy Allison
jra at samba.org
Fri Feb 15 02:11:30 GMT 2008
The branch, v3-2-test has been updated
via 8767a0dab95c544878b4187157e494e740974bb8 (commit)
via 67768fc71f9bd7ff3d61acc50360356b524ae923 (commit)
via 8cd04b948bfba3896d40c9e314a197f60ad76833 (commit)
via b41799c351c72b268ef094047a51766747671280 (commit)
via b7628f3a47166791db4cd6451d52ea3881a45bed (commit)
from e3e08c6e7d270e1be7a9d3042b1f36f5a291f90a (commit)
http://gitweb.samba.org/?samba.git;a=shortlog;h=v3-2-test
- Log -----------------------------------------------------------------
commit 8767a0dab95c544878b4187157e494e740974bb8
Author: Jeremy Allison <jra at samba.org>
Date: Thu Feb 14 18:10:50 2008 -0800
Correctly use SPNEGO to negotiate down from krb5 to NTLMSSP.
Previously we didn't implement the 'NEGO' part of SPNEGO :-).
Jeremy.
commit 67768fc71f9bd7ff3d61acc50360356b524ae923
Author: Jeremy Allison <jra at samba.org>
Date: Thu Feb 14 18:08:23 2008 -0800
Currently we don't SPNEGO negotiate back to NTLMSSP. Note this.
Jeremy.
commit 8cd04b948bfba3896d40c9e314a197f60ad76833
Author: Jeremy Allison <jra at samba.org>
Date: Thu Feb 14 18:07:27 2008 -0800
Currently we don't SPNEGO negotiate back to NTLMSSP. Note this.
Jeremy.
commit b41799c351c72b268ef094047a51766747671280
Author: Jeremy Allison <jra at samba.org>
Date: Thu Feb 14 18:06:16 2008 -0800
Ensure invalidate_vuid() deletes any ntlmssp state.
Jeremy.
commit b7628f3a47166791db4cd6451d52ea3881a45bed
Author: Jeremy Allison <jra at samba.org>
Date: Thu Feb 14 18:05:37 2008 -0800
Allow auth_ntlmssp_end() to ignore null pointers passed in.
Jeremy.
-----------------------------------------------------------------------
Summary of changes:
source/auth/auth_ntlmssp.c | 7 ++-
source/rpc_server/srv_pipe.c | 55 +++++++++++++--------
source/smbd/password.c | 4 ++
source/smbd/seal.c | 20 ++++++--
source/smbd/sesssetup.c | 109 +++++++++++++++++++++++++++++++-----------
5 files changed, 142 insertions(+), 53 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source/auth/auth_ntlmssp.c b/source/auth/auth_ntlmssp.c
index 526f2c9..ed66d0d 100644
--- a/source/auth/auth_ntlmssp.c
+++ b/source/auth/auth_ntlmssp.c
@@ -186,8 +186,13 @@ NTSTATUS auth_ntlmssp_start(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
void auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
{
- TALLOC_CTX *mem_ctx = (*auth_ntlmssp_state)->mem_ctx;
+ TALLOC_CTX *mem_ctx;
+
+ if (*auth_ntlmssp_state == NULL) {
+ return;
+ }
+ mem_ctx = (*auth_ntlmssp_state)->mem_ctx;
if ((*auth_ntlmssp_state)->ntlmssp_state) {
ntlmssp_end(&(*auth_ntlmssp_state)->ntlmssp_state);
}
diff --git a/source/rpc_server/srv_pipe.c b/source/rpc_server/srv_pipe.c
index 06694a2..a671f89 100644
--- a/source/rpc_server/srv_pipe.c
+++ b/source/rpc_server/srv_pipe.c
@@ -1105,7 +1105,7 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_
char *OIDs[ASN1_MAX_OIDS];
int i;
NTSTATUS status;
- bool got_kerberos_mechanism = False;
+ bool got_kerberos_mechanism = false;
AUTH_NTLMSSP_STATE *a = NULL;
RPC_HDR_AUTH auth_info;
@@ -1133,7 +1133,7 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_
}
if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
- got_kerberos_mechanism = True;
+ got_kerberos_mechanism = true;
}
for (i=0;OIDs[i];i++) {
@@ -1154,27 +1154,38 @@ static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_
free_pipe_ntlmssp_auth_data(&p->auth);
}
- /* Initialize the NTLM engine. */
- status = auth_ntlmssp_start(&a);
- if (!NT_STATUS_IS_OK(status)) {
- goto err;
- }
+ if (!got_kerberos_mechanism) {
+ /* Initialize the NTLM engine. */
+ status = auth_ntlmssp_start(&a);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err;
+ }
- /*
- * Pass the first security blob of data to it.
- * This can return an error or NT_STATUS_MORE_PROCESSING_REQUIRED
- * which means we need another packet to complete the bind.
- */
+ /*
+ * Pass the first security blob of data to it.
+ * This can return an error or NT_STATUS_MORE_PROCESSING_REQUIRED
+ * which means we need another packet to complete the bind.
+ */
- status = auth_ntlmssp_update(a, secblob, &chal);
+ status = auth_ntlmssp_update(a, secblob, &chal);
- if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DEBUG(3,("pipe_spnego_auth_bind_negotiate: auth_ntlmssp_update failed.\n"));
- goto err;
- }
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ DEBUG(3,("pipe_spnego_auth_bind_negotiate: auth_ntlmssp_update failed.\n"));
+ goto err;
+ }
- /* Generate the response blob we need for step 2 of the bind. */
- response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
+ /* Generate the response blob we need for step 2 of the bind. */
+ response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
+ } else {
+ /*
+ * SPNEGO negotiate down to NTLMSSP. The subsequent
+ * code to process follow-up packets is not complete
+ * yet. JRA.
+ */
+ response = spnego_gen_auth_response(NULL,
+ NT_STATUS_MORE_PROCESSING_REQUIRED,
+ OID_NTLMSSP);
+ }
/* Copy the blob into the pout_auth parse struct */
init_rpc_hdr_auth(&auth_info, RPC_SPNEGO_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1);
@@ -1231,6 +1242,10 @@ static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p
ZERO_STRUCT(auth_reply);
ZERO_STRUCT(response);
+ /*
+ * NB. If we've negotiated down from krb5 to NTLMSSP we'll currently
+ * fail here as 'a' == NULL.
+ */
if (p->auth.auth_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP || !a) {
DEBUG(0,("pipe_spnego_auth_bind_continue: not in NTLMSSP auth state.\n"));
goto err;
@@ -1259,7 +1274,7 @@ static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p
* The following call actually checks the challenge/response data.
* for correctness against the given DOMAIN\user name.
*/
-
+
if (!pipe_ntlmssp_verify_final(p, &auth_blob)) {
goto err;
}
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 687b679..80eba56 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -121,6 +121,10 @@ void invalidate_vuid(uint16 vuid)
data_blob_free(&vuser->session_key);
+ if (vuser->auth_ntlmssp_state) {
+ auth_ntlmssp_end(&vuser->auth_ntlmssp_state);
+ }
+
DLIST_REMOVE(validated_users, vuser);
/* clear the vuid from the 'cache' on each connection, and
diff --git a/source/smbd/seal.c b/source/smbd/seal.c
index ea017e0..d4394e5 100644
--- a/source/smbd/seal.c
+++ b/source/smbd/seal.c
@@ -496,12 +496,15 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn,
srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ if (got_kerberos_mechanism) {
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
- if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) {
status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob);
- } else
+#else
+ /* Currently we don't SPNEGO negotiate
+ * back to NTLMSSP as we do in sessionsetupX. We should... */
+ return NT_STATUS_LOGON_FAILURE;
#endif
- {
+ } else {
status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, true);
}
@@ -558,7 +561,16 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn,
status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply);
data_blob_free(&auth);
- response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP);
+ /* From RFC4178.
+ *
+ * supportedMech
+ *
+ * This field SHALL only be present in the first reply from the
+ * target.
+ * So set mechOID to NULL here.
+ */
+
+ response = spnego_gen_auth_response(&auth_reply, status, NULL);
data_blob_free(&auth_reply);
if (NT_STATUS_IS_OK(status)) {
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index 1e4e208..3e04da3 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -620,6 +620,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
uint16 vuid,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
+ const char *OID,
bool wrap)
{
DATA_BLOB response;
@@ -680,7 +681,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
if (wrap) {
response = spnego_gen_auth_response(ntlmssp_blob,
- nt_status, OID_NTLMSSP);
+ nt_status, OID);
} else {
response = *ntlmssp_blob;
}
@@ -745,6 +746,28 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
}
/****************************************************************************
+ Fall back from krb5 to NTLMSSP.
+****************************************************************************/
+
+static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
+ uint16 vuid)
+{
+ DATA_BLOB response;
+
+ reply_outbuf(req, 4, 0);
+ SSVAL(req->outbuf,smb_uid,vuid);
+
+ DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
+ "but set to downgrade to NTLMSSP\n"));
+
+ response = spnego_gen_auth_response(NULL,
+ NT_STATUS_MORE_PROCESSING_REQUIRED,
+ OID_NTLMSSP);
+ reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
+ data_blob_free(&response);
+}
+
+/****************************************************************************
Reply to a session setup spnego negotiate packet.
****************************************************************************/
@@ -789,6 +812,15 @@ static void reply_spnego_negotiate(struct smb_request *req,
auth_ntlmssp_end(auth_ntlmssp_state);
}
+ if (got_kerberos_mechanism) {
+ data_blob_free(&secblob);
+ /* The mechtoken is a krb5 ticket, but
+ * we need to fall back to NTLM. */
+ reply_spnego_downgrade_to_ntlmssp(req,
+ vuid);
+ return;
+ }
+
status = auth_ntlmssp_start(auth_ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
@@ -803,7 +835,7 @@ static void reply_spnego_negotiate(struct smb_request *req,
data_blob_free(&secblob);
reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
- &chal, status, True);
+ &chal, status, OID_NTLMSSP, true);
data_blob_free(&chal);
@@ -823,7 +855,7 @@ static void reply_spnego_auth(struct smb_request *req,
DATA_BLOB auth = data_blob_null;
DATA_BLOB auth_reply = data_blob_null;
DATA_BLOB secblob = data_blob_null;
- NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
+ NTSTATUS status = NT_STATUS_LOGON_FAILURE;
if (!spnego_parse_auth(blob1, &auth)) {
#if 0
@@ -833,7 +865,7 @@ static void reply_spnego_auth(struct smb_request *req,
invalidate_vuid(vuid);
reply_nterror(req, nt_status_squash(
- NT_STATUS_INVALID_PARAMETER));
+ NT_STATUS_LOGON_FAILURE));
return;
}
@@ -843,24 +875,43 @@ static void reply_spnego_auth(struct smb_request *req,
bool got_krb5_mechanism = False;
status = parse_spnego_mechanisms(auth, &secblob,
&got_krb5_mechanism);
- if (NT_STATUS_IS_OK(status)) {
- DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
- (unsigned long)secblob.length));
+
+ if (!NT_STATUS_IS_OK(status)) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
+ reply_nterror(req, nt_status_squash(status));
+ return;
+ }
+
+ DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
+ (unsigned long)secblob.length));
#ifdef HAVE_KRB5
- if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
- lp_use_kerberos_keytab()) ) {
- bool destroy_vuid = True;
- reply_spnego_kerberos(req, &secblob,
- vuid, &destroy_vuid);
- data_blob_free(&secblob);
- data_blob_free(&auth);
- if (destroy_vuid) {
- /* Kill the intermediate vuid */
- invalidate_vuid(vuid);
- }
- return;
+ if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
+ lp_use_kerberos_keytab()) ) {
+ bool destroy_vuid = True;
+ reply_spnego_kerberos(req, &secblob,
+ vuid, &destroy_vuid);
+ data_blob_free(&secblob);
+ data_blob_free(&auth);
+ if (destroy_vuid) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
}
+ return;
+ }
#endif
+ /* Can't blunder into NTLMSSP auth if we have
+ * a krb5 ticket. */
+
+ if (got_krb5_mechanism) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
+ DEBUG(3,("reply_spnego_auth: network "
+ "misconfiguration, client sent us a "
+ "krb5 ticket and kerberos security "
+ "not enabled"));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_LOGON_FAILURE));
}
}
@@ -868,13 +919,13 @@ static void reply_spnego_auth(struct smb_request *req,
data_blob_free(&secblob);
if (!*auth_ntlmssp_state) {
- /* Kill the intermediate vuid */
- invalidate_vuid(vuid);
-
- /* auth before negotiatiate? */
- reply_nterror(req, nt_status_squash(
- NT_STATUS_INVALID_PARAMETER));
- return;
+ status = auth_ntlmssp_start(auth_ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
+ reply_nterror(req, nt_status_squash(status));
+ return;
+ }
}
status = auth_ntlmssp_update(*auth_ntlmssp_state,
@@ -882,9 +933,11 @@ static void reply_spnego_auth(struct smb_request *req,
data_blob_free(&auth);
+ /* Don't send the mechid as we've already sent this (RFC4178). */
+
reply_spnego_ntlmssp(req, vuid,
auth_ntlmssp_state,
- &auth_reply, status, True);
+ &auth_reply, status, NULL, true);
data_blob_free(&auth_reply);
@@ -1251,7 +1304,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
reply_spnego_ntlmssp(req, vuid,
&vuser->auth_ntlmssp_state,
- &chal, status, False);
+ &chal, status, OID_NTLMSSP, false);
data_blob_free(&chal);
return;
}
--
Samba Shared Repository
More information about the samba-cvs
mailing list