r21876: Start adding in the seal implementation - prototype code
authorJeremy Allison <jra@samba.org>
Mon, 19 Mar 2007 20:39:58 +0000 (20:39 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:18:42 +0000 (12:18 -0500)
for the server side enc. (doesn't break anything).
I'll keep updating this until I've got NTLM seal working
on both client and server, then add in the gss level
seal.
Jeremy.

source/include/client.h
source/lib/util_sock.c
source/libsmb/smb_seal.c

index aa8a647947023f12b490c2c094ca68898fa1bcc7..97922ba232a8bbbb717e68dba15c368802023edb 100644 (file)
@@ -34,8 +34,7 @@
  * These definitions depend on smb.h
  */
 
-struct print_job_info
-{
+struct print_job_info {
        uint16 id;
        uint16 priority;
        size_t size;
@@ -79,6 +78,19 @@ struct rpc_pipe_client {
        struct dcinfo *dc;
 };
 
+/* Transport encryption state. */
+enum smb_trans_enc_type { SMB_TRANS_ENC_NTLM, SMB_TRANS_ENC_KRB5 };
+
+struct smb_trans_enc_state {
+       enum smb_trans_enc_type smb_enc_type;
+       union {
+               NTLMSSP_STATE *ntlmssp_state;
+#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
+               gss_ctx_id_t context_handle;
+#endif
+       };
+};
+
 struct cli_state {
        int port;
        int fd;
@@ -137,6 +149,8 @@ struct cli_state {
 
        smb_sign_info sign_info;
 
+       struct smb_trans_enc_state *trans_enc_state; /* Setup if we're encrypting SMB's. */
+
        /* the session key for this CLI, outside 
           any per-pipe authenticaion */
        DATA_BLOB user_session_key;
index 663502bef0723fd37ea2f7e5f76530b1c8b2c9f0..296405edd396b7a9661f0bcb5ba7f0c74ab05980 100644 (file)
@@ -770,29 +770,32 @@ BOOL send_smb(int fd, char *buffer)
        size_t len;
        size_t nwritten=0;
        ssize_t ret;
+       char *buf_out;
 
        /* Sign the outgoing packet if required. */
        srv_calculate_sign_mac(buffer);
 
-       status = srv_encrypt_buffer(buffer);
+       status = srv_encrypt_buffer(buffer, &buf_out);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("send_smb: SMB encryption failed on outgoing packet! Error %s\n",
                        nt_errstr(status) ));
                return False;
        }
 
-       len = smb_len(buffer) + 4;
+       len = smb_len(buf_out) + 4;
 
        while (nwritten < len) {
-               ret = write_data(fd,buffer+nwritten,len - nwritten);
+               ret = write_data(fd,buf_out+nwritten,len - nwritten);
                if (ret <= 0) {
                        DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
                                (int)len,(int)ret, strerror(errno) ));
+                       srv_free_buffer(buf_out);
                        return False;
                }
                nwritten += ret;
        }
 
+       srv_free_buffer(buf_out);
        return True;
 }
 
index eb35fc05f962224bd973c828253f358907117bfd..90efa05f0b90004c45f487dc8f32f2871c4838a2 100644 (file)
@@ -30,12 +30,186 @@ NTSTATUS cli_encrypt_message(struct cli_state *cli)
        return NT_STATUS_OK;
 }
 
