* effectively checks this.
*/
if (krb5_realm_compare(context, in_cred->client, in_cred->server) &&
- data_eq(*in_cred->server->data[1], *in_cred->client->realm) {
- /* Attempted to rewrite local TGS. */
- return KRB5_KDCREP_MODIFIED;
- }
+ data_eq(*in_cred->server->data[1], *in_cred->client->realm)) {
+ /* Attempted to rewrite local TGS. */
+ return KRB5_KDCREP_MODIFIED;
+ }
#endif
- return 0;
- }
+ return 0;
+}
/* Return true if a TGS credential is for the client's local realm. */
- static inline int
- tgt_is_local_realm(krb5_creds *tgt)
- {
- return (tgt->server->length == 2
- && data_eq_string(tgt->server->data[0], KRB5_TGS_NAME)
- && data_eq(tgt->server->data[1], tgt->client->realm)
- && data_eq(tgt->server->realm, tgt->client->realm));
- }
+static inline int
+tgt_is_local_realm(krb5_creds *tgt)
+{
+ return (tgt->server->length == 2
+ && data_eq_string(tgt->server->data[0], KRB5_TGS_NAME)
+ && data_eq(tgt->server->data[1], tgt->client->realm)
+ && data_eq(tgt->server->realm, tgt->client->realm));
+}
- krb5_error_code
- krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt,
- krb5_flags kdcoptions, krb5_address *const *address,
- krb5_creds *in_cred, krb5_creds **out_cred)
- {
- return krb5_get_cred_via_tkt_ext (context, tkt,
- kdcoptions, address,
- NULL, in_cred, NULL, NULL,
- NULL, NULL, out_cred, NULL);
- }
+krb5_error_code
+krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt,
+ krb5_flags kdcoptions, krb5_address *const *address,
+ krb5_creds *in_cred, krb5_creds **out_cred)
+{
+ return krb5_get_cred_via_tkt_ext (context, tkt,
+ kdcoptions, address,
+ NULL, in_cred, NULL, NULL,
+ NULL, NULL, out_cred, NULL);
+}
- krb5_error_code
- krb5_get_cred_via_tkt_ext (krb5_context context, krb5_creds *tkt,
- krb5_flags kdcoptions, krb5_address *const *address,
- krb5_pa_data **in_padata,
- krb5_creds *in_cred,
- krb5_error_code (*pacb_fct)(krb5_context,
- krb5_keyblock *,
- krb5_kdc_req *,
- void *),
- void *pacb_data,
- krb5_pa_data ***out_padata,
- krb5_pa_data ***out_enc_padata,
- krb5_creds **out_cred,
- krb5_keyblock **out_subkey)
- {
- krb5_error_code retval;
- krb5_kdc_rep *dec_rep;
- krb5_error *err_reply;
- krb5_response tgsrep;
- krb5_enctype *enctypes = 0;
- krb5_keyblock *subkey = NULL;
- krb5_boolean s4u2self = FALSE, second_tkt;
+krb5_error_code
+krb5_get_cred_via_tkt_ext (krb5_context context, krb5_creds *tkt,
+ krb5_flags kdcoptions, krb5_address *const *address,
+ krb5_pa_data **in_padata,
+ krb5_creds *in_cred,
+ krb5_error_code (*pacb_fct)(krb5_context,
+ krb5_keyblock *,
+ krb5_kdc_req *,
+ void *),
+ void *pacb_data,
+ krb5_pa_data ***out_padata,
+ krb5_pa_data ***out_enc_padata,
+ krb5_creds **out_cred,
+ krb5_keyblock **out_subkey)
+{
+ krb5_error_code retval;
+ krb5_kdc_rep *dec_rep;
+ krb5_error *err_reply;
+ krb5_response tgsrep;
+ krb5_enctype *enctypes = 0;
+ krb5_keyblock *subkey = NULL;
+ krb5_boolean s4u2self = FALSE, second_tkt;
#ifdef DEBUG_REFERRALS
- printf("krb5_get_cred_via_tkt starting; referral flag is %s\n", kdcoptions&KDC_OPT_CANONICALIZE?"on":"off");
- krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt requested ticket", in_cred->server);
- krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt TGT in use", tkt->server);
+ printf("krb5_get_cred_via_tkt starting; referral flag is %s\n", kdcoptions&KDC_OPT_CANONICALIZE?"on":"off");
+ krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt requested ticket", in_cred->server);
+ krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt TGT in use", tkt->server);
#endif
- /* tkt->client must be equal to in_cred->client */
- if (!krb5_principal_compare(context, tkt->client, in_cred->client))
- return KRB5_PRINC_NOMATCH;
+ /* tkt->client must be equal to in_cred->client */
+ if (!krb5_principal_compare(context, tkt->client, in_cred->client))
+ return KRB5_PRINC_NOMATCH;
- if (!tkt->ticket.length)
- return KRB5_NO_TKT_SUPPLIED;
+ if (!tkt->ticket.length)
+ return KRB5_NO_TKT_SUPPLIED;
- second_tkt = ((kdcoptions & (KDC_OPT_ENC_TKT_IN_SKEY | KDC_OPT_CNAME_IN_ADDL_TKT)) != 0);
+ second_tkt = ((kdcoptions & (KDC_OPT_ENC_TKT_IN_SKEY | KDC_OPT_CNAME_IN_ADDL_TKT)) != 0);
- if (second_tkt && !in_cred->second_ticket.length)
- return(KRB5_NO_2ND_TKT);
+ if (second_tkt && !in_cred->second_ticket.length)
+ return(KRB5_NO_2ND_TKT);
- s4u2self = krb5int_find_pa_data(context, in_padata, KRB5_PADATA_S4U_X509_USER) ||
- krb5int_find_pa_data(context, in_padata, KRB5_PADATA_FOR_USER);
+ s4u2self = krb5int_find_pa_data(context, in_padata, KRB5_PADATA_S4U_X509_USER) ||
+ krb5int_find_pa_data(context, in_padata, KRB5_PADATA_FOR_USER);
- /* check if we have the right TGT */
- /* tkt->server must be equal to */
- /* krbtgt/realmof(cred->server)@realmof(tgt->server) */
+ /* check if we have the right TGT */
+ /* tkt->server must be equal to */
+ /* krbtgt/realmof(cred->server)@realmof(tgt->server) */
/*
{
krb5_principal tempprinc;
}
*/
- if (in_cred->keyblock.enctype) {
- enctypes = (krb5_enctype *) malloc(sizeof(krb5_enctype)*2);
- if (!enctypes)
- return ENOMEM;
- enctypes[0] = in_cred->keyblock.enctype;
- enctypes[1] = 0;
- }
+ if (in_cred->keyblock.enctype) {
+ enctypes = (krb5_enctype *) malloc(sizeof(krb5_enctype)*2);
+ if (!enctypes)
+ return ENOMEM;
+ enctypes[0] = in_cred->keyblock.enctype;
+ enctypes[1] = 0;
+ }
- retval = krb5int_send_tgs(context, kdcoptions, &in_cred->times, enctypes,
- in_cred->server, address, in_cred->authdata,
- in_padata,
- second_tkt ? &in_cred->second_ticket : NULL,
- tkt, pacb_fct, pacb_data, &tgsrep, &subkey);
- if (enctypes)
- free(enctypes);
- if (retval) {
+ retval = krb5int_send_tgs(context, kdcoptions, &in_cred->times, enctypes,
+ in_cred->server, address, in_cred->authdata,
+ in_padata,
+ second_tkt ? &in_cred->second_ticket : NULL,
+ tkt, pacb_fct, pacb_data, &tgsrep, &subkey);
+ if (enctypes)
+ free(enctypes);
+ if (retval) {
#ifdef DEBUG_REFERRALS
- printf("krb5_get_cred_via_tkt ending early after send_tgs with: %s\n",
- error_message(retval));
+ printf("krb5_get_cred_via_tkt ending early after send_tgs with: %s\n",
+ error_message(retval));
#endif
- return retval;
- }
+ return retval;
+ }
- switch (tgsrep.message_type) {
- case KRB5_TGS_REP:
- break;
- case KRB5_ERROR:
- default:
- if (krb5_is_krb_error(&tgsrep.response))
- retval = decode_krb5_error(&tgsrep.response, &err_reply);
- else
- retval = KRB5KRB_AP_ERR_MSG_TYPE;
-
- if (retval) /* neither proper reply nor error! */
- goto error_4;
-
- retval = (krb5_error_code) err_reply->error + ERROR_TABLE_BASE_krb5;
- if (err_reply->text.length > 0) {
+ switch (tgsrep.message_type) {
+ case KRB5_TGS_REP:
+ break;
+ case KRB5_ERROR:
+ default:
+ if (krb5_is_krb_error(&tgsrep.response))
+ retval = decode_krb5_error(&tgsrep.response, &err_reply);
+ else
+ retval = KRB5KRB_AP_ERR_MSG_TYPE;
+
+ if (retval) /* neither proper reply nor error! */
+ goto error_4;
+
+ retval = (krb5_error_code) err_reply->error + ERROR_TABLE_BASE_krb5;
+ if (err_reply->text.length > 0) {
#if 0
- const char *m;
+ const char *m;
#endif
- switch (err_reply->error) {
- case KRB_ERR_GENERIC:
- krb5_set_error_message(context, retval,
- "KDC returned error string: %.*s",
- err_reply->text.length,
- err_reply->text.data);
- break;
- case KDC_ERR_S_PRINCIPAL_UNKNOWN:
- {
- char *s_name;
- if (krb5_unparse_name(context, in_cred->server, &s_name) == 0) {
- krb5_set_error_message(context, retval,
- "Server %s not found in Kerberos database",
- s_name);
- krb5_free_unparsed_name(context, s_name);
- } else
- /* In case there's a stale S_PRINCIPAL_UNKNOWN
- report already noted. */
- krb5_clear_error_message(context);
- }
+ switch (err_reply->error) {
+ case KRB_ERR_GENERIC:
+ krb5_set_error_message(context, retval,
+ "KDC returned error string: %.*s",
+ err_reply->text.length,
+ err_reply->text.data);
break;
- default:
+ case KDC_ERR_S_PRINCIPAL_UNKNOWN:
+ {
+ char *s_name;
+ if (krb5_unparse_name(context, in_cred->server, &s_name) == 0) {
+ krb5_set_error_message(context, retval,
+ "Server %s not found in Kerberos database",
+ s_name);
+ krb5_free_unparsed_name(context, s_name);
+ } else
+ /* In case there's a stale S_PRINCIPAL_UNKNOWN
+ report already noted. */
+ krb5_clear_error_message(context);
+ }
+ break;
+ default:
#if 0 /* We should stop the KDC from sending back this text, because
if the local language doesn't match the KDC's language, we'd
just wind up printing out the error message in two languages.
Well, when we get some localization. Which is already
happening in KfM. */
- m = error_message(retval);
- /* Special case: MIT KDC may return this same string
- in the e-text field. */
- if (strlen (m) == err_reply->text.length-1
- && !strcmp(m, err_reply->text.data))
- break;
- krb5_set_error_message(context, retval,
- "%s (KDC supplied additional data: %s)",
- m, err_reply->text.data);
-#endif
+ m = error_message(retval);
+ /* Special case: MIT KDC may return this same string
+ in the e-text field. */
+ if (strlen (m) == err_reply->text.length-1
+ && !strcmp(m, err_reply->text.data))
break;
- }
+ krb5_set_error_message(context, retval,
+ "%s (KDC supplied additional data: %s)",
+ m, err_reply->text.data);
+#endif
+ break;
}
-
- krb5_free_error(context, err_reply);
- goto error_4;
}
- /* Unfortunately, Heimdal at least up through 1.2 encrypts using
- the session key not the subsession key. So we try both. */
- if ((retval = krb5int_decode_tgs_rep(context, &tgsrep.response,
- subkey,
- KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY, &dec_rep))) {
- if ((krb5int_decode_tgs_rep(context, &tgsrep.response,
- &tkt->keyblock,
- KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY, &dec_rep)) == 0)
- retval = 0;
- else goto error_4;
- }
+ krb5_free_error(context, err_reply);
+ goto error_4;
+ }
- if (dec_rep->msg_type != KRB5_TGS_REP) {
- retval = KRB5KRB_AP_ERR_MSG_TYPE;
- goto error_3;
- }
+ /* Unfortunately, Heimdal at least up through 1.2 encrypts using
+ the session key not the subsession key. So we try both. */
+ if ((retval = krb5int_decode_tgs_rep(context, &tgsrep.response,
+ subkey,
+ KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY, &dec_rep))) {
+ if ((krb5int_decode_tgs_rep(context, &tgsrep.response,
+ &tkt->keyblock,
+ KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY, &dec_rep)) == 0)
+ retval = 0;
+ else goto error_4;
+ }
- /*
- * Don't trust the ok-as-delegate flag from foreign KDCs unless the
- * cross-realm TGT also had the ok-as-delegate flag set.
+ if (dec_rep->msg_type != KRB5_TGS_REP) {
+ retval = KRB5KRB_AP_ERR_MSG_TYPE;
+ goto error_3;
+ }
+
+ /*
+ * Don't trust the ok-as-delegate flag from foreign KDCs unless the
+ * cross-realm TGT also had the ok-as-delegate flag set.
+ */
+ if (!tgt_is_local_realm(tkt)
+ && !(tkt->ticket_flags & TKT_FLG_OK_AS_DELEGATE))
+ dec_rep->enc_part2->flags &= ~TKT_FLG_OK_AS_DELEGATE;
+
+ /* make sure the response hasn't been tampered with..... */
+ retval = 0;
+
+ if (s4u2self && !IS_TGS_PRINC(context, dec_rep->ticket->server)) {
+ /* Final hop, check whether KDC supports S4U2Self */
+ if (krb5_principal_compare(context, dec_rep->client, in_cred->server))
+ retval = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
+ } else if ((kdcoptions & KDC_OPT_CNAME_IN_ADDL_TKT) == 0) {
+ /* XXX for constrained delegation this check must be performed by caller
+ * as we don't have access to the key to decrypt the evidence ticket.
*/
- if (!tgt_is_local_realm(tkt)
- && !(tkt->ticket_flags & TKT_FLG_OK_AS_DELEGATE))
- dec_rep->enc_part2->flags &= ~TKT_FLG_OK_AS_DELEGATE;
-
- /* make sure the response hasn't been tampered with..... */
- retval = 0;
-
- if (s4u2self && !IS_TGS_PRINC(context, dec_rep->ticket->server)) {
- /* Final hop, check whether KDC supports S4U2Self */
- if (krb5_principal_compare(context, dec_rep->client, in_cred->server))
- retval = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
- } else if ((kdcoptions & KDC_OPT_CNAME_IN_ADDL_TKT) == 0) {
- /* XXX for constrained delegation this check must be performed by caller
- * as we don't have access to the key to decrypt the evidence ticket.
- */
- if (!krb5_principal_compare(context, dec_rep->client, tkt->client))
- retval = KRB5_KDCREP_MODIFIED;
- }
+ if (!krb5_principal_compare(context, dec_rep->client, tkt->client))
+ retval = KRB5_KDCREP_MODIFIED;
+ }
- if (retval == 0)
- retval = check_reply_server(context, kdcoptions, in_cred, dec_rep);
+ if (retval == 0)
+ retval = check_reply_server(context, kdcoptions, in_cred, dec_rep);
- if (dec_rep->enc_part2->nonce != tgsrep.expected_nonce)
- retval = KRB5_KDCREP_MODIFIED;
+ if (dec_rep->enc_part2->nonce != tgsrep.expected_nonce)
+ retval = KRB5_KDCREP_MODIFIED;
- if ((kdcoptions & KDC_OPT_POSTDATED) &&
- (in_cred->times.starttime != 0) &&
- (in_cred->times.starttime != dec_rep->enc_part2->times.starttime))
- retval = KRB5_KDCREP_MODIFIED;
+ if ((kdcoptions & KDC_OPT_POSTDATED) &&
+ (in_cred->times.starttime != 0) &&
+ (in_cred->times.starttime != dec_rep->enc_part2->times.starttime))
+ retval = KRB5_KDCREP_MODIFIED;
- if ((in_cred->times.endtime != 0) &&
- (dec_rep->enc_part2->times.endtime > in_cred->times.endtime))
- retval = KRB5_KDCREP_MODIFIED;
+ if ((in_cred->times.endtime != 0) &&
+ (dec_rep->enc_part2->times.endtime > in_cred->times.endtime))
+ retval = KRB5_KDCREP_MODIFIED;
- if ((kdcoptions & KDC_OPT_RENEWABLE) &&
- (in_cred->times.renew_till != 0) &&
- (dec_rep->enc_part2->times.renew_till > in_cred->times.renew_till))
- retval = KRB5_KDCREP_MODIFIED;
+ if ((kdcoptions & KDC_OPT_RENEWABLE) &&
+ (in_cred->times.renew_till != 0) &&
+ (dec_rep->enc_part2->times.renew_till > in_cred->times.renew_till))
+ retval = KRB5_KDCREP_MODIFIED;
- if ((kdcoptions & KDC_OPT_RENEWABLE_OK) &&
- (dec_rep->enc_part2->flags & KDC_OPT_RENEWABLE) &&
- (in_cred->times.endtime != 0) &&
- (dec_rep->enc_part2->times.renew_till > in_cred->times.endtime))
- retval = KRB5_KDCREP_MODIFIED;
+ if ((kdcoptions & KDC_OPT_RENEWABLE_OK) &&
+ (dec_rep->enc_part2->flags & KDC_OPT_RENEWABLE) &&
+ (in_cred->times.endtime != 0) &&
+ (dec_rep->enc_part2->times.renew_till > in_cred->times.endtime))
+ retval = KRB5_KDCREP_MODIFIED;
- if (retval != 0)
- goto error_3;
+ if (retval != 0)
+ goto error_3;
- if (!in_cred->times.starttime &&
- !in_clock_skew(dec_rep->enc_part2->times.starttime,
- tgsrep.request_time)) {
- retval = KRB5_KDCREP_SKEW;
- goto error_3;
- }
+ if (!in_cred->times.starttime &&
+ !in_clock_skew(dec_rep->enc_part2->times.starttime,
+ tgsrep.request_time)) {
+ retval = KRB5_KDCREP_SKEW;
+ goto error_3;
+ }
- if (out_padata != NULL) {
- *out_padata = dec_rep->padata;
- dec_rep->padata = NULL;
- }
- if (out_enc_padata != NULL) {
- *out_enc_padata = dec_rep->enc_part2->enc_padata;
- dec_rep->enc_part2->enc_padata = NULL;
- }
+ if (out_padata != NULL) {
+ *out_padata = dec_rep->padata;
+ dec_rep->padata = NULL;
+ }
+ if (out_enc_padata != NULL) {
+ *out_enc_padata = dec_rep->enc_part2->enc_padata;
+ dec_rep->enc_part2->enc_padata = NULL;
+ }
- retval = krb5_kdcrep2creds(context, dec_rep, address,
- &in_cred->second_ticket, out_cred);
+ retval = krb5_kdcrep2creds(context, dec_rep, address,
+ &in_cred->second_ticket, out_cred);
- error_3:;
- if (subkey != NULL) {
- if (retval == 0 && out_subkey != NULL)
- *out_subkey = subkey;
- else
- krb5_free_keyblock(context, subkey);
- }
+error_3:;
+ if (subkey != NULL) {
+ if (retval == 0 && out_subkey != NULL)
+ *out_subkey = subkey;
+ else
+ krb5_free_keyblock(context, subkey);
+ }
- memset(dec_rep->enc_part2->session->contents, 0,
- dec_rep->enc_part2->session->length);
- krb5_free_kdc_rep(context, dec_rep);
+ memset(dec_rep->enc_part2->session->contents, 0,
+ dec_rep->enc_part2->session->length);
+ krb5_free_kdc_rep(context, dec_rep);
- error_4:;
- free(tgsrep.response.data);
+error_4:;
+ free(tgsrep.response.data);
#ifdef DEBUG_REFERRALS
- printf("krb5_get_cred_via_tkt ending; %s\n", retval?error_message(retval):"no error");
+ printf("krb5_get_cred_via_tkt ending; %s\n", retval?error_message(retval):"no error");
#endif
- return retval;
- }
+ return retval;
+}