summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/client.h18
-rw-r--r--source3/lib/util_sock.c9
-rw-r--r--source3/libsmb/smb_seal.c178
3 files changed, 198 insertions, 7 deletions
diff --git a/source3/include/client.h b/source3/include/client.h
index aa8a647947..97922ba232 100644
--- a/source3/include/client.h
+++ b/source3/include/client.h
@@ -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;
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index 663502bef0..296405edd3 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -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;
}
diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c
index eb35fc05f9..90efa05f0b 100644
--- a/source3/libsmb/smb_seal.c
+++ b/source3/libsmb/smb_seal.c
@@ -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
+ }
+}