diff options
Diffstat (limited to 'source4/auth/gensec')
-rw-r--r-- | source4/auth/gensec/gensec_gssapi.c | 127 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_krb5.c | 98 |
2 files changed, 134 insertions, 91 deletions
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index ed407b623b..136962d892 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -24,7 +24,7 @@ #include "includes.h" #include "system/kerberos.h" -#include "heimdal/lib/gssapi/gssapi.h" +#include "heimdal/lib/gssapi/gssapi/gssapi.h" #include "auth/kerberos/kerberos.h" #include "librpc/gen_ndr/krb5pac.h" #include "auth/auth.h" @@ -73,6 +73,7 @@ struct gensec_gssapi_state { * layer... */ size_t max_wrap_buf_size; + int gss_exchange_count; }; static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security); @@ -133,12 +134,14 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security) { struct gensec_gssapi_state *gensec_gssapi_state; krb5_error_code ret; - + struct gsskrb5_send_to_kdc send_to_kdc; + gensec_gssapi_state = talloc(gensec_security, struct gensec_gssapi_state); if (!gensec_gssapi_state) { return NT_STATUS_NO_MEMORY; } + gensec_gssapi_state->gss_exchange_count = 0; gensec_gssapi_state->max_wrap_buf_size = lp_parm_int(-1, "gensec_gssapi", "max wrap buf size", 65536); @@ -186,10 +189,18 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security) gensec_gssapi_state->gss_oid = gss_mech_krb5; + send_to_kdc.func = smb_krb5_send_and_recv_func; + send_to_kdc.ptr = gensec_security->event_ctx; + + ret = gsskrb5_set_send_to_kdc(&send_to_kdc); + if (ret) { + DEBUG(1,("gensec_krb5_start: gsskrb5_set_send_to_kdc failed\n")); + return NT_STATUS_INTERNAL_ERROR; + } ret = smb_krb5_init_context(gensec_gssapi_state, &gensec_gssapi_state->smb_krb5_context); if (ret) { - DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n", + DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n", error_message(ret))); return NT_STATUS_INTERNAL_ERROR; } @@ -431,6 +442,8 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, } + gensec_gssapi_state->gss_exchange_count++; + if (maj_stat == GSS_S_COMPLETE) { *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length); gss_release_buffer(&min_stat2, &output_token); @@ -493,12 +506,14 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, /* garbage input, possibly from the auto-mech detection */ return NT_STATUS_INVALID_PARAMETER; default: - DEBUG(1, ("GSS(krb5) Update failed: %s\n", + DEBUG(1, ("GSS Update(krb5)(%d) Update failed: %s\n", + gensec_gssapi_state->gss_exchange_count, gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); return nt_status; } } else { - DEBUG(1, ("GSS Update failed: %s\n", + DEBUG(1, ("GSS Update(%d) failed: %s\n", + gensec_gssapi_state->gss_exchange_count, gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); return nt_status; } @@ -583,7 +598,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, &conf_state, &output_token); if (GSS_ERROR(maj_stat)) { - DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n", + DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); return NT_STATUS_ACCESS_DENIED; } @@ -648,7 +663,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, &conf_state, &output_token); if (GSS_ERROR(maj_stat)) { - DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n", + DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); return NT_STATUS_ACCESS_DENIED; } @@ -1185,38 +1200,57 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi return NT_STATUS_NO_MEMORY; } - maj_stat = gss_krb5_copy_service_keyblock(&min_stat, - gensec_gssapi_state->gssapi_context, - &keyblock); - - if (maj_stat == 0) { - maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat, - gensec_gssapi_state->gssapi_context, - &authtime); - } - - if (maj_stat == 0) { - maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, - gensec_gssapi_state->gssapi_context, - KRB5_AUTHDATA_WIN2K_PAC, - &pac); - } - + maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, + gensec_gssapi_state->gssapi_context, + KRB5_AUTHDATA_WIN2K_PAC, + &pac); + + if (maj_stat == 0) { pac_blob = data_blob_talloc(mem_ctx, pac.value, pac.length); gss_release_buffer(&min_stat, &pac); + + } else { + pac_blob = data_blob(NULL, 0); } /* IF we have the PAC - otherwise we need to get this * data from elsewere - local ldb, or (TODO) lookup of some * kind... */ - if (maj_stat == 0) { + if (pac_blob.length) { krb5_error_code ret; + union netr_Validation validation; - ret = krb5_parse_name(gensec_gssapi_state->smb_krb5_context->krb5_context, - principal_string, &principal); + maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat, + gensec_gssapi_state->gssapi_context, + &authtime); + + if (GSS_ERROR(maj_stat)) { + DEBUG(1, ("gsskrb5_extract_authtime_from_sec_context: %s\n", + gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); + talloc_free(mem_ctx); + return NT_STATUS_FOOBAR; + } + + maj_stat = gsskrb5_extract_service_keyblock(&min_stat, + gensec_gssapi_state->gssapi_context, + &keyblock); + + if (GSS_ERROR(maj_stat)) { + DEBUG(1, ("gsskrb5_copy_service_keyblock failed: %s\n", + gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); + talloc_free(mem_ctx); + return NT_STATUS_FOOBAR; + } + + ret = krb5_parse_name_flags(gensec_gssapi_state->smb_krb5_context->krb5_context, + principal_string, + KRB5_PRINCIPAL_PARSE_MUST_REALM, + &principal); if (ret) { + krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, + keyblock); talloc_free(mem_ctx); return NT_STATUS_INVALID_PARAMETER; } @@ -1226,25 +1260,25 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi gensec_gssapi_state->smb_krb5_context->krb5_context, NULL, keyblock, principal, authtime, NULL); krb5_free_principal(gensec_gssapi_state->smb_krb5_context->krb5_context, principal); + krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, + keyblock); - 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, - NULL, - 3, &validation, - &server_info); - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(mem_ctx); - return nt_status; - } - } else { - maj_stat = 1; + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return nt_status; } - } - - if (maj_stat) { - DEBUG(1, ("Unable to use PAC, resorting to local user lookup!\n")); + validation.sam3 = &logon_info->info3; + nt_status = make_server_info_netlogon_validation(gensec_gssapi_state, + NULL, + 3, &validation, + &server_info); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return nt_status; + } + } else if (!lp_parm_bool(-1, "gensec", "require_pac", False)) { + DEBUG(1, ("Unable to find PAC, resorting to local user lookup: %s\n", + gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); nt_status = sam_get_server_info_principal(mem_ctx, principal_string, &server_info); @@ -1252,6 +1286,11 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi talloc_free(mem_ctx); return nt_status; } + } else { + DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s\n", + principal_string, + gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); + return NT_STATUS_ACCESS_DENIED; } /* 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 d84f3dedf5..66d2801520 100644 --- a/source4/auth/gensec/gensec_krb5.c +++ b/source4/auth/gensec/gensec_krb5.c @@ -527,6 +527,7 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security struct PAC_LOGON_INFO *logon_info; krb5_principal client_principal; + char *principal_string; DATA_BLOB pac; krb5_data pac_data; @@ -538,30 +539,63 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security return NT_STATUS_NO_MEMORY; } + ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal); + if (ret) { + DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n", + smb_get_krb5_error_message(context, + ret, mem_ctx))); + talloc_free(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context, + client_principal, &principal_string); + if (ret) { + DEBUG(1, ("Unable to parse client principal: %s\n", + smb_get_krb5_error_message(context, + ret, mem_ctx))); + talloc_free(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + ret = krb5_ticket_get_authorization_data_type(context, gensec_krb5_state->ticket, KRB5_AUTHDATA_WIN2K_PAC, &pac_data); - if (ret) { + if (ret && lp_parm_bool(-1, "gensec", "require_pac", False)) { + DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s \n", + principal_string, + smb_get_krb5_error_message(context, + ret, mem_ctx))); + krb5_free_principal(context, client_principal); + free(principal_string); + return NT_STATUS_ACCESS_DENIED; + } else if (ret) { + /* NO pac */ DEBUG(5, ("krb5_ticket_get_authorization_data_type failed to find PAC: %s\n", smb_get_krb5_error_message(context, ret, mem_ctx))); + nt_status = sam_get_server_info_principal(mem_ctx, principal_string, + &server_info); + krb5_free_principal(context, client_principal); + free(principal_string); + + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return nt_status; + } } else { + /* Found pac */ + union netr_Validation validation; + free(principal_string); + pac = data_blob_talloc(mem_ctx, pac_data.data, pac_data.length); if (!pac.data) { + krb5_free_principal(context, client_principal); talloc_free(mem_ctx); return NT_STATUS_NO_MEMORY; } - ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal); - if (ret) { - DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n", - smb_get_krb5_error_message(context, - ret, mem_ctx))); - talloc_free(mem_ctx); - return NT_STATUS_NO_MEMORY; - } - /* decode and verify the pac */ nt_status = kerberos_pac_logon_info(gensec_krb5_state, &logon_info, pac, gensec_krb5_state->smb_krb5_context->krb5_context, @@ -570,46 +604,16 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security gensec_krb5_state->ticket->ticket.authtime, NULL); krb5_free_principal(context, client_principal); - if (NT_STATUS_IS_OK(nt_status)) { - union netr_Validation validation; - validation.sam3 = &logon_info->info3; - nt_status = make_server_info_netlogon_validation(mem_ctx, - NULL, - 3, &validation, - &server_info); - } - } - - - - /* IF we have the PAC - otherwise we need to get this - * data from elsewere - local ldb, or (TODO) lookup of some - * kind... - */ - if (!NT_STATUS_IS_OK(nt_status)) { - /* NO pac, or can't parse or verify it */ - char *principal_string; - ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal); - if (ret) { - DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n", - smb_get_krb5_error_message(context, - ret, mem_ctx))); - talloc_free(mem_ctx); - return NT_STATUS_NO_MEMORY; - } - - ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context, - client_principal, &principal_string); - krb5_free_principal(context, client_principal); - if (ret) { + if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); - return NT_STATUS_NO_MEMORY; + return nt_status; } - nt_status = sam_get_server_info_principal(mem_ctx, principal_string, - &server_info); - free(principal_string); - + validation.sam3 = &logon_info->info3; + nt_status = make_server_info_netlogon_validation(mem_ctx, + NULL, + 3, &validation, + &server_info); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); return nt_status; |