-NTSTATUS srv_decrypt_buffer(char *buffer)
+/* Server state if we're encrypting SMBs. If NULL then enc is off. */
+
+static struct smb_trans_enc_state *srv_trans_enc_state;
+
+/******************************************************************************
+ Is server encryption on ?
+******************************************************************************/
+
+BOOL srv_encryption_on(void)
+{
+       return srv_trans_enc_state != NULL;
+}
+
+/******************************************************************************
+ Free an encryption-allocated buffer.
+******************************************************************************/
+
+void srv_free_buffer(char *buf_out)
 {
+       if (!srv_trans_enc_state) {
+               return;
+       }
+
+       if (srv_trans_enc_state->smb_enc_type == SMB_TRANS_ENC_NTLM) {
+               SAFE_FREE(buf_out);
+               return;
+       }
+
+#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
+       /* gss-api free buffer.... */
+#endif
+}
+
+/******************************************************************************
+ gss-api decrypt an incoming buffer.
+******************************************************************************/
+
+#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
+static NTSTATUS srv_gss_decrypt_buffer(gss_ctx_id_t context_handle, char *buf)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+#endif
+
+/******************************************************************************
+ NTLM decrypt an incoming buffer.
+******************************************************************************/
+
+static NTSTATUS srv_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
+{
+       NTSTATUS status;
+       size_t orig_len = smb_len(buf);
+       size_t new_len = orig_len - NTLMSSP_SIG_SIZE;
+       DATA_BLOB sig;
+
+       if (orig_len < 8 + NTLMSSP_SIG_SIZE) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+
+       /* Save off the signature. */
+       sig = data_blob(buf+orig_len-NTLMSSP_SIG_SIZE, NTLMSSP_SIG_SIZE);
+
+       status = ntlmssp_unseal_packet(ntlmssp_state,
+               (unsigned char *)buf + 8, /* 4 byte len + 0xFF 'S' 'M' 'B' */
+               new_len - 8,
+               (unsigned char *)buf,
+               new_len,
+               &sig);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               data_blob_free(&sig);
+               return status;
+       }
+       /* Reset the length. */
+       smb_setlen(buf, new_len);
        return NT_STATUS_OK;
 }
 
-NTSTATUS srv_encrypt_buffer(char *buffer)
+/******************************************************************************
+ Decrypt an incoming buffer.
+******************************************************************************/
+
+NTSTATUS srv_decrypt_buffer(char *buf)
 {
+       if (!srv_trans_enc_state) {
+               /* Not decrypting. */
+               return NT_STATUS_OK;
+       }
+       if (srv_trans_enc_state->smb_enc_type == SMB_TRANS_ENC_NTLM) {
+               return srv_ntlm_decrypt_buffer(srv_trans_enc_state->ntlmssp_state, buf);
+       } else {
+#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
+               return srv_gss_decrypt_buffer(srv_trans_enc_state->context_handle, buf);
+#else
+               return NT_STATUS_NOT_SUPPORTED;
+#endif
+       }
+}
+
+/******************************************************************************
+ gss-api encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
+******************************************************************************/
+
+#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
+static NTSTATUS srv_gss_encrypt_buffer(gss_ctx_id_t context_handle, char *buf, char **buf_out)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+#endif
+
+/******************************************************************************
+ NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
+******************************************************************************/
+
+static NTSTATUS srv_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, char **ppbuf_out)
+{
+       NTSTATUS status;
+       char *buf_out;
+       size_t orig_len = smb_len(buf);
+       size_t new_len = orig_len + NTLMSSP_SIG_SIZE;
+       DATA_BLOB sig;
+
+       *ppbuf_out = NULL;
+
+       if (orig_len < 8) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+
+       /* 
+        * We know smb_len can't return a value > 128k, so no int overflow
+        * check needed.
+        */
+
+       /* Copy the original buffer. */
+
+       buf_out = SMB_XMALLOC_ARRAY(char, new_len);
+       memcpy(buf_out, buf, orig_len);
+       /* Last 16 bytes undefined here... */
+
+       smb_setlen(buf_out, new_len);
+
+       sig = data_blob(NULL, NTLMSSP_SIG_SIZE);
+
+       status = ntlmssp_seal_packet(ntlmssp_state,
+               (unsigned char *)buf_out + 8, /* 4 byte len + 0xFF 'S' 'M' 'B' */
+               orig_len - 8,
+               (unsigned char *)buf_out,
+               orig_len,
+               &sig);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               data_blob_free(&sig);
+               SAFE_FREE(buf_out);
+               return status;
+       }
+
+       memcpy(buf_out+orig_len, sig.data, NTLMSSP_SIG_SIZE);
+       *ppbuf_out = buf_out;
        return NT_STATUS_OK;
 }
+
+/******************************************************************************
+ Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
+******************************************************************************/
+
+NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out)
+{
+       if (!srv_trans_enc_state) {
+               /* Not encrypting. */
+               *buf_out = buffer;
+               return NT_STATUS_OK;
+       }
+
+       if (srv_trans_enc_state->smb_enc_type == SMB_TRANS_ENC_NTLM) {
+               return srv_ntlm_encrypt_buffer(srv_trans_enc_state->ntlmssp_state, buffer, buf_out);
+       } else {
+#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
+               return srv_gss_encrypt_buffer(srv_trans_enc_state->context_handle, buffer, buf_out);
+#else
+               return NT_STATUS_NOT_SUPPORTED;
+#endif
+       }
+}