{
struct gensec_gssapi_state *gensec_gssapi_state;
krb5_error_code ret;
- struct gsskrb5_send_to_kdc send_to_kdc;
const char *realm;
- gensec_gssapi_state = talloc(gensec_security, struct gensec_gssapi_state);
+ gensec_gssapi_state = talloc_zero(gensec_security, struct gensec_gssapi_state);
if (!gensec_gssapi_state) {
return NT_STATUS_NO_MEMORY;
}
gensec_gssapi_state->pac = data_blob(NULL, 0);
ret = smb_krb5_init_context(gensec_gssapi_state,
- gensec_security->event_ctx,
+ NULL,
gensec_security->settings->lp_ctx,
&gensec_gssapi_state->smb_krb5_context);
if (ret) {
talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destructor);
- 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"));
- talloc_free(gensec_gssapi_state);
- return NT_STATUS_INTERNAL_ERROR;
- }
-
realm = lpcfg_realm(gensec_security->settings->lp_ctx);
if (realm != NULL) {
ret = gsskrb5_set_default_realm(realm);
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
} else {
ret = cli_credentials_get_server_gss_creds(machine_account,
- gensec_security->event_ctx,
gensec_security->settings->lp_ctx, &gcc);
if (ret) {
DEBUG(1, ("Aquiring acceptor credentials failed: %s\n",
gss_OID name_type;
OM_uint32 maj_stat, min_stat;
const char *hostname = gensec_get_target_hostname(gensec_security);
- const char *principal;
struct gssapi_creds_container *gcc;
const char *error_string;
gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
- principal = gensec_get_target_principal(gensec_security);
- if (principal && lpcfg_client_use_spnego_principal(gensec_security->settings->lp_ctx)) {
+ gensec_gssapi_state->target_principal = gensec_get_target_principal(gensec_security);
+ if (gensec_gssapi_state->target_principal) {
name_type = GSS_C_NULL_OID;
} else {
- principal = talloc_asprintf(gensec_gssapi_state, "%s/%s@%s",
+ gensec_gssapi_state->target_principal = talloc_asprintf(gensec_gssapi_state, "%s/%s@%s",
gensec_get_target_service(gensec_security),
hostname, lpcfg_realm(gensec_security->settings->lp_ctx));
name_type = GSS_C_NT_USER_NAME;
- }
- name_token.value = discard_const_p(uint8_t, principal);
- name_token.length = strlen(principal);
+ }
+ name_token.value = discard_const_p(uint8_t, gensec_gssapi_state->target_principal);
+ name_token.length = strlen(gensec_gssapi_state->target_principal);
maj_stat = gss_import_name (&min_stat,
case 0:
break;
case KRB5KDC_ERR_PREAUTH_FAILED:
+ case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
+ DEBUG(1, ("Wrong username or password: %s\n", error_string));
return NT_STATUS_LOGON_FAILURE;
case KRB5_KDC_UNREACH:
- DEBUG(3, ("Cannot reach a KDC we require to contact %s : %s\n", principal, error_string));
- return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
+ DEBUG(3, ("Cannot reach a KDC we require to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
+ return NT_STATUS_NO_LOGON_SERVERS;
case KRB5_CC_NOTFOUND:
case KRB5_CC_END:
- DEBUG(3, ("Error preparing credentials we require to contact %s : %s\n", principal, error_string));
- return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
+ DEBUG(2, ("Error obtaining ticket we require to contact %s: (possibly due to clock skew between us and the KDC) %s\n", gensec_gssapi_state->target_principal, error_string));
+ return NT_STATUS_TIME_DIFFERENCE_AT_DC;
default:
DEBUG(1, ("Aquiring initiator credentials failed: %s\n", error_string));
return NT_STATUS_UNSUCCESSFUL;
switch (gensec_security->gensec_role) {
case GENSEC_CLIENT:
{
+ struct gsskrb5_send_to_kdc send_to_kdc;
+ krb5_error_code ret;
+ send_to_kdc.func = smb_krb5_send_and_recv_func;
+ send_to_kdc.ptr = gensec_security->event_ctx;
+
+ min_stat = gsskrb5_set_send_to_kdc(&send_to_kdc);
+ if (min_stat) {
+ DEBUG(1,("gensec_krb5_start: gsskrb5_set_send_to_kdc failed\n"));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
maj_stat = gss_init_sec_context(&min_stat,
gensec_gssapi_state->client_cred->creds,
&gensec_gssapi_state->gssapi_context,
if (gss_oid_p) {
gensec_gssapi_state->gss_oid = gss_oid_p;
}
+
+ send_to_kdc.func = smb_krb5_send_and_recv_func;
+ send_to_kdc.ptr = NULL;
+
+ 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;
+ }
+
break;
}
case GENSEC_SERVER:
gensec_gssapi_state->sasl_state = STAGE_DONE;
if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
- DEBUG(5, ("GSSAPI Connection will be cryptographicly sealed\n"));
+ DEBUG(5, ("GSSAPI Connection will be cryptographically sealed\n"));
} else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
- DEBUG(5, ("GSSAPI Connection will be cryptographicly signed\n"));
+ DEBUG(5, ("GSSAPI Connection will be cryptographically signed\n"));
} else {
DEBUG(5, ("GSSAPI Connection will have no cryptographic protection\n"));
}
return NT_STATUS_MORE_PROCESSING_REQUIRED;
} else if (gss_oid_equal(gensec_gssapi_state->gss_oid, gss_mech_krb5)) {
switch (min_stat) {
+ case KRB5KRB_AP_ERR_TKT_NYV:
+ DEBUG(1, ("Error with ticket to contact %s: possible clock skew between us and the KDC or target server: %s\n",
+ gensec_gssapi_state->target_principal,
+ gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
+ return NT_STATUS_TIME_DIFFERENCE_AT_DC; /* Make SPNEGO ignore us, we can't go any further here */
+ case KRB5KRB_AP_ERR_TKT_EXPIRED:
+ DEBUG(1, ("Error with ticket to contact %s: ticket is expired, possible clock skew between us and the KDC or target server: %s\n",
+ gensec_gssapi_state->target_principal,
+ gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
+ return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
case KRB5_KDC_UNREACH:
- DEBUG(3, ("Cannot reach a KDC we require: %s\n",
+ DEBUG(3, ("Cannot reach a KDC we require in order to obtain a ticetk to %s: %s\n",
+ gensec_gssapi_state->target_principal,
gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
- return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
+ return NT_STATUS_NO_LOGON_SERVERS; /* Make SPNEGO ignore us, we can't go any further here */
case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
- DEBUG(3, ("Server is not registered with our KDC: %s\n",
+ DEBUG(3, ("Server %s is not registered with our KDC: %s\n",
+ gensec_gssapi_state->target_principal,
gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
case KRB5KRB_AP_ERR_MSG_TYPE:
/* garbage input, possibly from the auto-mech detection */
return NT_STATUS_INVALID_PARAMETER;
default:
- DEBUG(1, ("GSS Update(krb5)(%d) Update failed: %s\n",
+ DEBUG(1, ("GSS %s Update(krb5)(%d) Update failed: %s\n",
+ gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
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(%d) failed: %s\n",
+ DEBUG(1, ("GSS %s Update(%d) failed: %s\n",
+ gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
gensec_gssapi_state->gss_exchange_count,
gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
return nt_status;
gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_proposed, 0),
gensec_gssapi_state->max_wrap_buf_size);
gensec_gssapi_state->sasl_protection = 0;
- if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
- if (security_supported & NEG_SEAL) {
+ if (security_supported & NEG_SEAL) {
+ if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
gensec_gssapi_state->sasl_protection |= NEG_SEAL;
}
- } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
- if (security_supported & NEG_SIGN) {
+ }
+ if (security_supported & NEG_SIGN) {
+ if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
gensec_gssapi_state->sasl_protection |= NEG_SIGN;
}
- } else if (security_supported & NEG_NONE) {
+ }
+ if (security_supported & NEG_NONE) {
gensec_gssapi_state->sasl_protection |= NEG_NONE;
- } else {
- DEBUG(1, ("Remote server does not support unprotected connections"));
+ }
+ if (gensec_gssapi_state->sasl_protection == 0) {
+ DEBUG(1, ("Remote server does not support unprotected connections\n"));
return NT_STATUS_ACCESS_DENIED;
}
gensec_gssapi_state->sasl_state = STAGE_DONE;
if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
- DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographicly sealed\n"));
+ DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically sealed\n"));
} else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
- DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographicly signed\n"));
+ DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically signed\n"));
} else {
- DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographicly protection\n"));
+ DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographically protection\n"));
}
return NT_STATUS_OK;
/* first byte is the proposed security */
security_accepted = maxlength_accepted[0];
maxlength_accepted[0] = '\0';
-
+
/* Rest is the proposed max wrap length */
gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_accepted, 0),
gensec_gssapi_state->max_wrap_buf_size);
gensec_gssapi_state->sasl_protection = 0;
- if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
- if (security_accepted & NEG_SEAL) {
- gensec_gssapi_state->sasl_protection |= NEG_SEAL;
+ if (security_accepted & NEG_SEAL) {
+ if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
+ DEBUG(1, ("Remote client wanted seal, but gensec refused\n"));
+ return NT_STATUS_ACCESS_DENIED;
}
- } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
- if (security_accepted & NEG_SIGN) {
- gensec_gssapi_state->sasl_protection |= NEG_SIGN;
+ gensec_gssapi_state->sasl_protection |= NEG_SEAL;
+ }
+ if (security_accepted & NEG_SIGN) {
+ if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
+ DEBUG(1, ("Remote client wanted sign, but gensec refused\n"));
+ return NT_STATUS_ACCESS_DENIED;
}
- } else if (security_accepted & NEG_NONE) {
+ gensec_gssapi_state->sasl_protection |= NEG_SIGN;
+ }
+ if (security_accepted & NEG_NONE) {
gensec_gssapi_state->sasl_protection |= NEG_NONE;
- } else {
- DEBUG(1, ("Remote client does not support unprotected connections, but we failed to negotiate anything better"));
- return NT_STATUS_ACCESS_DENIED;
}
/* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
gensec_gssapi_state->sasl_state = STAGE_DONE;
if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
- DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographicly sealed\n"));
+ DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically sealed\n"));
} else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
- DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographicly signed\n"));
+ DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically signed\n"));
} else {
DEBUG(5, ("SASL/GSSAPI Connection from client will have no cryptographic protection\n"));
}
cli_credentials_set_anonymous(session_info->credentials);
ret = cli_credentials_set_client_gss_creds(session_info->credentials,
- gensec_security->event_ctx,
gensec_security->settings->lp_ctx,
gensec_gssapi_state->delegated_cred_handle,
CRED_SPECIFIED, &error_string);