Subject: AS -- The Authentication Service Exchange
Author: Alex_Raj
In response to: Kerberos Authentication Protocol (V5) -- RFC 1510
Posted on: 11/08/2006 07:10:51 PM
1. Client sends a request to KDC:  KRB_AS_REQ    
KRB_AS_REQ generation:
        request.pvno := protocol version; /* pvno = 5 */
        request.msg-type := message type; /* type = KRB_AS_REQ */
        if(pa_enc_timestamp_required) then
                request.padata.padata-type = PA-ENC-TIMESTAMP;
                get system_time;
                padata-body.patimestamp,pausec = system_time;
                encrypt padata-body into request.padata.padata-value
                        using client.key; /* derived from password */
        endif
        body.kdc-options := users's preferences;
        body.cname := user's name;
        body.realm := user's realm;
        body.sname := service's name; /* usually "krbtgt",
                                         "localrealm" */
        if (body.kdc-options.POSTDATED is set) then
                body.from := requested starting time;
        else
                omit body.from;
        endif
        body.till := requested end time;
        if (body.kdc-options.RENEWABLE is set) then
                body.rtime := requested final renewal time;
        endif
        body.nonce := random_nonce();
        body.etype := requested etypes;
        if (user supplied addresses) then
                body.addresses := user's addresses;
        else
                omit body.addresses;
        endif
        omit body.enc-authorization-data;
        request.req-body := body;
        kerberos := lookup(name of local kerberos server (or servers));
        send(packet,kerberos);
        wait(for response);
        if (timed_out) then
                retry or use alternate server;
        endif
2. KDC sneds a reply to client: KRB_AS_REP or  KRB_ERROR
 KRB_AS_REQ verification and KRB_AS_REP generation
        decode message into req;
        client := lookup(req.cname,req.realm);
        server := lookup(req.sname,req.realm);
        get system_time;
        kdc_time := system_time.seconds;
        if (!client) then
                /* no client in Database */
                error_out(KDC_ERR_C_PRINCIPAL_UNKNOWN);
        endif
        if (!server) then
                /* no server in Database */
                error_out(KDC_ERR_S_PRINCIPAL_UNKNOWN);
        endif
        if(client.pa_enc_timestamp_required and
           pa_enc_timestamp not present) then
                error_out(KDC_ERR_PREAUTH_REQUIRED(PA_ENC_TIMESTAMP));
        endif
        if(pa_enc_timestamp present) then
                decrypt req.padata-value into decrypted_enc_timestamp
                        using client.key;
                        using auth_hdr.authenticator.subkey;
                if (decrypt_error()) then
                        error_out(KRB_AP_ERR_BAD_INTEGRITY);
                if(decrypted_enc_timestamp is not within allowable
                        skew) then error_out(KDC_ERR_PREAUTH_FAILED);
                endif
                if(decrypted_enc_timestamp and usec is replay)
                        error_out(KDC_ERR_PREAUTH_FAILED);
                endif
                add decrypted_enc_timestamp and usec to replay cache;
        endif
        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 := req.srealm;
        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         */
        if (req.kdc-options.FORWARDABLE is set) then
                set new_tkt.flags.FORWARDABLE;
        endif
        if (req.kdc-options.PROXIABLE is set) then
                set new_tkt.flags.PROXIABLE;
        endif
        if (req.kdc-options.ALLOW-POSTDATE is set) then
                set new_tkt.flags.ALLOW-POSTDATE;
        endif
        if ((req.kdc-options.RENEW is set) or
            (req.kdc-options.VALIDATE is set) or
            (req.kdc-options.PROXY is set) or
            (req.kdc-options.FORWARDED is set) or
            (req.kdc-options.ENC-TKT-IN-SKEY is set)) then
                error_out(KDC_ERR_BADOPTION);
        endif
        new_tkt.session := random_session_key();
        new_tkt.cname := req.cname;
        new_tkt.crealm := req.crealm;
        new_tkt.transited := empty_transited_field();
        new_tkt.authtime := kdc_time;
        if (req.kdc-options.POSTDATED is set) then
           if (against_postdate_policy(req.from)) then
                error_out(KDC_ERR_POLICY);
           endif
           set new_tkt.flags.INVALID;
           new_tkt.starttime := req.from;
        else
           omit new_tkt.starttime; /* treated as authtime when
                                      omitted */
        endif
        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);
        if ((req.kdc-options.RENEWABLE-OK is set) and
            (new_tkt.endtime < req.till)) then
                /* we set the RENEWABLE option for later processing */
                set req.kdc-options.RENEWABLE;
                req.rtime := req.till;
        endif
        if (req.rtime = 0) then
                rtime := infinity;
        else
                rtime := req.rtime;
        endif
        if (req.kdc-options.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);
        else
                omit new_tkt.renew-till; /* only present if RENEWABLE */
        endif
        if (req.addresses) then
                new_tkt.caddr := req.addresses;
        else
                omit new_tkt.caddr;
        endif
        new_tkt.authorization_data := empty_authorization_data();
        encode to-be-encrypted part of ticket into OCTET STRING;
        new_tkt.enc-part := encrypt OCTET STRING
            using etype_for_key(server.key), server.key, server.p_kvno;
        /* Start processing the response */
        resp.pvno := 5;
        resp.msg-type := KRB_AS_REP;
        resp.cname := req.cname;
        resp.crealm := req.realm;
        resp.ticket := new_tkt;
        resp.key := new_tkt.session;
        resp.last-req := fetch_last_request_info(client);
        resp.nonce := req.nonce;
        resp.key-expiration := client.expiration;
        resp.flags := new_tkt.flags;
        resp.authtime := new_tkt.authtime;
        resp.starttime := new_tkt.starttime;
        resp.endtime := new_tkt.endtime;
        if (new_tkt.flags.RENEWABLE) then
                resp.renew-till := new_tkt.renew-till;
        endif
        resp.realm := new_tkt.realm;
        resp.sname := new_tkt.sname;
        resp.caddr := new_tkt.caddr;
        encode body of reply into OCTET STRING;
        resp.enc-part := encrypt OCTET STRING
                         using use_etype, client.key, client.p_kvno;
        send(resp);
