diff options
Diffstat (limited to 'source4/auth')
-rw-r--r-- | source4/auth/credentials/credentials_krb5.h | 4 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_gssapi.c | 127 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_krb5.c | 98 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos.c | 4 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos_pac.c | 6 | ||||
-rw-r--r-- | source4/auth/kerberos/krb5_init_context.c | 32 | ||||
-rw-r--r-- | source4/auth/kerberos/krb5_init_context.h | 5 |
7 files changed, 159 insertions, 117 deletions
diff --git a/source4/auth/credentials/credentials_krb5.h b/source4/auth/credentials/credentials_krb5.h index 2bd38af5c7..22c0f5abfe 100644 --- a/source4/auth/credentials/credentials_krb5.h +++ b/source4/auth/credentials/credentials_krb5.h @@ -21,9 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -struct EncryptionKey; - -#include "heimdal/lib/gssapi/gssapi.h" +#include "heimdal/lib/gssapi/gssapi/gssapi.h" struct ccache_container; 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; diff --git a/source4/auth/kerberos/kerberos.c b/source4/auth/kerberos/kerberos.c index 06f0c186a3..2b4c5d4cb0 100644 --- a/source4/auth/kerberos/kerberos.c +++ b/source4/auth/kerberos/kerberos.c @@ -45,6 +45,8 @@ krb5_get_init_creds_opt_init(&options); + krb5_get_init_creds_opt_set_default_flags(ctx, NULL, NULL, &options); + if ((code = krb5_get_init_creds_keyblock(ctx, &my_creds, principal, keyblock, 0, NULL, &options))) { return code; @@ -87,6 +89,8 @@ krb5_get_init_creds_opt_init(&options); + krb5_get_init_creds_opt_set_default_flags(ctx, NULL, NULL, &options); + if ((code = krb5_get_init_creds_password(ctx, &my_creds, principal, password, NULL, NULL, 0, NULL, &options))) { diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c index dcfe16c896..8e1801f745 100644 --- a/source4/auth/kerberos/kerberos_pac.c +++ b/source4/auth/kerberos/kerberos_pac.c @@ -280,7 +280,8 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, return NT_STATUS_ACCESS_DENIED; } - ret = krb5_parse_name_norealm(context, logon_name->account_name, &client_principal_pac); + ret = krb5_parse_name_flags(context, logon_name->account_name, KRB5_PRINCIPAL_PARSE_NO_REALM, + &client_principal_pac); if (ret) { DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n", logon_name->account_name, @@ -591,7 +592,8 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx, u_LOGON_INFO->logon_info.info = LOGON_INFO; LOGON_INFO->info3 = *sam3; - ret = krb5_unparse_name_norealm(context, client_principal, &name); + ret = krb5_unparse_name_flags(context, client_principal, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name); if (ret) { return ret; } diff --git a/source4/auth/kerberos/krb5_init_context.c b/source4/auth/kerberos/krb5_init_context.c index d895d7a336..a3ef895b16 100644 --- a/source4/auth/kerberos/krb5_init_context.c +++ b/source4/auth/kerberos/krb5_init_context.c @@ -23,6 +23,7 @@ #include "includes.h" #include "system/kerberos.h" +#include "heimdal/lib/krb5/krb5_locl.h" #include "auth/kerberos/kerberos.h" #include "lib/socket/socket.h" #include "system/network.h" @@ -69,7 +70,7 @@ static void smb_krb5_debug_close(void *private) { static void smb_krb5_debug_wrapper(const char *timestr, const char *msg, void *private) { - DEBUG(3, ("Kerberos: %s\n", msg)); + DEBUG(2, ("Kerberos: %s\n", msg)); } /* @@ -224,11 +225,11 @@ static void smb_krb5_socket_handler(struct event_context *ev, struct fd_event *f } -static krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, - void *data, - krb5_krbhst_info *hi, - const krb5_data *send_buf, - krb5_data *recv_buf) +krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, + void *data, + krb5_krbhst_info *hi, + const krb5_data *send_buf, + krb5_data *recv_buf) { krb5_error_code ret; NTSTATUS status; @@ -363,13 +364,6 @@ static krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, return KRB5_KDC_UNREACH; } -/* NO internal data, so nothing to free */ -static void smb_krb5_send_and_recv_close_func(krb5_context context, void *data) -{ - return; -} - - krb5_error_code smb_krb5_init_context(void *parent_ctx, struct smb_krb5_context **smb_krb5_context) { @@ -437,9 +431,9 @@ krb5_error_code smb_krb5_init_context(void *parent_ctx, ev = event_context_find(*smb_krb5_context); /* Set use of our socket lib */ - ret = krb5_set_send_recv_func((*smb_krb5_context)->krb5_context, - smb_krb5_send_and_recv_func, - smb_krb5_send_and_recv_close_func, ev); + ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context, + smb_krb5_send_and_recv_func, + ev); if (ret) { DEBUG(1,("krb5_set_send_recv_func failed (%s)\n", smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); @@ -454,12 +448,8 @@ krb5_error_code smb_krb5_init_context(void *parent_ctx, /* Set options in kerberos */ - (*smb_krb5_context)->krb5_context->fdns = FALSE; + krb5_set_dns_canonicalize_hostname((*smb_krb5_context)->krb5_context, FALSE); return 0; } - void smb_krb5_free_context(struct smb_krb5_context *smb_krb5_context) -{ - talloc_free(smb_krb5_context); -} diff --git a/source4/auth/kerberos/krb5_init_context.h b/source4/auth/kerberos/krb5_init_context.h index f3ffc067fa..7aad97e2ca 100644 --- a/source4/auth/kerberos/krb5_init_context.h +++ b/source4/auth/kerberos/krb5_init_context.h @@ -27,3 +27,8 @@ krb5_error_code smb_krb5_init_context(void *parent_ctx, struct smb_krb5_context **smb_krb5_context); void smb_krb5_free_context(struct smb_krb5_context *smb_krb5_context); +krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, + void *data, + krb5_krbhst_info *hi, + const krb5_data *send_buf, + krb5_data *recv_buf); |