Connected: An Internet Encyclopedia
RFC 1510 - A.6. KRB_TGS_REQ verification and KRB_TGS_REP generation

Top: Connected: An Internet Encyclopedia
Up: Requests For Comments
Up: RFC 1510
Up: A. Pseudo-code for protocol processing
Prev: A.5. KRB_TGS_REQ generation
Next: A.7. KRB_TGS_REP verification

### A.6. KRB_TGS_REQ verification and KRB_TGS_REP generation

            /* note that reading the application request requires first
            determining the server for which a ticket was issued, and
            choosing the correct key for decryption.  The name of the
            server appears in the plaintext part of the ticket. */

            if (no KRB_AP_REQ in req.padata) then
                    error_out(KDC_ERR_PADATA_TYPE_NOSUPP);
            endif
            verify KRB_AP_REQ in req.padata;

            /* Note that the realm in which the Kerberos server is
            operating is determined by the instance from the
            ticket-granting ticket.  The realm in the ticket-granting
            ticket is the realm under which the ticket granting ticket was
            issued.  It is possible for a single Kerberos server to
            support more than one realm. */

            auth_hdr := KRB_AP_REQ;
            tgt := auth_hdr.ticket;

            if (tgt.sname is not a TGT for local realm and is not
                    req.sname) then error_out(KRB_AP_ERR_NOT_US);

            realm := realm_tgt_is_for(tgt);

            decode remainder of request;

            if (auth_hdr.authenticator.cksum is missing) then
                    error_out(KRB_AP_ERR_INAPP_CKSUM);
            endif
            if (auth_hdr.authenticator.cksum type is not supported) then
                    error_out(KDC_ERR_SUMTYPE_NOSUPP);
            endif
            if (auth_hdr.authenticator.cksum is not both collision-proof
                and keyed)  then
                    error_out(KRB_AP_ERR_INAPP_CKSUM);
            endif
            set computed_checksum := checksum(req);
            if (computed_checksum != auth_hdr.authenticatory.cksum) then
                    error_out(KRB_AP_ERR_MODIFIED);
            endif

            server := lookup(req.sname,realm);

            if (!server) then
                    if (is_foreign_tgt_name(server)) then
                            server := best_intermediate_tgs(server);
                    else
                            /* no server in Database */
                            error_out(KDC_ERR_S_PRINCIPAL_UNKNOWN);
                    endif
            endif

            session := generate_random_session_key();

            use_etype := first supported etype in req.etypes;

            if (no support for req.etypes) then
                    error_out(KDC_ERR_ETYPE_NOSUPP);
            endif

            new_tkt.vno := ticket version; /* = 5 */
            new_tkt.sname := req.sname;
            new_tkt.srealm := realm;
            reset all flags in new_tkt.flags;

            /* It should be noted that local policy may affect the  */
            /* processing of any of these flags.  For example, some */
            /* realms may refuse to issue renewable tickets         */

            new_tkt.caddr := tgt.caddr;
            resp.caddr := NULL; /* We only include this if they change */
            if (req.kdc-options.FORWARDABLE is set) then
                    if (tgt.flags.FORWARDABLE is reset) then
                            error_out(KDC_ERR_BADOPTION);
                    endif
                    set new_tkt.flags.FORWARDABLE;
            endif
            if (req.kdc-options.FORWARDED is set) then
                    if (tgt.flags.FORWARDABLE is reset) then
                            error_out(KDC_ERR_BADOPTION);
                    endif
                    set new_tkt.flags.FORWARDED;
                    new_tkt.caddr := req.addresses;
                    resp.caddr := req.addresses;
            endif
            if (tgt.flags.FORWARDED is set) then
                    set new_tkt.flags.FORWARDED;
            endif

            if (req.kdc-options.PROXIABLE is set) then
                    if (tgt.flags.PROXIABLE is reset)
                            error_out(KDC_ERR_BADOPTION);
                    endif
                    set new_tkt.flags.PROXIABLE;
            endif
            if (req.kdc-options.PROXY is set) then
                    if (tgt.flags.PROXIABLE is reset) then
                            error_out(KDC_ERR_BADOPTION);
                    endif
                    set new_tkt.flags.PROXY;
                    new_tkt.caddr := req.addresses;
                    resp.caddr := req.addresses;
            endif

            if (req.kdc-options.POSTDATE is set) then
                    if (tgt.flags.POSTDATE is reset)
                            error_out(KDC_ERR_BADOPTION);
                    endif
                    set new_tkt.flags.POSTDATE;
            endif
            if (req.kdc-options.POSTDATED is set) then
                    if (tgt.flags.POSTDATE is reset) then
                            error_out(KDC_ERR_BADOPTION);
                    endif
                    set new_tkt.flags.POSTDATED;
                    set new_tkt.flags.INVALID;
                    if (against_postdate_policy(req.from)) then
                            error_out(KDC_ERR_POLICY);
                    endif
                    new_tkt.starttime := req.from;
            endif

            if (req.kdc-options.VALIDATE is set) then
                    if (tgt.flags.INVALID is reset) then
                            error_out(KDC_ERR_POLICY);
                    endif
                    if (tgt.starttime > kdc_time) then
                            error_out(KRB_AP_ERR_NYV);
                    endif
                    if (check_hot_list(tgt)) then
                            error_out(KRB_AP_ERR_REPEAT);
                    endif
                    tkt := tgt;
                    reset new_tkt.flags.INVALID;
            endif

            if (req.kdc-options.(any flag except ENC-TKT-IN-SKEY, RENEW,
                                 and those already processed) is set) then
                    error_out(KDC_ERR_BADOPTION);
            endif

            new_tkt.authtime := tgt.authtime;

            if (req.kdc-options.RENEW is set) then
              /* Note that if the endtime has already passed, the ticket */
              /* would have been rejected in the initial authentication  */
              /* stage, so there is no need to check again here          */
                    if (tgt.flags.RENEWABLE is reset) then
                            error_out(KDC_ERR_BADOPTION);
                    endif
                    if (tgt.renew-till >= kdc_time) then
                            error_out(KRB_AP_ERR_TKT_EXPIRED);
                    endif
                    tkt := tgt;
                    new_tkt.starttime := kdc_time;
                    old_life := tgt.endttime - tgt.starttime;
                    new_tkt.endtime := min(tgt.renew-till,
                                           new_tkt.starttime + old_life);
            else
                    new_tkt.starttime := kdc_time;
                    if (req.till = 0) then
                            till := infinity;
                    else
                            till := req.till;
                    endif
                    new_tkt.endtime := min(till,
                                       new_tkt.starttime+client.max_life,
                                       new_tkt.starttime+server.max_life,
                                       new_tkt.starttime+max_life_for_realm,
                                       tgt.endtime);

                    if ((req.kdc-options.RENEWABLE-OK is set) and
                        (new_tkt.endtime < req.till) and
                        (tgt.flags.RENEWABLE is set) then
                            /* we set the RENEWABLE option for later  */
                            /* processing                             */
                            set req.kdc-options.RENEWABLE;
                            req.rtime := min(req.till, tgt.renew-till);
                    endif
            endif

            if (req.rtime = 0) then
                    rtime := infinity;
            else
                    rtime := req.rtime;
            endif

            if ((req.kdc-options.RENEWABLE is set) and
                (tgt.flags.RENEWABLE is set)) then
                    set new_tkt.flags.RENEWABLE;
                    new_tkt.renew-till := min(rtime,
                    new_tkt.starttime+client.max_rlife,
                    new_tkt.starttime+server.max_rlife,
                    new_tkt.starttime+max_rlife_for_realm,
                    tgt.renew-till);
            else
                    new_tkt.renew-till := OMIT;
                                  /* leave the renew-till field out */
            endif
            if (req.enc-authorization-data is present) then
                    decrypt req.enc-authorization-data
                            into    decrypted_authorization_data
                            using auth_hdr.authenticator.subkey;
                    if (decrypt_error()) then
                            error_out(KRB_AP_ERR_BAD_INTEGRITY);
                    endif
            endif
            new_tkt.authorization_data :=
            req.auth_hdr.ticket.authorization_data +
                                     decrypted_authorization_data;

            new_tkt.key := session;
            new_tkt.crealm := tgt.crealm;
            new_tkt.cname := req.auth_hdr.ticket.cname;

            if (realm_tgt_is_for(tgt) := tgt.realm) then
                    /* tgt issued by local realm */
                    new_tkt.transited := tgt.transited;
            else
                    /* was issued for this realm by some other realm */
                    if (tgt.transited.tr-type not supported) then
                            error_out(KDC_ERR_TRTYPE_NOSUPP);
                    endif
                    new_tkt.transited
                       := compress_transited(tgt.transited + tgt.realm)
            endif
            encode encrypted part of new_tkt into OCTET STRING;
            if (req.kdc-options.ENC-TKT-IN-SKEY is set) then
                    if (server not specified) then
                            server = req.second_ticket.client;
                    endif
                    if ((req.second_ticket is not a TGT) or
                        (req.second_ticket.client != server)) then
                            error_out(KDC_ERR_POLICY);
                    endif

                    new_tkt.enc-part := encrypt OCTET STRING using
                            using etype_for_key(second-ticket.key),
                                                          second-ticket.key;
            else
                    new_tkt.enc-part := encrypt OCTET STRING
                            using etype_for_key(server.key), server.key,
                                                          server.p_kvno;
            endif

            resp.pvno := 5;
            resp.msg-type := KRB_TGS_REP;
            resp.crealm := tgt.crealm;
            resp.cname := tgt.cname;
            resp.ticket := new_tkt;

            resp.key := session;
            resp.nonce := req.nonce;
            resp.last-req := fetch_last_request_info(client);
            resp.flags := new_tkt.flags;

            resp.authtime := new_tkt.authtime;
            resp.starttime := new_tkt.starttime;
            resp.endtime := new_tkt.endtime;

            omit resp.key-expiration;

            resp.sname := new_tkt.sname;
            resp.realm := new_tkt.realm;

            if (new_tkt.flags.RENEWABLE) then
                    resp.renew-till := new_tkt.renew-till;
            endif

            encode body of reply into OCTET STRING;

            if (req.padata.authenticator.subkey)
                    resp.enc-part := encrypt OCTET STRING using use_etype,
                            req.padata.authenticator.subkey;
            else resp.enc-part := encrypt OCTET STRING
                                  using use_etype, tgt.key;

            send(resp);

Next: A.7. KRB_TGS_REP verification

Connected: An Internet Encyclopedia
RFC 1510 - A.6. KRB_TGS_REQ verification and KRB_TGS_REP generation