summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-03-20 18:11:48 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:18:46 -0500
commit492ad718552b77d6de7233b126e834cf11f9316c (patch)
treea7d709677ab4e303f7db08cf8d261ff837122c39 /source3
parent2af42eaaa35e356ed605f750489b327b1e1b9193 (diff)
downloadsamba-492ad718552b77d6de7233b126e834cf11f9316c.tar.gz
samba-492ad718552b77d6de7233b126e834cf11f9316c.tar.bz2
samba-492ad718552b77d6de7233b126e834cf11f9316c.zip
r21891: Finish server-side NTLM-SPNEGO negotiation support.
Now for the client part, and testing. Jeremy. (This used to be commit 487706701f5f4a92c8fd1da1f29fb44491bac064)
Diffstat (limited to 'source3')
-rw-r--r--source3/smbd/seal.c108
1 files changed, 75 insertions, 33 deletions
diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c
index 2dd4fc8b62..0a530526a2 100644
--- a/source3/smbd/seal.c
+++ b/source3/smbd/seal.c
@@ -118,15 +118,46 @@ NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out)
******************************************************************************/
#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
-static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, DATA_BLOB *psecblob)
+static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, DATA_BLOB secblob)
{
return NT_STATUS_NOT_SUPPORTED;
}
#endif
/******************************************************************************
+ Do the NTLM SPNEGO encryption negotiation. Parameters are in/out.
+ Until success we do everything on the partial enc ctx.
+******************************************************************************/
+
+static NTSTATUS srv_enc_spnego_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob)
+{
+ NTSTATUS status;
+ DATA_BLOB chal = data_blob(NULL, 0);
+ DATA_BLOB response = data_blob(NULL, 0);
+ struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx;
+
+ status = auth_ntlmssp_start(&ec->auth_ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
+ return nt_status_squash(status);
+ }
+
+ status = auth_ntlmssp_update(ec->auth_ntlmssp_state, secblob, &chal);
+
+ /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED
+ * for success ... */
+
+ response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
+ data_blob_free(&chal);
+
+ SAFE_FREE(*ppdata);
+ *ppdata = response.data;
+ *p_data_size = response.length;
+ return status;
+}
+
+/******************************************************************************
Do the SPNEGO encryption negotiation. Parameters are in/out.
- Covers the NTLM case. Based off code in smbd/sesssionsetup.c
+ Based off code in smbd/sesssionsetup.c
Until success we do everything on the partial enc ctx.
******************************************************************************/
@@ -135,10 +166,7 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_
NTSTATUS status;
DATA_BLOB blob = data_blob(NULL,0);
DATA_BLOB secblob = data_blob(NULL, 0);
- DATA_BLOB chal = data_blob(NULL, 0);
- DATA_BLOB response = data_blob(NULL, 0);
BOOL got_kerberos_mechanism = False;
- struct smb_srv_trans_enc_ctx *ec = NULL;
blob = data_blob_const(*ppdata, *p_data_size);
@@ -160,47 +188,59 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_
#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
if (got_kerberos_mechanism && lp_use_kerberos_keytab()) ) {
- status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, &secblob);
- if (!NT_STATUS_IS_OK(status)) {
- data_blob_free(&secblob);
- srv_free_encryption_context(&partial_srv_trans_enc_ctx);
- }
- return status;
- }
+ status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob);
+ } else
#endif
-
- /* Deal with an NTLM enc. setup. */
- ec = partial_srv_trans_enc_ctx;
-
- status = auth_ntlmssp_start(&ec->auth_ntlmssp_state);
- if (!NT_STATUS_IS_OK(status)) {
- srv_free_encryption_context(&partial_srv_trans_enc_ctx);
- return nt_status_squash(status);
+ {
+ status = srv_enc_spnego_ntlm_negotiate(ppdata, p_data_size, secblob);
}
- status = auth_ntlmssp_update(ec->auth_ntlmssp_state, secblob, &chal);
data_blob_free(&secblob);
- /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED
- * for success ... */
-
- response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
- data_blob_free(&chal);
-
- SAFE_FREE(*ppdata);
- *ppdata = response.data;
- *p_data_size = response.length;
+ if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ }
return status;
}
/******************************************************************************
Complete a SPNEGO encryption negotiation. Parameters are in/out.
+ We only get this for a NTLM auth second stage.
******************************************************************************/
-static NTSTATUS srv_enc_spnego_auth(unsigned char **ppdata, size_t *p_data_size)
+static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_size)
{
- return NT_STATUS_NOT_SUPPORTED;
+ NTSTATUS status;
+ DATA_BLOB blob = data_blob(NULL,0);
+ DATA_BLOB auth = data_blob(NULL,0);
+ DATA_BLOB auth_reply = data_blob(NULL,0);
+ DATA_BLOB response = data_blob(NULL,0);
+ struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx;
+
+ /* We must have a partial context here. */
+
+ if (!ec || ec->auth_ntlmssp_state == NULL) {
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ blob = data_blob_const(*ppdata, *p_data_size);
+ if (!spnego_parse_auth(blob, &auth)) {
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ 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);
+ data_blob_free(&auth_reply);
+
+ SAFE_FREE(*ppdata);
+ *ppdata = response.data;
+ *p_data_size = response.length;
+ return status;
}
/******************************************************************************
@@ -226,7 +266,7 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz
if (pdata[0] == ASN1_CONTEXT(1)) {
/* Its a auth packet */
- return srv_enc_spnego_auth(ppdata, p_data_size);
+ return srv_enc_spnego_ntlm_auth(ppdata, p_data_size);
}
return NT_STATUS_INVALID_PARAMETER;
@@ -238,7 +278,9 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz
void srv_encryption_start(void)
{
+ /* Throw away the context we're using currently (if any). */
srv_free_encryption_context(&srv_trans_enc_ctx);
+
/* Steal the partial pointer. Deliberate shallow copy. */
srv_trans_enc_ctx = partial_srv_trans_enc_ctx;
srv_trans_enc_ctx->es->enc_on = True;