Ignore password attributes for S4U2Self requests

For consistency with Windows KDCs, allow protocol transition to work
even if the password has expired or needs changing.

Also, when looking up an enterprise principal with an AS request,
treat ERR_KEY_EXP as confirmation that the client is present in the
realm.

[ghudson@mit.edu: added comment in kdc_process_s4u2self_req(); edited
commit message]

ticket: 8763 (new)
tags: pullup
target_version: 1.17
kdc_get_ticket_renewtime(kdc_realm_t *realm, krb5_kdc_req *request,
                         krb5_enc_tkt_part *tgt, krb5_db_entry *client,
                         krb5_db_entry *server, krb5_enc_tkt_part *tkt)
{
    krb5_timestamp rtime, max_rlife;

    clear(tkt->flags, TKT_FLG_RENEWABLE);
    tkt->times.renew_till = 0;

    /* Don't issue renewable tickets if the client or server don't allow it,
     * or if this is a TGS request and the TGT isn't renewable. */
    if (server->attributes & KRB5_KDB_DISALLOW_RENEWABLE)
        return;
    if (client != NULL && (client->attributes & KRB5_KDB_DISALLOW_RENEWABLE))
        return;
    if (tgt != NULL && !(tgt->flags & TKT_FLG_RENEWABLE))
        return;

    /* Determine the requested renewable time. */
    if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE))
        rtime = request->rtime ? request->rtime : kdc_infinity;
    else if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
             ts_after(request->till, tkt->times.endtime))
        rtime = request->till;
    else
        return;

    /* Truncate it to the allowable renewable time. */
    if (tgt != NULL)
        rtime = ts_min(rtime, tgt->times.renew_till);
    max_rlife = min(server->max_renewable_life, realm->realm_maxrlife);
    if (client != NULL)
        max_rlife = min(max_rlife, client->max_renewable_life);
    rtime = ts_min(rtime, ts_incr(tkt->times.starttime, max_rlife));

    /* If the client only specified renewable-ok, don't issue a renewable
     * ticket unless the truncated renew time exceeds the ticket end time. */
    if (!isflagset(request->kdc_options, KDC_OPT_RENEWABLE) &&
        !ts_after(rtime, tkt->times.endtime))
        return;

    setflag(tkt->flags, TKT_FLG_RENEWABLE);
    tkt->times.renew_till = rtime;
}

kdc_get_ticket_renewtime(kdc_realm_t *realm, krb5_kdc_req *request,
                         krb5_enc_tkt_part *tgt, krb5_db_entry *client,
                         krb5_db_entry *server, krb5_enc_tkt_part *tkt)
{
    krb5_timestamp rtime, max_rlife;

    clear(tkt->flags, TKT_FLG_RENEWABLE);
    tkt->times.renew_till = 0;

    /* Don't issue renewable tickets if the client or server don't allow it,
     * or if this is a TGS request and the TGT isn't renewable. */
    if (server->attributes & KRB5_KDB_DISALLOW_RENEWABLE)
        return;
    if (client != NULL && (client->attributes & KRB5_KDB_DISALLOW_RENEWABLE))
        return;
    if (tgt != NULL && !(tgt->flags & TKT_FLG_RENEWABLE))
        return;

    /* Determine the requested renewable time. */
    if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE))
        rtime = request->rtime ? request->rtime : kdc_infinity;
    else if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
             ts_after(request->till, tkt->times.endtime))
        rtime = request->till;
    else
        return;

    /* Truncate it to the allowable renewable time. */
    if (tgt != NULL)
        rtime = ts_min(rtime, tgt->times.renew_till);
    max_rlife = min(server->max_renewable_life, realm->realm_maxrlife);
    if (client != NULL)
        max_rlife = min(max_rlife, client->max_renewable_life);
    rtime = ts_min(rtime, ts_incr(tkt->times.starttime, max_rlife));

    /* If the client only specified renewable-ok, don't issue a renewable
     * ticket unless the truncated renew time exceeds the ticket end time. */
    if (!isflagset(request->kdc_options, KDC_OPT_RENEWABLE) &&
        !ts_after(rtime, tkt->times.endtime))
        return;

    setflag(tkt->flags, TKT_FLG_RENEWABLE);
    tkt->times.renew_till = rtime;
}
