diff options
Diffstat (limited to 'source4/auth/kerberos')
-rw-r--r-- | source4/auth/kerberos/clikrb5.c | 100 | ||||
-rw-r--r-- | source4/auth/kerberos/config.m4 | 3 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos.h | 16 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos_util.c | 22 |
4 files changed, 124 insertions, 17 deletions
diff --git a/source4/auth/kerberos/clikrb5.c b/source4/auth/kerberos/clikrb5.c index ec8f60fbb3..dc02cf7b01 100644 --- a/source4/auth/kerberos/clikrb5.c +++ b/source4/auth/kerberos/clikrb5.c @@ -3,6 +3,7 @@ simple kerberos5 routines for active directory Copyright (C) Andrew Tridgell 2001 Copyright (C) Luke Howard 2002-2003 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 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 @@ -475,4 +476,103 @@ cleanup_princ: return ret; } + +static int smb_krb5_context_destory_1(void *ptr) +{ + struct smb_krb5_context *ctx = ptr; + krb5_free_context(ctx->krb5_context); + return 0; +} + +#if defined(HAVE_KRB5_INITLOG) && defined(HAVE_KRB5_ADDLOG_FUNC) && defined(HAVE_KRB5_FREELOG) +static int smb_krb5_context_destory_2(void *ptr) +{ + struct smb_krb5_context *ctx = ptr; + + /* Otherwise krb5_free_context will try and close what we have already free()ed */ + krb5_set_warn_dest(ctx->krb5_context, NULL); + krb5_freelog(ctx->krb5_context, ctx->logf); + smb_krb5_context_destory_1(ptr); + return 0; +} + +/* We never close down the DEBUG system, and no need to unreference the use */ +static void smb_krb5_debug_close(void *private) { + return; +} + +static void smb_krb5_debug_wrapper(const char *timestr, const char *msg, void *private) +{ + DEBUG(3, ("Kerberos: %s\n", msg)); +} + +#endif + + krb5_error_code smb_krb5_init_context(TALLOC_CTX *parent_ctx, + struct smb_krb5_context **smb_krb5_context) +{ + krb5_error_code ret; + TALLOC_CTX *tmp_ctx; + + *smb_krb5_context = talloc(parent_ctx, struct smb_krb5_context); + tmp_ctx = talloc_new(*smb_krb5_context); + + if (!*smb_krb5_context || !tmp_ctx) { + talloc_free(*smb_krb5_context); + talloc_free(tmp_ctx); + return ENOMEM; + } + + ret = krb5_init_context(&(*smb_krb5_context)->krb5_context); + if (ret) { + DEBUG(1,("krb5_init_context failed (%s)\n", + error_message(ret))); + return ret; + } + + talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destory_1); + + if (lp_realm() && *lp_realm()) { + char *upper_realm = strupper_talloc(tmp_ctx, lp_realm()); + if (!upper_realm) { + DEBUG(1,("gensec_krb5_start: could not uppercase realm: %s\n", lp_realm())); + return ENOMEM; + } + ret = krb5_set_default_realm((*smb_krb5_context)->krb5_context, lp_realm()); + if (ret) { + DEBUG(1,("krb5_set_default_realm failed (%s)\n", + smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); + talloc_free(*smb_krb5_context); + return ret; + } + } + +#if defined(HAVE_KRB5_INITLOG) && defined(HAVE_KRB5_ADDLOG_FUNC) && defined(HAVE_KRB5_FREELOG) + /* TODO: Should we have a different name here? */ + ret = krb5_initlog((*smb_krb5_context)->krb5_context, "Samba", &(*smb_krb5_context)->logf); + + if (ret) { + DEBUG(1,("krb5_initlog failed (%s)\n", + smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); + talloc_free(*smb_krb5_context); + return ret; + } + + talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destory_2); + + ret = krb5_addlog_func((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf, 0 /* min */, -1 /* max */, + smb_krb5_debug_wrapper, smb_krb5_debug_close, NULL); + if (ret) { + DEBUG(1,("krb5_addlog_func failed (%s)\n", + smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); + talloc_free(*smb_krb5_context); + return ret; + } + krb5_set_warn_dest((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf); + +#endif + talloc_free(tmp_ctx); + return 0; +} + #endif diff --git a/source4/auth/kerberos/config.m4 b/source4/auth/kerberos/config.m4 index 9cb66554ca..010a1c85da 100644 --- a/source4/auth/kerberos/config.m4 +++ b/source4/auth/kerberos/config.m4 @@ -260,6 +260,9 @@ if test x"$with_krb5_support" != x"no"; then AC_CHECK_FUNC_EXT(krb5_enctypes_compatible_keys, $KRB5_LIBS) AC_CHECK_FUNC_EXT(krb5_get_error_string, $KRB5_LIBS) AC_CHECK_FUNC_EXT(krb5_free_error_string, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_initlog, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_freelog, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_addlog_func, $KRB5_LIBS) LIBS="$LIBS $KRB5_LIBS" diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h index ec7df4c2f1..b65416e619 100644 --- a/source4/auth/kerberos/kerberos.h +++ b/source4/auth/kerberos/kerberos.h @@ -21,6 +21,12 @@ #if defined(HAVE_KRB5) +struct smb_krb5_context { + krb5_context krb5_context; + krb5_log_facility *logf; +}; + + /* not really ASN.1, but RFC 1964 */ #define TOK_ID_KRB_AP_REQ "\x01\x00" #define TOK_ID_KRB_AP_REP "\x02\x00" @@ -96,9 +102,11 @@ void kerberos_free_data_contents(krb5_context context, krb5_data *pdata); krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry); char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx); NTSTATUS kinit_to_ccache(TALLOC_CTX *parent_ctx, - struct cli_credentials *credentials, - krb5_context context, - krb5_ccache *ccache, - const char **ccache_name); + struct cli_credentials *credentials, + struct smb_krb5_context *smb_krb5_context, + krb5_ccache *ccache, + const char **ccache_name); +krb5_error_code smb_krb5_init_context(TALLOC_CTX *parent_ctx, + struct smb_krb5_context **smb_krb5_context); #endif /* HAVE_KRB5 */ diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c index 55975b2594..7945094be9 100644 --- a/source4/auth/kerberos/kerberos_util.c +++ b/source4/auth/kerberos/kerberos_util.c @@ -29,19 +29,17 @@ #include "auth/auth.h" struct ccache_container { - krb5_context krb5_context; + struct smb_krb5_context *smb_krb5_context; krb5_ccache ccache; } ccache_container; -#if 0 static int free_ccache(void *ptr) { struct ccache_container *ccc = ptr; /* current heimdal - 0.6.3, which we need anyway, fixes segfaults here */ - krb5_cc_close(ccc->krb5_context, ccc->ccache); + krb5_cc_close(ccc->smb_krb5_context->krb5_context, ccc->ccache); return 0; } -#endif /** * Return a freshly allocated ccache (destroyed by destructor on child @@ -50,7 +48,7 @@ static int free_ccache(void *ptr) { NTSTATUS kinit_to_ccache(TALLOC_CTX *parent_ctx, struct cli_credentials *credentials, - krb5_context context, + struct smb_krb5_context *smb_krb5_context, krb5_ccache *ccache, const char **ccache_name) { @@ -71,7 +69,7 @@ static int free_ccache(void *ptr) { cli_credentials_get_principal(credentials, mem_ctx), generate_random_str(mem_ctx, 16)); - ret = krb5_cc_resolve(context, ccache_string, ccache); + ret = krb5_cc_resolve(smb_krb5_context->krb5_context, ccache_string, ccache); if (ret) { DEBUG(1,("failed to generate a new krb5 keytab (%s): %s\n", ccache_string, @@ -80,13 +78,11 @@ static int free_ccache(void *ptr) { return NT_STATUS_INTERNAL_ERROR; } - mem_ctx->krb5_context = context; + mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context); mem_ctx->ccache = *ccache; -#if 0 talloc_set_destructor(mem_ctx, free_ccache); -#endif - ret = kerberos_kinit_password_cc(context, *ccache, + ret = kerberos_kinit_password_cc(smb_krb5_context->krb5_context, *ccache, cli_credentials_get_principal(credentials, mem_ctx), password, NULL, &kdc_time); @@ -95,13 +91,13 @@ static int free_ccache(void *ptr) { time_t t = time(NULL); int time_offset =(unsigned)kdc_time-t; DEBUG(4,("Advancing clock by %d seconds to cope with clock skew\n", time_offset)); - krb5_set_real_time(context, t + time_offset + 1, 0); + krb5_set_real_time(smb_krb5_context->krb5_context, t + time_offset + 1, 0); } if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) { DEBUG(1,("kinit for %s failed (%s)\n", cli_credentials_get_principal(credentials, mem_ctx), - smb_get_krb5_error_message(context, + smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx))); talloc_free(mem_ctx); return NT_STATUS_TIME_DIFFERENCE_AT_DC; @@ -109,7 +105,7 @@ static int free_ccache(void *ptr) { if (ret) { DEBUG(1,("kinit for %s failed (%s)\n", cli_credentials_get_principal(credentials, mem_ctx), - smb_get_krb5_error_message(context, + smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx))); talloc_free(mem_ctx); return NT_STATUS_WRONG_PASSWORD; |