Author: jra
Date: 2007-03-20 22:01:02 +0000 (Tue, 20 Mar 2007)
New Revision: 21894

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=21894

Log:
Some refactoring of server side encryption context. Support
"raw" NTLM auth (no spnego).
Jeremy.

Modified:
   branches/SAMBA_3_0/source/libsmb/cliconnect.c
   branches/SAMBA_3_0/source/libsmb/smb_seal.c
   branches/SAMBA_3_0/source/smbd/seal.c


Changeset:
Modified: branches/SAMBA_3_0/source/libsmb/cliconnect.c
===================================================================
--- branches/SAMBA_3_0/source/libsmb/cliconnect.c       2007-03-20 21:21:04 UTC 
(rev 21893)
+++ branches/SAMBA_3_0/source/libsmb/cliconnect.c       2007-03-20 22:01:02 UTC 
(rev 21894)
@@ -763,7 +763,7 @@
                }
        }
 
-       /* 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 @@
        }
 
        return NT_STATUS_OK;
-
 }
 
 /****************************************************************************

Modified: branches/SAMBA_3_0/source/libsmb/smb_seal.c
===================================================================
--- branches/SAMBA_3_0/source/libsmb/smb_seal.c 2007-03-20 21:21:04 UTC (rev 
21893)
+++ branches/SAMBA_3_0/source/libsmb/smb_seal.c 2007-03-20 22:01:02 UTC (rev 
21894)
@@ -282,3 +282,15 @@
 {
        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)
+{
+
+}

Modified: branches/SAMBA_3_0/source/smbd/seal.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/seal.c       2007-03-20 21:21:04 UTC (rev 
21893)
+++ branches/SAMBA_3_0/source/smbd/seal.c       2007-03-20 22:01:02 UTC (rev 
21894)
@@ -49,9 +49,46 @@
 }
 
 /******************************************************************************
- 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)
 {
        struct smb_srv_trans_enc_ctx *ec = *pp_ec;
@@ -61,12 +98,8 @@
        }
 
        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 @@
 }
 
 /******************************************************************************
+ 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 @@
 #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 @@
 
        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 @@
 
        /* 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 @@
 }
 
 /******************************************************************************
+ 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 @@
        }
 
        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;
 }
 
 /******************************************************************************

Reply via email to