3. KRB_AS_REP verification
        decode response into resp;
        if (resp.msg-type = KRB_ERROR) then
                if(error = KDC_ERR_PREAUTH_REQUIRED(PA_ENC_TIMESTAMP))
                        then set pa_enc_timestamp_required;
                        goto KRB_AS_REQ;
                endif
                process_error(resp);
                return;
        endif
        /* On error, discard the response, and zero the session key */
        /* from the response immediately */
        key = get_decryption_key(resp.enc-part.kvno, resp.enc-part.etype,
                                 resp.padata);
        unencrypted part of resp := decode of decrypt of resp.enc-part
                                using resp.enc-part.etype and key;
        zero(key);
        if (common_as_rep_tgs_rep_checks fail) then
                destroy resp.key;
                return error;
        endif
        if near(resp.princ_exp) then
                print(warning message);
        endif
        save_for_later(ticket,session,client,server,times,flags);
4.  KRB_AS_REP and KRB_TGS_REP common checks
        if (decryption_error() or
            (req.cname != resp.cname) or
            (req.realm != resp.crealm) or
            (req.sname != resp.sname) or
            (req.realm != resp.realm) or
            (req.nonce != resp.nonce) or
            (req.addresses != resp.caddr)) then
                destroy resp.key;
                return KRB_AP_ERR_MODIFIED;
        endif
        /* make sure no flags are set that shouldn't be, and that  */
        /* all that should be are set                              */
        if (!check_flags_for_compatability(req.kdc-options,resp.flags))
                then destroy resp.key;
                return KRB_AP_ERR_MODIFIED;
        endif
        if ((req.from = 0) and
            (resp.starttime is not within allowable skew)) then
                destroy resp.key;
                return KRB_AP_ERR_SKEW;
        endif
        if ((req.from != 0) and (req.from != resp.starttime)) then
                destroy resp.key;
                return KRB_AP_ERR_MODIFIED;
        endif
        if ((req.till != 0) and (resp.endtime > req.till)) then
                destroy resp.key;
                return KRB_AP_ERR_MODIFIED;
        endif
        if ((req.kdc-options.RENEWABLE is set) and
            (req.rtime != 0) and (resp.renew-till > req.rtime)) then
                destroy resp.key;
                return KRB_AP_ERR_MODIFIED;
        endif
        if ((req.kdc-options.RENEWABLE-OK is set) and
            (resp.flags.RENEWABLE) and
            (req.till != 0) and
            (resp.renew-till > req.till)) then
                destroy resp.key;
                return KRB_AP_ERR_MODIFIED;
        endif
 
> 
> On 11/08/2006 06:47:42 PM 
Alex_Raj wrote:
The authentication process proceeds as follows: A client sends a request to the authentication server (AS) requesting "credentials" for a given server.  The AS responds with these credentials, encrypted in the client's key.  The credentials consist of 1) a "ticket" for the server and 2) a temporary encryption key (often called a "session key").  The client transmits the ticket (which contains the client's identity and a copy of the session key, all encrypted in the server's key) to the server.  The session key (now shared by the client and server) is used to authenticate the client, and may optionally be used to authenticate the server.  It may also be used to encrypt further communication between the two parties or to exchange a separate sub-session key to be used to encrypt further communication.
The Kerberos protocol consists of several sub-protocols (or  exchanges):
AS -- The Authentication Service Exchange
TGS-- The Ticket-Granting Service Exchange
CS -- The Client/Server Authentication Exchange
References: