diff options
Diffstat (limited to 'source4/auth')
-rw-r--r-- | source4/auth/gensec/gensec_gssapi.c | 80 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_krb5.c | 184 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos_pac.c | 213 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos_verify.c | 2 |
4 files changed, 277 insertions, 202 deletions
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 533448e06f..a95805f9fa 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -3,8 +3,8 @@ Kerberos backend for GENSEC - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004 - Copyright (C) Stefan Metzmacher <metze@samba.org> 2005 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 + Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -224,6 +224,7 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security) { struct gensec_gssapi_state *gensec_gssapi_state; + struct cli_credentials *creds = gensec_get_credentials(gensec_security); NTSTATUS nt_status; gss_buffer_desc name_token; OM_uint32 maj_stat, min_stat; @@ -251,8 +252,8 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi return NT_STATUS_UNSUCCESSFUL; } - name_token.value = cli_credentials_get_principal(gensec_get_credentials(gensec_security), - gensec_gssapi_state), + name_token.value = cli_credentials_get_principal(creds, + gensec_gssapi_state); name_token.length = strlen(name_token.value); maj_stat = gss_import_name (&min_stat, @@ -267,7 +268,7 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi } nt_status = kinit_to_ccache(gensec_gssapi_state, - gensec_get_credentials(gensec_security), + creds, gensec_gssapi_state->smb_krb5_context, &gensec_gssapi_state->ccache, &gensec_gssapi_state->ccache_name); if (!NT_STATUS_IS_OK(nt_status)) { @@ -724,16 +725,22 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi struct auth_session_info **_session_info) { NTSTATUS nt_status; + TALLOC_CTX *mem_ctx; struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data; struct auth_serversupplied_info *server_info = NULL; struct auth_session_info *session_info = NULL; + struct PAC_LOGON_INFO *logon_info; char *p; char *principal; const char *account_name; const char *realm; OM_uint32 maj_stat, min_stat; gss_buffer_desc name_token; + gss_buffer_desc pac; + mem_ctx = talloc_named(gensec_gssapi_state, 0, "gensec_gssapi_session_info context"); + NT_STATUS_HAVE_NO_MEMORY(mem_ctx); + maj_stat = gss_display_name (&min_stat, gensec_gssapi_state->client_name, &name_token, @@ -742,11 +749,14 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi return NT_STATUS_FOOBAR; } - principal = talloc_strndup(gensec_gssapi_state, name_token.value, name_token.length); + principal = talloc_strndup(mem_ctx, name_token.value, name_token.length); gss_release_buffer(&min_stat, &name_token); - NT_STATUS_HAVE_NO_MEMORY(principal); + if (!principal) { + talloc_free(mem_ctx); + return NT_STATUS_NO_MEMORY; + } p = strchr(principal, '@'); if (p) { @@ -757,24 +767,56 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi realm = lp_realm(); } account_name = principal; + + maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, + gensec_gssapi_state->gssapi_context, + 1, + &pac); + + if (maj_stat == 0) { + DATA_BLOB pac_blob = data_blob_talloc(mem_ctx, pac.value, pac.length); + pac_blob = unwrap_pac(mem_ctx, &pac_blob); + gss_release_buffer(&min_stat, &pac); + + /* decode and verify the pac */ + nt_status = kerberos_decode_pac(mem_ctx, &logon_info, pac_blob, + gensec_gssapi_state->smb_krb5_context); + + if (NT_STATUS_IS_OK(nt_status)) { + union netr_Validation validation; + validation.sam3 = &logon_info->info3; + nt_status = make_server_info_netlogon_validation(gensec_gssapi_state, + account_name, + 3, &validation, + &server_info); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return nt_status; + } + } else { + maj_stat = 1; + } + } + + if (maj_stat) { + /* IF we have the PAC - otherwise we need to get this + * data from elsewere - local ldb, or (TODO) lookup of some + * kind... + * + * when heimdal can generate the PAC, we should fail if there's + * no PAC present + */ - /* IF we have the PAC - otherwise we need to get this - * data from elsewere - local ldb, or (TODO) lookup of some - * kind... - * - * when heimdal can generate the PAC, we should fail if there's - * no PAC present - */ - - { DATA_BLOB user_sess_key = data_blob(NULL, 0); DATA_BLOB lm_sess_key = data_blob(NULL, 0); /* TODO: should we pass the krb5 session key in here? */ - nt_status = sam_get_server_info(gensec_gssapi_state, account_name, realm, + nt_status = sam_get_server_info(mem_ctx, account_name, realm, user_sess_key, lm_sess_key, &server_info); - talloc_free(principal); - NT_STATUS_NOT_OK_RETURN(nt_status); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return nt_status; + } } /* references the server_info into the session_info */ diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c index 348a75b535..6d3c105405 100644 --- a/source4/auth/gensec/gensec_krb5.c +++ b/source4/auth/gensec/gensec_krb5.c @@ -51,185 +51,6 @@ struct gensec_krb5_state { char *peer_principal; }; -#ifdef KRB5_DO_VERIFY_PAC -static NTSTATUS gensec_krb5_pac_checksum(DATA_BLOB pac_data, - struct PAC_SIGNATURE_DATA *sig, - struct gensec_krb5_state *gensec_krb5_state, - uint32 keyusage) -{ - krb5_error_code ret; - krb5_crypto crypto; - Checksum cksum; - int i; - - cksum.cksumtype = (CKSUMTYPE)sig->type; - cksum.checksum.length = sizeof(sig->signature); - cksum.checksum.data = sig->signature; - - - ret = krb5_crypto_init(gensec_krb5_state->smb_krb5_context->krb5_context, - &gensec_krb5_state->keyblock, - 0, - &crypto); - if (ret) { - DEBUG(0,("krb5_crypto_init() failed\n")); - return NT_STATUS_FOOBAR; - } - for (i=0; i < 40; i++) { - keyusage = i; - ret = krb5_verify_checksum(gensec_krb5_state->smb_krb5_context->krb5_context, - crypto, - keyusage, - pac_data.data, - pac_data.length, - &cksum); - if (!ret) { - DEBUG(0,("PAC Verified: keyusage: %d\n", keyusage)); - break; - } - } - krb5_crypto_destroy(gensec_krb5_state->smb_krb5_context->krb5_context, crypto); - - if (ret) { - DEBUG(0,("NOT verifying PAC checksums yet!\n")); - //return NT_STATUS_LOGON_FAILURE; - } else { - DEBUG(0,("PAC checksums verified!\n")); - } - - return NT_STATUS_OK; -} -#endif - -static NTSTATUS gensec_krb5_decode_pac(TALLOC_CTX *mem_ctx, - struct PAC_LOGON_INFO **logon_info_out, - DATA_BLOB blob, - struct gensec_krb5_state *gensec_krb5_state) -{ - NTSTATUS status; - struct PAC_SIGNATURE_DATA srv_sig; - struct PAC_SIGNATURE_DATA *srv_sig_ptr; - struct PAC_SIGNATURE_DATA kdc_sig; - struct PAC_SIGNATURE_DATA *kdc_sig_ptr; - struct PAC_LOGON_INFO *logon_info = NULL; - struct PAC_DATA pac_data; -#ifdef KRB5_DO_VERIFY_PAC - DATA_BLOB tmp_blob = data_blob(NULL, 0); -#endif - int i; - - status = ndr_pull_struct_blob(&blob, mem_ctx, &pac_data, - (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("can't parse the PAC\n")); - return status; - } - NDR_PRINT_DEBUG(PAC_DATA, &pac_data); - - if (pac_data.num_buffers < 3) { - /* we need logon_ingo, service_key and kdc_key */ - DEBUG(0,("less than 3 PAC buffers\n")); - return NT_STATUS_FOOBAR; - } - - for (i=0; i < pac_data.num_buffers; i++) { - switch (pac_data.buffers[i].type) { - case PAC_TYPE_LOGON_INFO: - if (!pac_data.buffers[i].info) { - break; - } - logon_info = &pac_data.buffers[i].info->logon_info; - break; - case PAC_TYPE_SRV_CHECKSUM: - if (!pac_data.buffers[i].info) { - break; - } - srv_sig_ptr = &pac_data.buffers[i].info->srv_cksum; - srv_sig = pac_data.buffers[i].info->srv_cksum; - break; - case PAC_TYPE_KDC_CHECKSUM: - if (!pac_data.buffers[i].info) { - break; - } - kdc_sig_ptr = &pac_data.buffers[i].info->kdc_cksum; - kdc_sig = pac_data.buffers[i].info->kdc_cksum; - break; - case PAC_TYPE_UNKNOWN_10: - break; - default: - break; - } - } - - if (!logon_info) { - DEBUG(0,("PAC no logon_info\n")); - return NT_STATUS_FOOBAR; - } - - if (!srv_sig_ptr) { - DEBUG(0,("PAC no srv_key\n")); - return NT_STATUS_FOOBAR; - } - - if (!kdc_sig_ptr) { - DEBUG(0,("PAC no kdc_key\n")); - return NT_STATUS_FOOBAR; - } -#ifdef KRB5_DO_VERIFY_PAC - /* clear the kdc_key */ -/* memset((void *)kdc_sig_ptr , '\0', sizeof(*kdc_sig_ptr));*/ - - status = ndr_push_struct_blob(&tmp_blob, mem_ctx, &pac_data, - (ndr_push_flags_fn_t)ndr_push_PAC_DATA); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data, - (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("can't parse the PAC\n")); - return status; - } - /*NDR_PRINT_DEBUG(PAC_DATA, &pac_data);*/ - - /* verify by kdc_key */ - status = gensec_krb5_pac_checksum(tmp_blob, &kdc_sig, gensec_krb5_state, 0); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* clear the service_key */ -/* memset((void *)srv_sig_ptr , '\0', sizeof(*srv_sig_ptr));*/ - - status = ndr_push_struct_blob(&tmp_blob, mem_ctx, &pac_data, - (ndr_push_flags_fn_t)ndr_push_PAC_DATA); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data, - (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("can't parse the PAC\n")); - return status; - } - NDR_PRINT_DEBUG(PAC_DATA, &pac_data); - - /* verify by servie_key */ - status = gensec_krb5_pac_checksum(tmp_blob, &srv_sig, gensec_krb5_state, 0); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } -#endif - DEBUG(0,("account_name: %s [%s]\n", - logon_info->info3.base.account_name.string, - logon_info->info3.base.full_name.string)); - *logon_info_out = logon_info; - - return status; -} - static int gensec_krb5_destory(void *ptr) { struct gensec_krb5_state *gensec_krb5_state = ptr; @@ -263,7 +84,6 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security) gensec_security->private_data = gensec_krb5_state; - initialize_krb5_error_table(); gensec_krb5_state->auth_context = NULL; gensec_krb5_state->ccache = NULL; ZERO_STRUCT(gensec_krb5_state->ticket); @@ -623,8 +443,8 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security account_name = principal; /* decode and verify the pac */ - nt_status = gensec_krb5_decode_pac(gensec_krb5_state, &logon_info, gensec_krb5_state->pac, - gensec_krb5_state); + nt_status = kerberos_decode_pac(gensec_krb5_state, &logon_info, gensec_krb5_state->pac, + gensec_krb5_state); /* IF we have the PAC - otherwise we need to get this * data from elsewere - local ldb, or (TODO) lookup of some diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c new file mode 100644 index 0000000000..8f3d2cd72c --- /dev/null +++ b/source4/auth/kerberos/kerberos_pac.c @@ -0,0 +1,213 @@ +/* + Unix SMB/CIFS implementation. + + Kerberos backend for GENSEC + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004 + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Luke Howard 2002-2003 + Copyright (C) Stefan Metzmacher 2004-2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "system/kerberos.h" +#include "system/time.h" +#include "system/network.h" +#include "auth/kerberos/kerberos.h" +#include "librpc/gen_ndr/ndr_krb5pac.h" +#include "auth/auth.h" + +#ifdef KRB5_DO_VERIFY_PAC +static NTSTATUS kerberos_pac_checksum(DATA_BLOB pac_data, + struct PAC_SIGNATURE_DATA *sig, + struct smb_krb5_context *smb_krb5_context, + uint32 keyusage) +{ + krb5_error_code ret; + krb5_crypto crypto; + Checksum cksum; + int i; + + cksum.cksumtype = (CKSUMTYPE)sig->type; + cksum.checksum.length = sizeof(sig->signature); + cksum.checksum.data = sig->signature; + + + ret = krb5_crypto_init(smb_krb5_context->krb5_context, + &gensec_krb5_state->keyblock, + 0, + &crypto); + if (ret) { + DEBUG(0,("krb5_crypto_init() failed\n")); + return NT_STATUS_FOOBAR; + } + for (i=0; i < 40; i++) { + keyusage = i; + ret = krb5_verify_checksum(smb_krb5_context->krb5_context, + crypto, + keyusage, + pac_data.data, + pac_data.length, + &cksum); + if (!ret) { + DEBUG(0,("PAC Verified: keyusage: %d\n", keyusage)); + break; + } + } + krb5_crypto_destroy(smb_krb5_context->krb5_context, crypto); + + if (ret) { + DEBUG(0,("NOT verifying PAC checksums yet!\n")); + //return NT_STATUS_LOGON_FAILURE; + } else { + DEBUG(0,("PAC checksums verified!\n")); + } + + return NT_STATUS_OK; +} +#endif + +NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, + struct PAC_LOGON_INFO **logon_info_out, + DATA_BLOB blob, + struct smb_krb5_context *smb_krb5_context) +{ + NTSTATUS status; + struct PAC_SIGNATURE_DATA srv_sig; + struct PAC_SIGNATURE_DATA *srv_sig_ptr; + struct PAC_SIGNATURE_DATA kdc_sig; + struct PAC_SIGNATURE_DATA *kdc_sig_ptr; + struct PAC_LOGON_INFO *logon_info = NULL; + struct PAC_DATA pac_data; +#ifdef KRB5_DO_VERIFY_PAC + DATA_BLOB tmp_blob = data_blob(NULL, 0); +#endif + int i; + + status = ndr_pull_struct_blob(&blob, mem_ctx, &pac_data, + (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("can't parse the PAC\n")); + return status; + } + NDR_PRINT_DEBUG(PAC_DATA, &pac_data); + + if (pac_data.num_buffers < 3) { + /* we need logon_ingo, service_key and kdc_key */ + DEBUG(0,("less than 3 PAC buffers\n")); + return NT_STATUS_FOOBAR; + } + + for (i=0; i < pac_data.num_buffers; i++) { + switch (pac_data.buffers[i].type) { + case PAC_TYPE_LOGON_INFO: + if (!pac_data.buffers[i].info) { + break; + } + logon_info = &pac_data.buffers[i].info->logon_info; + break; + case PAC_TYPE_SRV_CHECKSUM: + if (!pac_data.buffers[i].info) { + break; + } + srv_sig_ptr = &pac_data.buffers[i].info->srv_cksum; + srv_sig = pac_data.buffers[i].info->srv_cksum; + break; + case PAC_TYPE_KDC_CHECKSUM: + if (!pac_data.buffers[i].info) { + break; + } + kdc_sig_ptr = &pac_data.buffers[i].info->kdc_cksum; + kdc_sig = pac_data.buffers[i].info->kdc_cksum; + break; + case PAC_TYPE_UNKNOWN_10: + break; + default: + break; + } + } + + if (!logon_info) { + DEBUG(0,("PAC no logon_info\n")); + return NT_STATUS_FOOBAR; + } + + if (!srv_sig_ptr) { + DEBUG(0,("PAC no srv_key\n")); + return NT_STATUS_FOOBAR; + } + + if (!kdc_sig_ptr) { + DEBUG(0,("PAC no kdc_key\n")); + return NT_STATUS_FOOBAR; + } +#ifdef KRB5_DO_VERIFY_PAC + /* clear the kdc_key */ +/* memset((void *)kdc_sig_ptr , '\0', sizeof(*kdc_sig_ptr));*/ + + status = ndr_push_struct_blob(&tmp_blob, mem_ctx, &pac_data, + (ndr_push_flags_fn_t)ndr_push_PAC_DATA); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data, + (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("can't parse the PAC\n")); + return status; + } + /*NDR_PRINT_DEBUG(PAC_DATA, &pac_data);*/ + + /* verify by kdc_key */ + status = kerberos_pac_checksum(tmp_blob, &kdc_sig, smb_krb5_context, 0); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* clear the service_key */ +/* memset((void *)srv_sig_ptr , '\0', sizeof(*srv_sig_ptr));*/ + + status = ndr_push_struct_blob(&tmp_blob, mem_ctx, &pac_data, + (ndr_push_flags_fn_t)ndr_push_PAC_DATA); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data, + (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("can't parse the PAC\n")); + return status; + } + NDR_PRINT_DEBUG(PAC_DATA, &pac_data); + + /* verify by servie_key */ + status = kerberos_pac_checksum(tmp_blob, &srv_sig, smb_krb5_context, 0); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } +#endif + DEBUG(0,("account_name: %s [%s]\n", + logon_info->info3.base.account_name.string, + logon_info->info3.base.full_name.string)); + *logon_info_out = logon_info; + + return status; +} + diff --git a/source4/auth/kerberos/kerberos_verify.c b/source4/auth/kerberos/kerberos_verify.c index f269012ae3..01b8a75c95 100644 --- a/source4/auth/kerberos/kerberos_verify.c +++ b/source4/auth/kerberos/kerberos_verify.c @@ -34,7 +34,7 @@ #ifdef HAVE_KRB5 -static DATA_BLOB unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data) +DATA_BLOB unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data) { DATA_BLOB out; DATA_BLOB pac_contents = data_blob(NULL, 0); |