From 42238c78bb8820a21cfb08fc29a5109ee1a62bab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Mar 2007 19:15:14 +0000 Subject: [PATCH] r21917: Start to do the gss versions of sign+seal. Jeremy. (This used to be commit a226645353a40047b72de1b96c3a7676a2bf1034) --- source3/include/client.h | 4 +- source3/include/includes.h | 4 +- source3/libsmb/smb_seal.c | 97 ++++++++++++++++++++++++++++++-------- source3/smbd/seal.c | 8 ++-- 4 files changed, 85 insertions(+), 28 deletions(-) diff --git a/source3/include/client.h b/source3/include/client.h index 0f268834c68..a81c19bc555 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -79,14 +79,14 @@ struct rpc_pipe_client { }; /* Transport encryption state. */ -enum smb_trans_enc_type { SMB_TRANS_ENC_NTLM, SMB_TRANS_ENC_KRB5 }; +enum smb_trans_enc_type { SMB_TRANS_ENC_NTLM, SMB_TRANS_ENC_GSS }; struct smb_trans_enc_state { enum smb_trans_enc_type smb_enc_type; BOOL enc_on; union { NTLMSSP_STATE *ntlmssp_state; -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) gss_ctx_id_t context_handle; #endif }; diff --git a/source3/include/includes.h b/source3/include/includes.h index b591d7d8071..c51da335a2d 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -1187,10 +1187,10 @@ krb5_error_code smb_krb5_mk_error(krb5_context context, krb5_data *reply); /* Call for SMB transport encryption. */ -#if defined(HAVE_GSSAPI_SUPPORT) +#if defined(HAVE_GSSAPI) NTSTATUS common_gss_decrypt_buffer(gss_ctx_id_t context_handle, char *buf); #endif -#if defined(HAVE_GSSAPI_SUPPORT) +#if defined(HAVE_GSSAPI) NTSTATUS common_gss_encrypt_buffer(gss_ctx_id_t context_handle, char *buf, char **buf_out); #endif diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c index 9ea3a103509..f16c1402a2b 100644 --- a/source3/libsmb/smb_seal.c +++ b/source3/libsmb/smb_seal.c @@ -124,7 +124,7 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, cha gss-api decrypt an incoming buffer. ******************************************************************************/ -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) NTSTATUS common_gss_decrypt_buffer(gss_ctx_id_t context_handle, char *buf) { return NT_STATUS_NOT_SUPPORTED; @@ -136,10 +136,65 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, cha gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out. ******************************************************************************/ -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) - NTSTATUS common_gss_encrypt_buffer(gss_ctx_id_t context_handle, char *buf, char **buf_out) +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + NTSTATUS common_gss_encrypt_buffer(gss_ctx_id_t context_handle, char *buf, char **ppbuf_out) { - return NT_STATUS_NOT_SUPPORTED; + OM_uint32 ret = 0; + OM_uint32 minor = 0; + int flags_got = 0; + gss_buffer_desc in_buf, out_buf; + size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */ + + *ppbuf_out = NULL; + + if (buf_len < 8) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + in_buf.value = buf + 8; + in_buf.length = buf_len - 8; + + ret = gss_wrap(&minor, + context_handle, + True, /* we want sign+seal. */ + GSS_C_QOP_DEFAULT, + &in_buf, + &flags_got, /* did we get sign+seal ? */ + &out_buf); + + if (ret != GSS_S_COMPLETE) { + /* Um - no mapping for gss-errs to NTSTATUS yet. */ + return NT_STATUS_UNSUCCESSFUL; + } + + if (!flags_got) { + /* Sign+seal not supported. */ + gss_release_buffer(&minor, &out_buf); + return NT_STATUS_NOT_SUPPORTED; + } + + /* Ya see - this is why I *hate* gss-api. I don't + * want to have to malloc another buffer of the + * same size + 8 bytes just to get a continuous + * header + buffer, but gss won't let me pass in + * a pre-allocated buffer. Bastards (and you know + * who you are....). I might fix this by + * going to "encrypt_and_send" passing in a file + * descriptor and doing scatter-gather write with + * TCP cork on Linux. But I shouldn't have to + * bother :-*(. JRA. + */ + + *ppbuf_out = SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */ + if (!*ppbuf_out) { + gss_release_buffer(&minor, &out_buf); + return NT_STATUS_NO_MEMORY; + } + + smb_setlen(*ppbuf_out, out_buf.length + 8); + memcpy(*ppbuf_out+8, out_buf.value, out_buf.length); + gss_release_buffer(&minor, &out_buf); + return NT_STATUS_OK; } #endif @@ -162,14 +217,15 @@ NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, cha return NT_STATUS_OK; } - if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) { - return common_ntlm_encrypt_buffer(es->ntlmssp_state, buffer, buf_out); - } else { -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) - return common_gss_encrypt_buffer(es->context_handle, buffer, buf_out); -#else - return NT_STATUS_NOT_SUPPORTED; + switch (es->smb_enc_type) { + case SMB_TRANS_ENC_NTLM: + return common_ntlm_encrypt_buffer(es->ntlmssp_state, buffer, buf_out); +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + case SMB_TRANS_ENC_GSS: + return common_gss_encrypt_buffer(es->context_handle, buffer, buf_out); #endif + default: + return NT_STATUS_NOT_SUPPORTED; } } @@ -191,14 +247,15 @@ NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf) return NT_STATUS_OK; } - if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) { - return common_ntlm_decrypt_buffer(es->ntlmssp_state, buf); - } else { -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) - return common_gss_decrypt_buffer(es->context_handle, buf); -#else - return NT_STATUS_NOT_SUPPORTED; + switch (es->smb_enc_type) { + case SMB_TRANS_ENC_NTLM: + return common_ntlm_decrypt_buffer(es->ntlmssp_state, buf); +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + case SMB_TRANS_ENC_GSS: + return common_gss_decrypt_buffer(es->context_handle, buf); #endif + default: + return NT_STATUS_NOT_SUPPORTED; } } @@ -219,7 +276,7 @@ void common_free_encryption_state(struct smb_trans_enc_state **pp_es) ntlmssp_end(&es->ntlmssp_state); } } -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) if (es->smb_enc_type == SMB_TRANS_ENC_GSS) { /* Free the gss context handle. */ } @@ -251,7 +308,7 @@ void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf) return; } -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) /* gss-api free buffer.... */ #endif } diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 64965d42721..9fa35601f8f 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -180,8 +180,8 @@ NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out) Until success we do everything on the partial enc ctx. ******************************************************************************/ -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) -static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, DATA_BLOB secblob) +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) +static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) { return NT_STATUS_NOT_SUPPORTED; } @@ -246,8 +246,8 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ srv_free_encryption_context(&partial_srv_trans_enc_ctx); -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) - if (got_kerberos_mechanism && lp_use_kerberos_keytab()) ) { +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) { status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); } else #endif -- 2.34.1