summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/libsmb/cliconnect.c3
-rw-r--r--source3/libsmb/smb_seal.c12
-rw-r--r--source3/smbd/seal.c163
3 files changed, 149 insertions, 29 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 0f09747dbf..3970731b45 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -763,7 +763,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
}
}
- /* we have a reference conter on ntlmssp_state, if we are signing
+ /* we have a reference counter on ntlmssp_state, if we are signing
then the state will be kept by the signing engine */
ntlmssp_end(&ntlmssp_state);
@@ -973,7 +973,6 @@ NTSTATUS cli_session_setup(struct cli_state *cli,
}
return NT_STATUS_OK;
-
}
/****************************************************************************
diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c
index e7b3e8f024..06662e53fb 100644
--- a/source3/libsmb/smb_seal.c
+++ b/source3/libsmb/smb_seal.c
@@ -282,3 +282,15 @@ NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out)
{
return common_encrypt_buffer(cli->trans_enc_state, cli->outbuf, buf_out);
}
+
+/******************************************************************************
+ Start a raw ntlmssp encryption.
+******************************************************************************/
+
+NTSTATUS cli_ntlm_smb_encryption_on(struct cli_state *cli,
+ const char *user,
+ const char *pass,
+ const char *workgroup)
+{
+
+}
diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c
index 0a530526a2..9910a84f4c 100644
--- a/source3/smbd/seal.c
+++ b/source3/smbd/seal.c
@@ -49,7 +49,44 @@ BOOL srv_encryption_on(void)
}
/******************************************************************************
- Shutdown a server encryption state.
+ Create an auth_ntlmssp_state and ensure pointer copy is correct.
+******************************************************************************/
+
+static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec)
+{
+ NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
+ return nt_status_squash(status);
+ }
+
+ /*
+ * We must remember to update the pointer copy for the common
+ * functions after any auth_ntlmssp_start/auth_ntlmssp_end.
+ */
+ ec->es->ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state;
+ return status;
+}
+
+/******************************************************************************
+ Destroy an auth_ntlmssp_state and ensure pointer copy is correct.
+******************************************************************************/
+
+static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec)
+{
+ /*
+ * We must remember to update the pointer copy for the common
+ * functions after any auth_ntlmssp_start/auth_ntlmssp_end.
+ */
+
+ if (ec->auth_ntlmssp_state) {
+ auth_ntlmssp_end(&ec->auth_ntlmssp_state);
+ /* The auth_ntlmssp_end killed this already. */
+ ec->es->ntlmssp_state = NULL;
+ }
+}
+
+/******************************************************************************
+ Shutdown a server encryption context.
******************************************************************************/
static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec)
@@ -61,12 +98,8 @@ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec)
}
if (ec->es) {
- struct smb_trans_enc_state *es = ec->es;
- if (es->smb_enc_type == SMB_TRANS_ENC_NTLM &&
- ec->auth_ntlmssp_state) {
- auth_ntlmssp_end(&ec->auth_ntlmssp_state);
- /* The auth_ntlmssp_end killed this already. */
- es->ntlmssp_state = NULL;
+ if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
+ destroy_auth_ntlmssp(ec);
}
common_free_encryption_state(&ec->es);
}
@@ -76,6 +109,36 @@ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec)
}
/******************************************************************************
+ Create a server encryption context.
+******************************************************************************/
+
+static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type)
+{
+ struct smb_srv_trans_enc_ctx *ec;
+
+ ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx);
+ if (!ec) {
+ return NULL;
+ }
+ ZERO_STRUCTP(partial_srv_trans_enc_ctx);
+ ec->es = SMB_MALLOC_P(struct smb_trans_enc_state);
+ if (!ec->es) {
+ SAFE_FREE(ec);
+ return NULL;
+ }
+ ZERO_STRUCTP(ec->es);
+ ec->es->smb_enc_type = smb_enc_type;
+ if (smb_enc_type == SMB_TRANS_ENC_NTLM) {
+ NTSTATUS status = make_auth_ntlmssp(ec);
+ if (!NT_STATUS_IS_OK(status)) {
+ srv_free_encryption_context(&ec);
+ return NULL;
+ }
+ }
+ return ec;
+}
+
+/******************************************************************************
Free an encryption-allocated buffer.
******************************************************************************/
@@ -125,29 +188,33 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size,
#endif
/******************************************************************************
- Do the NTLM SPNEGO encryption negotiation. Parameters are in/out.
+ Do the NTLM SPNEGO (or raw) 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)
+static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, BOOL spnego_wrap)
{
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);
+ partial_srv_trans_enc_ctx = make_srv_encryption_context(SMB_TRANS_ENC_NTLM);
+ if (!partial_srv_trans_enc_ctx) {
+ return NT_STATUS_NO_MEMORY;
}
- status = auth_ntlmssp_update(ec->auth_ntlmssp_state, secblob, &chal);
+ status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->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);
+ if (spnego_wrap) {
+ response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
+ data_blob_free(&chal);
+ } else {
+ /* Return the raw blob. */
+ response = chal;
+ }
SAFE_FREE(*ppdata);
*ppdata = response.data;
@@ -179,20 +246,13 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_
srv_free_encryption_context(&partial_srv_trans_enc_ctx);
- partial_srv_trans_enc_ctx = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx);
- if (!partial_srv_trans_enc_ctx) {
- data_blob_free(&secblob);
- return NT_STATUS_NO_MEMORY;
- }
- ZERO_STRUCTP(partial_srv_trans_enc_ctx);
-
#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);
} else
#endif
{
- status = srv_enc_spnego_ntlm_negotiate(ppdata, p_data_size, secblob);
+ status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, True);
}
data_blob_free(&secblob);
@@ -220,7 +280,7 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_
/* We must have a partial context here. */
- if (!ec || ec->auth_ntlmssp_state == NULL) {
+ if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) {
srv_free_encryption_context(&partial_srv_trans_enc_ctx);
return NT_STATUS_INVALID_PARAMETER;
}
@@ -244,6 +304,44 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_
}
/******************************************************************************
+ Raw NTLM encryption negotiation. Parameters are in/out.
+ This function does both steps.
+******************************************************************************/
+
+static NTSTATUS srv_enc_raw_ntlm_auth(unsigned char **ppdata, size_t *p_data_size)
+{
+ NTSTATUS status;
+ DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size);
+ DATA_BLOB response = data_blob(NULL,0);
+ struct smb_srv_trans_enc_ctx *ec;
+
+ if (!partial_srv_trans_enc_ctx) {
+ /* This is the initial step. */
+ status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, False);
+ if (!NT_STATUS_IS_OK(status)) {
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ return nt_status_squash(status);
+ }
+ return status;
+ }
+
+ ec = partial_srv_trans_enc_ctx;
+ if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) {
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Second step. */
+ status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response);
+
+ /* Return the raw blob. */
+ SAFE_FREE(*ppdata);
+ *ppdata = response.data;
+ *p_data_size = response.length;
+ return status;
+}
+
+/******************************************************************************
Do the SPNEGO encryption negotiation. Parameters are in/out.
******************************************************************************/
@@ -265,11 +363,22 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz
}
if (pdata[0] == ASN1_CONTEXT(1)) {
- /* Its a auth packet */
+ /* It's an auth packet */
return srv_enc_spnego_ntlm_auth(ppdata, p_data_size);
}
- return NT_STATUS_INVALID_PARAMETER;
+ /* Maybe it's a raw unwrapped auth ? */
+ if (*p_data_size < 7) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) {
+ return srv_enc_raw_ntlm_auth(ppdata, p_data_size);
+ }
+
+ DEBUG(1,("srv_request_encryption_setup: Unknown packet\n"));
+
+ return NT_STATUS_LOGON_FAILURE;
}
/******************************************************************************