A. プロトコル処理のための擬似コード English
この付録においては、クライアントとサーバーでメッセージがどのように作成され、解釈されるかを示す擬似コードについて説明します。
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; /* パスワードから取り出した */
endif
body.kdc-options := users's preferences;
body.cname := user's name;
body.realm := user's realm;
body.sname := service's name; /* 通常 "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
A.2. KRB_AS_REQ 検証および KRB_AS_REP 生成 (English)
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
/* データベース内にクライアントがない */
error_out(KDC_ERR_C_PRINCIPAL_UNKNOWN);
endif
if (!server) then
/* データベース内にサーバーがない */
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;
/* ローカル ポリシーはこれらのフラグの処理に影響を与える */
/* ことがあります。たとえば、レルムによっては、更新可能 */
/* なチケットを拒否します。 */
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; /* 省略したときには authtime として
扱われる */
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
/* ここでは、後の処理のために
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; /* 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;
/* 応答処理開始 */
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);
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
/* エラーが発生した場合は、応答を破棄し、 */
/* 応答のセッション鍵を即座に 0 にする */
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);
A.4. KRB_AS_REP および KRB_TGS_REP の一般チェック (English)
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
/* 適切なフラグだけがセットされていることを確認のこと */
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
/* make_application_request は、適切なチケット- */
/* グランティング チケットを取得するのにこのルーチンを */
/* 再帰的に実行する必要があるかもしれません。 */
request.pvno := protocol version; /* pvno = 5 */
request.msg-type := message type; /* type = KRB_TGS_REQ */
body.kdc-options := users's preferences;
/* TGT がエンドユーザーのレルム用ではない場合、sname */
/* はエンド レルムの TGT になり、要求したチケット */
/* (body.realm) のレルムは、要求を出している TGS の */
/* レルムになります。 */
body.sname := service's name;
body.realm := service's realm;
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
body.enc-authorization-data := user-supplied data;
if (body.kdc-options.ENC-TKT-IN-SKEY) then
body.additional-tickets_ticket := second TGT;
endif
request.req-body := body;
check := generate_checksum (req.body,checksumtype);
request.padata[0].padata-type := PA-TGS-REQ;
request.padata[0].padata-value := create a KRB_AP_REQ using
the TGT and checksum
/* 必要/供給に応じて他の padata を追加する */
kerberos := lookup(name of local kerberose server (or servers));
send(packet,kerberos);
wait(for response);
if (timed_out) then
retry or use alternate server;
endif
A.6. KRB_TGS_REQ 検証および KRB_TGS_REP 生成
(English)/* アプリケーション要求を読み取るには、まずチケットを発行した サーバーを判断し、
復号するための鍵を選択する必要があります。
サーバー名は、チケットのプレーンテキスト部分に表示されます。 */
if (no KRB_AP_REQ in req.padata) then
error_out(KDC_ERR_PADATA_TYPE_NOSUPP);
endif
verify KRB_AP_REQ in req.padata;
/* Kerberos サーバーが動作しているレルムは、チケット-
グランティング チケットのインスタンスによって判断されて
います。チケット-グランティング チケット内のレルムは、
チケット-グランティング チケットが発行されたレルムです。
1 つの Kerberos サーバーは、複数のレルムをサポート
できます。 */
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
/* データベース内にサーバーがありません */
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;
/* ローカル ポリシーはこれらのフラグの処理に影響を与える */
/* ことがあります。たとえば、レルムによっては、更新可能 */
/* なチケットを拒否します。 */
new_tkt.caddr := tgt.caddr;
resp.caddr := NULL; /* 変更された場合だけこれを入れます。 */
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
/* endtime がすでに過ぎている場合は、チケットは初回の認証段階で */
/* 拒否されているので、ここで再度チェックする必要はありません。 */
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
/* 後の処理のために RENEWABLE オプションを */
/* セットする */
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;
/* renew-till フィールドを省略する */
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 */
new_tkt.transited := tgt.transited;
else
/* 他のレルムによってこのレルム用に発行されている */
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);
decode response into resp;
if (resp.msg-type = KRB_ERROR) then
process_error(resp);
return;
endif
/* エラーが発生した場合は、応答を破棄し、 */
/* 応答のセッション鍵を即座に 0 にする */
if (req.padata.authenticator.subkey)
unencrypted part of resp :=
decode of decrypt of resp.enc-part
using resp.enc-part.etype and subkey;
else unencrypted part of resp :=
decode of decrypt of resp.enc-part
using resp.enc-part.etype and tgt's session key;
if (common_as_rep_tgs_rep_checks fail) then
destroy resp.key;
return error;
endif
check authorization_data as necessary;
save_for_later(ticket,session,client,server,times,flags);
A.8. Authenticator 生成 (English)
body.authenticator-vno := authenticator vno; /* = 5 */
body.cname, body.crealm := client name;
if (supplying checksum) then
body.cksum := checksum;
endif
get system_time;
body.ctime, body.cusec := system_time;
if (selecting sub-session key) then
select sub-session key;
body.subkey := sub-session key;
endif
if (using sequence numbers) then
select initial sequence number;
body.seq-number := initial sequence;
endif
obtain ticket and session_key from cache;
packet.pvno := protocol version; /* 5 */
packet.msg-type := message type; /* KRB_AP_REQ */
if (desired(MUTUAL_AUTHENTICATION)) then
set packet.ap-options.MUTUAL-REQUIRED;
else
reset packet.ap-options.MUTUAL-REQUIRED;
endif
if (using session key for ticket) then
set packet.ap-options.USE-SESSION-KEY;
else
reset packet.ap-options.USE-SESSION-KEY;
endif
packet.ticket := ticket; /* チケット */
generate authenticator;
encode authenticator into OCTET STRING;
encrypt OCTET STRING into packet.authenticator
using session_key;
receive packet;
if (packet.pvno != 5) then
either process using other protocol spec
or error_out(KRB_AP_ERR_BADVERSION);
endif
if (packet.msg-type != KRB_AP_REQ) then
error_out(KRB_AP_ERR_MSG_TYPE);
endif
if (packet.ticket.tkt_vno != 5) then
either process using other protocol spec
or error_out(KRB_AP_ERR_BADVERSION);
endif
if (packet.ap_options.USE-SESSION-KEY is set) then
retrieve session key from ticket-granting ticket for
packet.ticket.{sname,srealm,enc-part.etype};
else
retrieve service key for
packet.ticket.{sname,srealm,enc-part.etype,enc-part.skvno};
endif
if (no_key_available) then
if (cannot_find_specified_skvno) then
error_out(KRB_AP_ERR_BADKEYVER);
else
error_out(KRB_AP_ERR_NOKEY);
endif
endif
decrypt packet.ticket.enc-part into decr_ticket
using retrieved key;
if (decryption_error()) then
error_out(KRB_AP_ERR_BAD_INTEGRITY);
endif
decrypt packet.authenticator into decr_authenticator
using decr_ticket.key;
if (decryption_error()) then
error_out(KRB_AP_ERR_BAD_INTEGRITY);
endif
if (decr_authenticator.{cname,crealm} !=
decr_ticket.{cname,crealm}) then
error_out(KRB_AP_ERR_BADMATCH);
endif
if (decr_ticket.caddr is present) then
if (sender_address(packet) is not in decr_ticket.caddr)
then error_out(KRB_AP_ERR_BADADDR);
endif
elseif (application requires addresses) then
error_out(KRB_AP_ERR_BADADDR);
endif
if (not in_clock_skew(decr_authenticator.ctime,
decr_authenticator.cusec)) then
error_out(KRB_AP_ERR_SKEW);
endif
if (repeated(decr_authenticator.{ctime,cusec,cname,crealm}))
then error_out(KRB_AP_ERR_REPEAT);
endif
save_identifier(decr_authenticator.{ctime,cusec,cname,crealm});
get system_time;
if ((decr_ticket.starttime-system_time > CLOCK_SKEW) or
(decr_ticket.flags.INVALID is set)) then
/* まだ有効になっていません。 */
error_out(KRB_AP_ERR_TKT_NYV);
endif
if (system_time-decr_ticket.endtime > CLOCK_SKEW) then
error_out(KRB_AP_ERR_TKT_EXPIRED);
endif
/* 呼出側は、関係する詳細がないかどうか */
/* decr_ticket.flags チェックしなければならない */
return(OK, decr_ticket, packet.ap_options.MUTUAL-REQUIRED);
packet.pvno := protocol version; /* 5 */
packet.msg-type := message type; /* KRB_AP_REP */
body.ctime := packet.ctime;
body.cusec := packet.cusec;
if (selecting sub-session key) then
select sub-session key;
body.subkey := sub-session key;
endif
if (using sequence numbers) then
select initial sequence number;
body.seq-number := initial sequence;
endif
encode body into OCTET STRING;
select encryption type;
encrypt OCTET STRING into packet.enc-part;
receive packet;
if (packet.pvno != 5) then
either process using other protocol spec
or error_out(KRB_AP_ERR_BADVERSION);
endif
if (packet.msg-type != KRB_AP_REP) then
error_out(KRB_AP_ERR_MSG_TYPE);
endif
cleartext := decrypt(packet.enc-part)
using ticket's session key;
if (decryption_error()) then
error_out(KRB_AP_ERR_BAD_INTEGRITY);
endif
if (cleartext.ctime != authenticator.ctime) then
error_out(KRB_AP_ERR_MUT_FAIL);
endif
if (cleartext.cusec != authenticator.cusec) then
error_out(KRB_AP_ERR_MUT_FAIL);
endif
if (cleartext.subkey is present) then
save cleartext.subkey for future use;
endif
if (cleartext.seq-number is present) then
save cleartext.seq-number for future verifications;
endif
return(AUTHENTICATION_SUCCEEDED);
collect user data in buffer;
/* パケットをアセンブルする: */
packet.pvno := protocol version; /* 5 */
packet.msg-type := message type; /* KRB_SAFE */
body.user-data := buffer; /* DATA */
if (using timestamp) then
get system_time;
body.timestamp, body.usec := system_time;
endif
if (using sequence numbers) then
body.seq-number := sequence number;
endif
body.s-address := sender host addresses;
if (only one recipient) then
body.r-address := recipient host address;
endif
checksum.cksumtype := checksum type;
compute checksum over body;
checksum.checksum := checksum value; /* checksum.checksum */
packet.cksum := checksum;
packet.safe-body := body;
receive packet;
if (packet.pvno != 5) then
either process using other protocol spec
or error_out(KRB_AP_ERR_BADVERSION);
endif
if (packet.msg-type != KRB_SAFE) then
error_out(KRB_AP_ERR_MSG_TYPE);
endif
if (packet.checksum.cksumtype is not both collision-proof
and keyed) then
error_out(KRB_AP_ERR_INAPP_CKSUM);
endif
if (safe_priv_common_checks_ok(packet)) then
set computed_checksum := checksum(packet.body);
if (computed_checksum != packet.checksum) then
error_out(KRB_AP_ERR_MODIFIED);
endif
return (packet, PACKET_IS_GENUINE);
else
return common_checks_error;
endif
A.15. KRB_SAFE および KRB_PRIV の一般チェック (English)
if (packet.s-address != O/S_sender(packet)) then
/* 送信を要求していない送信者の O/S レポート */
error_out(KRB_AP_ERR_BADADDR);
endif
if ((packet.r-address is present) and
(packet.r-address != local_host_address)) then
/* 適切な場所に送信されていない */
error_out(KRB_AP_ERR_BADADDR);
endif
if (((packet.timestamp is present) and
(not in_clock_skew(packet.timestamp,packet.usec))) or
(packet.timestamp is not present and timestamp expected))
then error_out(KRB_AP_ERR_SKEW);
endif
if (repeated(packet.timestamp,packet.usec,packet.s-address))
then error_out(KRB_AP_ERR_REPEAT);
endif
if (((packet.seq-number is present) and
((not in_sequence(packet.seq-number)))) or
(packet.seq-number is not present and sequence expected))
then error_out(KRB_AP_ERR_BADORDER);
endif
if (packet.timestamp not present and
packet.seq-number not present) then
error_out(KRB_AP_ERR_MODIFIED);
endif
save_identifier(packet.{timestamp,usec,s-address},
sender_principal(packet));
return PACKET_IS_OK;
collect user data in buffer;
/* パケットをアセンブルする: */
packet.pvno := protocol version; /* 5 */
packet.msg-type := message type; /* KRB_PRIV */
packet.enc-part.etype := encryption type;
body.user-data := buffer;
if (using timestamp) then
get system_time;
body.timestamp, body.usec := system_time;
endif
if (using sequence numbers) then
body.seq-number := sequence number;
endif
body.s-address := sender host addresses;
if (only one recipient) then
body.r-address := recipient host address;
endif
encode body into OCTET STRING;
select encryption type;
encrypt OCTET STRING into packet.enc-part.cipher;
receive packet;
if (packet.pvno != 5) then
either process using other protocol spec
or error_out(KRB_AP_ERR_BADVERSION);
endif
if (packet.msg-type != KRB_PRIV) then
error_out(KRB_AP_ERR_MSG_TYPE);
endif
cleartext := decrypt(packet.enc-part) using negotiated key;
if (decryption_error()) then
error_out(KRB_AP_ERR_BAD_INTEGRITY);
endif
if (safe_priv_common_checks_ok(cleartext)) then
return(cleartext.DATA, PACKET_IS_GENUINE_AND_UNMODIFIED);
else
return common_checks_error;
endif
invoke KRB_TGS; /* ピアに提供するチケットを取得する */
/* パケットをアセンブルする: */
packet.pvno := protocol version; /* 5 */
packet.msg-type := message type; /* KRB_CRED */
for (tickets[n] in tickets to be forwarded) do
packet.tickets[n] = tickets[n].ticket;
done
packet.enc-part.etype := encryption type;
for (ticket[n] in tickets to be forwarded) do
body.ticket-info[n].key = tickets[n].session;
body.ticket-info[n].prealm = tickets[n].crealm;
body.ticket-info[n].pname = tickets[n].cname;
body.ticket-info[n].flags = tickets[n].flags;
body.ticket-info[n].authtime = tickets[n].authtime;
body.ticket-info[n].starttime = tickets[n].starttime;
body.ticket-info[n].endtime = tickets[n].endtime;
body.ticket-info[n].renew-till = tickets[n].renew-till;
body.ticket-info[n].srealm = tickets[n].srealm;
body.ticket-info[n].sname = tickets[n].sname;
body.ticket-info[n].caddr = tickets[n].caddr;
done
get system_time;
body.timestamp, body.usec := system_time;
if (using nonce) then
body.nonce := nonce;
endif
if (using s-address) then
body.s-address := sender host addresses;
endif
if (limited recipients) then
body.r-address := recipient host address;
endif
encode body into OCTET STRING;
select encryption type;
encrypt OCTET STRING into packet.enc-part.cipher
using negotiated encryption key;
receive packet;
if (packet.pvno != 5) then
either process using other protocol spec
or error_out(KRB_AP_ERR_BADVERSION);
endif
if (packet.msg-type != KRB_CRED) then
error_out(KRB_AP_ERR_MSG_TYPE);
endif
cleartext := decrypt(packet.enc-part) using negotiated key;
if (decryption_error()) then
error_out(KRB_AP_ERR_BAD_INTEGRITY);
endif
if ((packet.r-address is present or required) and
(packet.s-address != O/S_sender(packet)) then
/* 送信を要求していない送信者の O/S レポート */
error_out(KRB_AP_ERR_BADADDR);
endif
if ((packet.r-address is present) and
(packet.r-address != local_host_address)) then
/* 適切な場所に送信されていない */
error_out(KRB_AP_ERR_BADADDR);
endif
if (not in_clock_skew(packet.timestamp,packet.usec)) then
error_out(KRB_AP_ERR_SKEW);
endif
if (repeated(packet.timestamp,packet.usec,packet.s-address))
then error_out(KRB_AP_ERR_REPEAT);
endif
if (packet.nonce is required or present) and
(packet.nonce != expected-nonce) then
error_out(KRB_AP_ERR_MODIFIED);
endif
for (ticket[n] in tickets that were forwarded) do
save_for_later(ticket[n],key[n],principal[n],
server[n],times[n],flags[n]);
return
/* パケットをアセンブルする: */
packet.pvno := protocol version; /* 5 */
packet.msg-type := message type; /* KRB_ERROR */
get system_time;
packet.stime, packet.susec := system_time;
packet.realm, packet.sname := server name;
if (client time available) then
packet.ctime, packet.cusec := client_time;
endif
packet.error-code := error code;
if (client name available) then
packet.cname, packet.crealm := client name;
endif
if (error text available) then
packet.e-text := error text;
endif
if (error data available) then
packet.e-data := error data;
endif