summaryrefslogtreecommitdiff
path: root/source4/libcli/auth/gensec_krb5.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-03-24 04:14:06 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:11:15 -0500
commit2eb3d680625286431a3a60e37b75f47e0738f253 (patch)
tree80a6731efbcb4913d691b414d162d700d4f9059e /source4/libcli/auth/gensec_krb5.c
parent46b22b073cf0d0c93f2e70dd4d670dc373d5a26a (diff)
downloadsamba-2eb3d680625286431a3a60e37b75f47e0738f253.tar.gz
samba-2eb3d680625286431a3a60e37b75f47e0738f253.tar.bz2
samba-2eb3d680625286431a3a60e37b75f47e0738f253.zip
r6028: A MAJOR update to intergrate the new credentails system fully with
GENSEC, and to pull SCHANNEL into GENSEC, by making it less 'special'. GENSEC now no longer has it's own handling of 'set username' etc, instead it uses cli_credentials calls. In order to link the credentails code right though Samba, a lot of interfaces have changed to remove 'username, domain, password' arguments, and these have been replaced with a single 'struct cli_credentials'. In the session setup code, a new parameter 'workgroup' contains the client/server current workgroup, which seems unrelated to the authentication exchange (it was being filled in from the auth info). This allows in particular kerberos to only call back for passwords when it actually needs to perform the kinit. The kerberos code has been modified not to use the SPNEGO provided 'principal name' (in the mechListMIC), but to instead use the name the host was connected to as. This better matches Microsoft behaviour, is more secure and allows better use of standard kerberos functions. To achieve this, I made changes to our socket code so that the hostname (before name resolution) is now recorded on the socket. In schannel, most of the code from librpc/rpc/dcerpc_schannel.c is now in libcli/auth/schannel.c, and it looks much more like a standard GENSEC module. The actual sign/seal code moved to libcli/auth/schannel_sign.c in a previous commit. The schannel credentails structure is now merged with the rest of the credentails, as many of the values (username, workstation, domain) where already present there. This makes handling this in a generic manner much easier, as there is no longer a custom entry-point. The auth_domain module continues to be developed, but is now just as functional as auth_winbind. The changes here are consequential to the schannel changes. The only removed function at this point is the RPC-LOGIN test (simulating the load of a WinXP login), which needs much more work to clean it up (it contains copies of too much code from all over the torture suite, and I havn't been able to penetrate its 'structure'). Andrew Bartlett (This used to be commit 2301a4b38a21aa60917973451687063d83d18d66)
Diffstat (limited to 'source4/libcli/auth/gensec_krb5.c')
-rw-r--r--source4/libcli/auth/gensec_krb5.c57
1 files changed, 30 insertions, 27 deletions
diff --git a/source4/libcli/auth/gensec_krb5.c b/source4/libcli/auth/gensec_krb5.c
index 71670632b9..453485d816 100644
--- a/source4/libcli/auth/gensec_krb5.c
+++ b/source4/libcli/auth/gensec_krb5.c
@@ -320,7 +320,12 @@ 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 *hostname = gensec_get_target_hostname(gensec_security);
+ if (!hostname) {
+ DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
nt_status = gensec_krb5_start(gensec_security);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
@@ -341,22 +346,8 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
}
while (1) {
- if (gensec_security->target.principal) {
- DEBUG(5, ("Finding ticket for target [%s]\n", gensec_security->target.principal));
- ret = ads_krb5_mk_req(gensec_krb5_state->context,
- &gensec_krb5_state->auth_context,
- AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED,
- gensec_security->target.principal,
- gensec_krb5_state->ccache,
- &gensec_krb5_state->ticket);
- } else {
+ {
krb5_data in_data;
- const char *hostname = gensec_get_target_hostname(gensec_security);
- if (!hostname) {
- DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
in_data.length = 0;
ret = krb5_mk_req(gensec_krb5_state->context,
@@ -372,36 +363,40 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
case 0:
return NT_STATUS_OK;
case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
- DEBUG(3, ("Server is not registered with our KDC: %s\n",
- error_message(ret)));
+ DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n",
+ hostname, error_message(ret)));
return NT_STATUS_ACCESS_DENIED;
case KRB5KDC_ERR_PREAUTH_FAILED:
case KRB5KRB_AP_ERR_TKT_EXPIRED:
case KRB5_CC_END:
+ /* Too much clock skew - we will need to kinit to re-skew the clock */
+ case KRB5KRB_AP_ERR_SKEW:
+ case KRB5_KDCREP_SKEW:
{
DEBUG(3, ("kerberos (mk_req) failed: %s\n",
error_message(ret)));
/* fall down to remaining code */
}
+
+
/* just don't print a message for these really ordinary messages */
case KRB5_FCC_NOFILE:
case KRB5_CC_NOTFOUND:
case ENOENT:
+
{
- char *password;
+ const char *password;
char *ccache_string;
time_t kdc_time = 0;
- nt_status = gensec_get_password(gensec_security,
- gensec_security,
- &password);
+ 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",
- gensec_get_client_principal(gensec_security, gensec_krb5_state),
- gensec_get_target_principal(gensec_security),
+ 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);
@@ -413,8 +408,8 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
}
ret = kerberos_kinit_password_cc(gensec_krb5_state->context, gensec_krb5_state->ccache,
- gensec_get_client_principal(gensec_security, gensec_krb5_state),
- password, NULL, &kdc_time);
+ 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)) {
@@ -422,10 +417,18 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
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 failed (%s)\n",
+ 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;
}