summaryrefslogtreecommitdiff
path: root/source4/auth/gensec/gensec_krb5.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-05-15 23:42:11 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:16:45 -0500
commit5c6dd5e800b879efdce3bbc3a16f32c5e78b4917 (patch)
tree13a8286bebac583bd979d278b7f12fac25c8513b /source4/auth/gensec/gensec_krb5.c
parent8f96c42027d282eec047d1b25951a33bc2fce71f (diff)
downloadsamba-5c6dd5e800b879efdce3bbc3a16f32c5e78b4917.tar.gz
samba-5c6dd5e800b879efdce3bbc3a16f32c5e78b4917.tar.bz2
samba-5c6dd5e800b879efdce3bbc3a16f32c5e78b4917.zip
r6800: A big GENSEC update:
Finally remove the distinction between 'krb5' and 'ms_krb5'. We now don't do kerberos stuff twice on failure. The solution to this is slightly more general than perhaps was really required (as this is a special case), but it works, and I'm happy with the cleanup I achived in the process. All modules have been updated to supply a NULL-terminated list of OIDs. In that process, SPNEGO code has been generalised, as I realised that two of the functions should have been identical in behaviour. Over in the actual modules, I have worked to remove the 'kinit' code from gensec_krb5, and placed it in kerberos/kerberos_util.c. The GSSAPI module has been extended to use this, so no longer requires a manual kinit at the command line. It will soon loose the requirement for a on-disk keytab too. The general kerberos code has also been updated to move from error_message() to our routine which gets the Heimdal error string (which may be much more useful) when available. Andrew Bartlett (This used to be commit 0101728d8e2ed9419eb31fe95047944a718ba135)
Diffstat (limited to 'source4/auth/gensec/gensec_krb5.c')
-rw-r--r--source4/auth/gensec/gensec_krb5.c131
1 files changed, 42 insertions, 89 deletions
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index c850d93fce..9e2d113cb8 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -53,9 +53,9 @@ struct gensec_krb5_state {
#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)
+ struct PAC_SIGNATURE_DATA *sig,
+ struct gensec_krb5_state *gensec_krb5_state,
+ uint32 keyusage)
{
krb5_error_code ret;
krb5_crypto crypto;
@@ -222,7 +222,9 @@ static NTSTATUS gensec_krb5_decode_pac(TALLOC_CTX *mem_ctx,
return status;
}
#endif
- DEBUG(0,("account_name: %s [%s]\n",logon_info->info3.base.account_name.string, logon_info->info3.base.full_name.string));
+ 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;
@@ -233,12 +235,10 @@ static int gensec_krb5_destory(void *ptr)
struct gensec_krb5_state *gensec_krb5_state = ptr;
if (gensec_krb5_state->ticket.length) {
- kerberos_free_data_contents(gensec_krb5_state->context, &gensec_krb5_state->ticket);
- }
- if (gensec_krb5_state->ccache) {
- /* current heimdal - 0.6.3, which we need anyway, fixes segfaults here */
- krb5_cc_close(gensec_krb5_state->context, gensec_krb5_state->ccache);
+ kerberos_free_data_contents(gensec_krb5_state->context,
+ &gensec_krb5_state->ticket);
}
+ /* ccache freed in a child destructor */
krb5_free_keyblock_contents(gensec_krb5_state->context,
&gensec_krb5_state->keyblock);
@@ -279,7 +279,9 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
ret = krb5_init_context(&gensec_krb5_state->context);
if (ret) {
- DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n", error_message(ret)));
+ DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n",
+ smb_get_krb5_error_message(gensec_krb5_state->context,
+ ret, gensec_krb5_state)));
return NT_STATUS_INTERNAL_ERROR;
}
@@ -291,14 +293,18 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
}
ret = krb5_set_default_realm(gensec_krb5_state->context, upper_realm);
if (ret) {
- DEBUG(1,("gensec_krb5_start: krb5_set_default_realm failed (%s)\n", error_message(ret)));
+ DEBUG(1,("gensec_krb5_start: krb5_set_default_realm failed (%s)\n",
+ smb_get_krb5_error_message(gensec_krb5_state->context,
+ ret, gensec_krb5_state)));
return NT_STATUS_INTERNAL_ERROR;
}
}
ret = krb5_auth_con_init(gensec_krb5_state->context, &gensec_krb5_state->auth_context);
if (ret) {
- DEBUG(1,("gensec_krb5_start: krb5_auth_con_init failed (%s)\n", error_message(ret)));
+ DEBUG(1,("gensec_krb5_start: krb5_auth_con_init failed (%s)\n",
+ smb_get_krb5_error_message(gensec_krb5_state->context,
+ ret, gensec_krb5_state)));
return NT_STATUS_INTERNAL_ERROR;
}
@@ -326,6 +332,8 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
struct gensec_krb5_state *gensec_krb5_state;
krb5_error_code ret;
NTSTATUS nt_status;
+ const char *ccache_name;
+
const char *hostname = gensec_get_target_hostname(gensec_security);
if (!hostname) {
DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
@@ -347,7 +355,7 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
ret = krb5_cc_default(gensec_krb5_state->context, &gensec_krb5_state->ccache);
if (ret) {
DEBUG(1,("krb5_cc_default failed (%s)\n",
- error_message(ret)));
+ smb_get_krb5_error_message(gensec_krb5_state->context, ret, gensec_krb5_state)));
return NT_STATUS_INTERNAL_ERROR;
}
@@ -370,7 +378,7 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
return NT_STATUS_OK;
case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n",
- hostname, error_message(ret)));
+ hostname, smb_get_krb5_error_message(gensec_krb5_state->context, ret, gensec_krb5_state)));
return NT_STATUS_ACCESS_DENIED;
case KRB5KDC_ERR_PREAUTH_FAILED:
case KRB5KRB_AP_ERR_TKT_EXPIRED:
@@ -380,7 +388,7 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
case KRB5_KDCREP_SKEW:
{
DEBUG(3, ("kerberos (mk_req) failed: %s\n",
- error_message(ret)));
+ smb_get_krb5_error_message(gensec_krb5_state->context, ret, gensec_krb5_state)));
/* fall down to remaining code */
}
@@ -390,59 +398,20 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
case KRB5_CC_NOTFOUND:
case ENOENT:
- {
- const char *password;
- char *ccache_string;
- time_t kdc_time = 0;
- password = cli_credentials_get_password(gensec_security->credentials);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- }
-
- /* this string should be unique */
- ccache_string = talloc_asprintf(gensec_krb5_state, "MEMORY:%s:%s:%s",
- cli_credentials_get_principal(gensec_security->credentials, gensec_krb5_state),
- gensec_get_target_hostname(gensec_security),
- generate_random_str(gensec_krb5_state, 16));
-
- ret = krb5_cc_resolve(gensec_krb5_state->context, ccache_string, &gensec_krb5_state->ccache);
- if (ret) {
- DEBUG(1,("failed to generate a new krb5 keytab (%s): %s\n",
- ccache_string,
- error_message(ret)));
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- ret = kerberos_kinit_password_cc(gensec_krb5_state->context, gensec_krb5_state->ccache,
- cli_credentials_get_principal(gensec_security->credentials, gensec_krb5_state),
- password, NULL, &kdc_time);
-
- /* cope with ticket being in the future due to clock skew */
- if ((unsigned)kdc_time > time(NULL)) {
- 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(gensec_krb5_state->context, t + time_offset + 1, 0);
- break;
- }
-
- if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
- DEBUG(1,("kinit for %s failed (%s)\n",
- cli_credentials_get_principal(gensec_security->credentials, gensec_krb5_state),
- error_message(ret)));
- return NT_STATUS_TIME_DIFFERENCE_AT_DC;
- }
- if (ret) {
- DEBUG(1,("kinit for %s failed (%s)\n",
- cli_credentials_get_principal(gensec_security->credentials, gensec_krb5_state),
- error_message(ret)));
- return NT_STATUS_WRONG_PASSWORD;
- }
- break;
+ nt_status = kinit_to_ccache(gensec_krb5_state,
+ gensec_security->credentials,
+ gensec_krb5_state->context,
+ &gensec_krb5_state->ccache,
+ &ccache_name);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
}
+ break;
+
default:
DEBUG(0, ("kerberos: %s\n",
- error_message(ret)));
+ smb_get_krb5_error_message(gensec_krb5_state->context, ret, gensec_krb5_state)));
return NT_STATUS_UNSUCCESSFUL;
}
}
@@ -474,7 +443,7 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
{
if (ret) {
DEBUG(1,("ads_krb5_mk_req (request ticket) failed (%s)\n",
- error_message(ret)));
+ smb_get_krb5_error_message(gensec_krb5_state->context, ret, out_mem_ctx)));
nt_status = NT_STATUS_LOGON_FAILURE;
} else {
DATA_BLOB unwrapped_out;
@@ -515,7 +484,7 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
&inbuf, &repl);
if (ret) {
DEBUG(1,("krb5_rd_rep (mutual authentication) failed (%s)\n",
- error_message(ret)));
+ smb_get_krb5_error_message(gensec_krb5_state->context, ret, out_mem_ctx)));
dump_data_pw("Mutual authentication message:\n", inbuf.data, inbuf.length);
nt_status = NT_STATUS_ACCESS_DENIED;
} else {
@@ -707,24 +676,16 @@ static BOOL gensec_krb5_have_feature(struct gensec_security *gensec_security,
return False;
}
+static const char *gensec_krb5_oids[] = {
+ GENSEC_OID_KERBEROS5,
+ GENSEC_OID_KERBEROS5_OLD,
+ NULL
+};
static const struct gensec_security_ops gensec_krb5_security_ops = {
.name = "krb5",
.auth_type = DCERPC_AUTH_TYPE_KRB5,
- .oid = GENSEC_OID_KERBEROS5,
- .client_start = gensec_krb5_client_start,
- .server_start = gensec_krb5_server_start,
- .update = gensec_krb5_update,
- .session_key = gensec_krb5_session_key,
- .session_info = gensec_krb5_session_info,
- .have_feature = gensec_krb5_have_feature,
- .enabled = False
-};
-
-static const struct gensec_security_ops gensec_ms_krb5_security_ops = {
- .name = "ms_krb5",
- .auth_type = DCERPC_AUTH_TYPE_KRB5,
- .oid = GENSEC_OID_KERBEROS5_OLD,
+ .oid = gensec_krb5_oids,
.client_start = gensec_krb5_client_start,
.server_start = gensec_krb5_server_start,
.update = gensec_krb5_update,
@@ -734,7 +695,6 @@ static const struct gensec_security_ops gensec_ms_krb5_security_ops = {
.enabled = False
};
-
NTSTATUS gensec_krb5_init(void)
{
NTSTATUS ret;
@@ -746,12 +706,5 @@ NTSTATUS gensec_krb5_init(void)
return ret;
}
- ret = gensec_register(&gensec_ms_krb5_security_ops);
- if (!NT_STATUS_IS_OK(ret)) {
- DEBUG(0,("Failed to register '%s' gensec backend!\n",
- gensec_krb5_security_ops.name));
- return ret;
- }
-
return ret;
}