#include "krb5.h"
#include "asn1_k_encode.h"
#include "asn1_encode.h"
#include "krbasn1.h"
#include "asn1buf.h"
#include "asn1_make.h"
#if 0
How to write a krb5 encoder function using these macros:
asn1_error_code encode_krb5_structure(const krb5_type *rep,
krb5_data **code)
{
krb5_setup();
krb5_addfield(rep->last_field, n, asn1_type);
krb5_addfield(rep->next_to_last_field, n-1, asn1_type);
...
if(rep->field_i == should_not_be_omitted)
krb5_addfield(rep->field_i, i, asn1_type);
addlenfield(rep->field_length, rep->field, i-1, asn1_type);
retval = asn1_encode_asn1_type(buf,rep->field,&length);
if(retval) return retval;
sum += length;
retval = asn1_make_etag(buf,
[UNIVERSAL/APPLICATION/CONTEXT_SPECIFIC/PRIVATE],
tag_number, length, &length);
if(retval) return retval;
sum += length;
...
krb5_addfield(rep->second_field, 1, asn1_type);
krb5_addfield(rep->first_field, 0, asn1_type);
krb5_makeseq();
krb5_apptag(tag_number);
krb5_cleanup();
}
#endif
#define krb5_setup()\
asn1_error_code retval;\
asn1buf *buf=NULL;\
unsigned int length, sum=0;\
\
if(rep == NULL) return ASN1_MISSING_FIELD;\
\
retval = asn1buf_create(&buf);\
if(retval) return retval
#define krb5_addfield(value,tag,encoder)\
{ retval = encoder(buf,value,&length);\
if(retval){\
asn1buf_destroy(&buf);\
return retval; }\
sum += length;\
retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
if(retval){\
asn1buf_destroy(&buf);\
return retval; }\
sum += length; }
#define krb5_addlenfield(len,value,tag,encoder)\
{ retval = encoder(buf,len,value,&length);\
if(retval){\
asn1buf_destroy(&buf);\
return retval; }\
sum += length;\
retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
if(retval){\
asn1buf_destroy(&buf);\
return retval; }\
sum += length; }
#define krb5_makeseq()\
retval = asn1_make_sequence(buf,sum,&length);\
if(retval){\
asn1buf_destroy(&buf);\
return retval; }\
sum += length
#define krb5_apptag(num)\
retval = asn1_make_etag(buf,APPLICATION,num,sum,&length);\
if(retval){\
asn1buf_destroy(&buf);\
return retval; }\
sum += length
#define krb5_cleanup()\
retval = asn12krb5_buf(buf,code);\
if(retval){\
asn1buf_destroy(&buf);\
return retval; }\
retval = asn1buf_destroy(&buf);\
if(retval){\
return retval; }\
\
return 0
krb5_error_code encode_krb5_authenticator(const krb5_authenticator *rep, krb5_data **code)
{
krb5_setup();
if(rep->authorization_data != NULL &&
rep->authorization_data[0] != NULL){
retval = asn1_encode_authorization_data(buf, (const krb5_authdata **)
rep->authorization_data,
&length);
if(retval){
asn1buf_destroy(&buf);
return retval; }
sum += length;
retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,8,length,&length);
if(retval){
asn1buf_destroy(&buf);
return retval; }
sum += length;
}
if(rep->seq_number != 0)
krb5_addfield(rep->seq_number,7,asn1_encode_unsigned_integer);
if(rep->subkey != NULL)
krb5_addfield(rep->subkey,6,asn1_encode_encryption_key);
krb5_addfield(rep->ctime,5,asn1_encode_kerberos_time);
krb5_addfield(rep->cusec,4,asn1_encode_integer);
if(rep->checksum != NULL)
krb5_addfield(rep->checksum,3,asn1_encode_checksum);
krb5_addfield(rep->client,2,asn1_encode_principal_name);
krb5_addfield(rep->client,1,asn1_encode_realm);
krb5_addfield(KVNO,0,asn1_encode_integer);
krb5_makeseq();
krb5_apptag(2);
krb5_cleanup();
}
krb5_error_code encode_krb5_ticket(const krb5_ticket *rep, krb5_data **code)
{
krb5_setup();
krb5_addfield(&(rep->enc_part),3,asn1_encode_encrypted_data);
krb5_addfield(rep->server,2,asn1_encode_principal_name);
krb5_addfield(rep->server,1,asn1_encode_realm);
krb5_addfield(KVNO,0,asn1_encode_integer);
krb5_makeseq();
krb5_apptag(1);
krb5_cleanup();
}
krb5_error_code encode_krb5_encryption_key(const krb5_keyblock *rep, krb5_data **code)
{
krb5_setup();
krb5_addlenfield(rep->length,rep->contents,1,asn1_encode_octetstring);
krb5_addfield(rep->enctype,0,asn1_encode_integer);
krb5_makeseq();
krb5_cleanup();
}
krb5_error_code encode_krb5_enc_tkt_part(const krb5_enc_tkt_part *rep, krb5_data **code)
{
krb5_setup();
if(rep->authorization_data != NULL &&
rep->authorization_data[0] != NULL)
krb5_addfield((const krb5_authdata**)rep->authorization_data,
10,asn1_encode_authorization_data);
if(rep->caddrs != NULL && rep->caddrs[0] != NULL)
krb5_addfield((const krb5_address**)rep->caddrs,9,asn1_encode_host_addresses);
if(rep->times.renew_till)
krb5_addfield(rep->times.renew_till,8,asn1_encode_kerberos_time);
krb5_addfield(rep->times.endtime,7,asn1_encode_kerberos_time);
if(rep->times.starttime)
krb5_addfield(rep->times.starttime,6,asn1_encode_kerberos_time);
krb5_addfield(rep->times.authtime,5,asn1_encode_kerberos_time);
krb5_addfield(&(rep->transited),4,asn1_encode_transited_encoding);
krb5_addfield(rep->client,3,asn1_encode_principal_name);
krb5_addfield(rep->client,2,asn1_encode_realm);
krb5_addfield(rep->session,1,asn1_encode_encryption_key);
krb5_addfield(rep->flags,0,asn1_encode_ticket_flags);
krb5_makeseq();
krb5_apptag(3);
krb5_cleanup();
}
krb5_error_code encode_krb5_enc_kdc_rep_part(const krb5_enc_kdc_rep_part *rep, krb5_data **code)
{
asn1_error_code retval;
asn1buf *buf=NULL;
unsigned int length, sum=0;
if(rep == NULL) return ASN1_MISSING_FIELD;
retval = asn1buf_create(&buf);
if(retval) return retval;
retval = asn1_encode_enc_kdc_rep_part(buf,rep,&length);
if(retval) return retval;
sum += length;
#ifdef KRB5_ENCKRB5KDCREPPART_COMPAT
krb5_apptag(26);
#else
if (rep->msg_type == KRB5_AS_REP) { krb5_apptag(ASN1_KRB_AS_REP); }
else if (rep->msg_type == KRB5_TGS_REP) { krb5_apptag(ASN1_KRB_TGS_REP); }
else return KRB5_BADMSGTYPE;
#endif
krb5_cleanup();
}
krb5_error_code encode_krb5_as_rep(const krb5_kdc_rep *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_kdc_rep(KRB5_AS_REP,buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_apptag(11);
krb5_cleanup();
}
krb5_error_code encode_krb5_tgs_rep(const krb5_kdc_rep *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_kdc_rep(KRB5_TGS_REP,buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_apptag(13);
krb5_cleanup();
}
krb5_error_code encode_krb5_ap_req(const krb5_ap_req *rep, krb5_data **code)
{
krb5_setup();
krb5_addfield(&(rep->authenticator),4,asn1_encode_encrypted_data);
krb5_addfield(rep->ticket,3,asn1_encode_ticket);
krb5_addfield(rep->ap_options,2,asn1_encode_ap_options);
krb5_addfield(ASN1_KRB_AP_REQ,1,asn1_encode_integer);
krb5_addfield(KVNO,0,asn1_encode_integer);
krb5_makeseq();
krb5_apptag(14);
krb5_cleanup();
}
krb5_error_code encode_krb5_ap_rep(const krb5_ap_rep *rep, krb5_data **code)
{
krb5_setup();
krb5_addfield(&(rep->enc_part),2,asn1_encode_encrypted_data);
krb5_addfield(ASN1_KRB_AP_REP,1,asn1_encode_integer);
krb5_addfield(KVNO,0,asn1_encode_integer);
krb5_makeseq();
krb5_apptag(15);
krb5_cleanup();
}
krb5_error_code encode_krb5_ap_rep_enc_part(const krb5_ap_rep_enc_part *rep, krb5_data **code)
{
krb5_setup();
if(rep->seq_number)
krb5_addfield(rep->seq_number,3,asn1_encode_unsigned_integer);
if(rep->subkey != NULL)
krb5_addfield(rep->subkey,2,asn1_encode_encryption_key);
krb5_addfield(rep->cusec,1,asn1_encode_integer);
krb5_addfield(rep->ctime,0,asn1_encode_kerberos_time);
krb5_makeseq();
krb5_apptag(27);
krb5_cleanup();
}
krb5_error_code encode_krb5_as_req(const krb5_kdc_req *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_kdc_req(KRB5_AS_REQ,buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_apptag(10);
krb5_cleanup();
}
krb5_error_code encode_krb5_tgs_req(const krb5_kdc_req *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_kdc_req(KRB5_TGS_REQ,buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_apptag(12);
krb5_cleanup();
}
krb5_error_code encode_krb5_kdc_req_body(const krb5_kdc_req *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_kdc_req_body(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_safe(const krb5_safe *rep, krb5_data **code)
{
krb5_setup();
krb5_addfield(rep->checksum,3,asn1_encode_checksum);
krb5_addfield(rep,2,asn1_encode_krb_safe_body);
krb5_addfield(ASN1_KRB_SAFE,1,asn1_encode_integer);
krb5_addfield(KVNO,0,asn1_encode_integer);
krb5_makeseq();
krb5_apptag(20);
krb5_cleanup();
}
krb5_error_code encode_krb5_safe_with_body(
const krb5_safe *rep,
const krb5_data *body,
krb5_data **code)
{
krb5_setup();
if (body == NULL) {
asn1buf_destroy(&buf);
return ASN1_MISSING_FIELD;
}
krb5_addfield(rep->checksum,3,asn1_encode_checksum);
krb5_addfield(body,2,asn1_encode_krb_saved_safe_body);
krb5_addfield(ASN1_KRB_SAFE,1,asn1_encode_integer);
krb5_addfield(KVNO,0,asn1_encode_integer);
krb5_makeseq();
krb5_apptag(20);
krb5_cleanup();
}
krb5_error_code encode_krb5_priv(const krb5_priv *rep, krb5_data **code)
{
krb5_setup();
krb5_addfield(&(rep->enc_part),3,asn1_encode_encrypted_data);
krb5_addfield(ASN1_KRB_PRIV,1,asn1_encode_integer);
krb5_addfield(KVNO,0,asn1_encode_integer);
krb5_makeseq();
krb5_apptag(21);
krb5_cleanup();
}
krb5_error_code encode_krb5_enc_priv_part(const krb5_priv_enc_part *rep, krb5_data **code)
{
krb5_setup();
if(rep->r_address)
krb5_addfield(rep->r_address,5,asn1_encode_host_address);
krb5_addfield(rep->s_address,4,asn1_encode_host_address);
if(rep->seq_number)
krb5_addfield(rep->seq_number,3,asn1_encode_unsigned_integer);
if(rep->timestamp){
krb5_addfield(rep->usec,2,asn1_encode_integer);
krb5_addfield(rep->timestamp,1,asn1_encode_kerberos_time);
}
krb5_addlenfield(rep->user_data.length,rep->user_data.data,0,asn1_encode_charstring);
krb5_makeseq();
krb5_apptag(28);
krb5_cleanup();
}
krb5_error_code encode_krb5_cred(const krb5_cred *rep, krb5_data **code)
{
krb5_setup();
krb5_addfield(&(rep->enc_part),3,asn1_encode_encrypted_data);
krb5_addfield((const krb5_ticket**)rep->tickets,2,asn1_encode_sequence_of_ticket);
krb5_addfield(ASN1_KRB_CRED,1,asn1_encode_integer);
krb5_addfield(KVNO,0,asn1_encode_integer);
krb5_makeseq();
krb5_apptag(22);
krb5_cleanup();
}
krb5_error_code encode_krb5_enc_cred_part(const krb5_cred_enc_part *rep, krb5_data **code)
{
krb5_setup();
if(rep->r_address != NULL)
krb5_addfield(rep->r_address,5,asn1_encode_host_address);
if(rep->s_address != NULL)
krb5_addfield(rep->s_address,4,asn1_encode_host_address);
if(rep->timestamp){
krb5_addfield(rep->usec,3,asn1_encode_integer);
krb5_addfield(rep->timestamp,2,asn1_encode_kerberos_time);
}
if(rep->nonce)
krb5_addfield(rep->nonce,1,asn1_encode_integer);
krb5_addfield((const krb5_cred_info**)rep->ticket_info,
0,asn1_encode_sequence_of_krb_cred_info);
krb5_makeseq();
krb5_apptag(29);
krb5_cleanup();
}
krb5_error_code encode_krb5_error(const krb5_error *rep, krb5_data **code)
{
krb5_setup();
if(rep->e_data.data != NULL && rep->e_data.length > 0)
krb5_addlenfield(rep->e_data.length,rep->e_data.data,12,asn1_encode_charstring);
if(rep->text.data != NULL && rep->text.length > 0)
krb5_addlenfield(rep->text.length,rep->text.data,11,asn1_encode_generalstring);
krb5_addfield(rep->server,10,asn1_encode_principal_name);
krb5_addfield(rep->server,9,asn1_encode_realm);
if(rep->client != NULL){
krb5_addfield(rep->client,8,asn1_encode_principal_name);
krb5_addfield(rep->client,7,asn1_encode_realm);
}
krb5_addfield(rep->error,6,asn1_encode_ui_4);
krb5_addfield(rep->susec,5,asn1_encode_integer);
krb5_addfield(rep->stime,4,asn1_encode_kerberos_time);
if(rep->cusec)
krb5_addfield(rep->cusec,3,asn1_encode_integer);
if(rep->ctime)
krb5_addfield(rep->ctime,2,asn1_encode_kerberos_time);
krb5_addfield(ASN1_KRB_ERROR,1,asn1_encode_integer);
krb5_addfield(KVNO,0,asn1_encode_integer);
krb5_makeseq();
krb5_apptag(30);
krb5_cleanup();
}
krb5_error_code encode_krb5_authdata(const krb5_authdata **rep, krb5_data **code)
{
asn1_error_code retval;
asn1buf *buf=NULL;
unsigned int length;
if(rep == NULL) return ASN1_MISSING_FIELD;
retval = asn1buf_create(&buf);
if(retval) return retval;
retval = asn1_encode_authorization_data(buf,(const krb5_authdata**)rep,
&length);
if(retval) return retval;
krb5_cleanup();
}
krb5_error_code encode_krb5_alt_method(const krb5_alt_method *rep, krb5_data **code)
{
krb5_setup();
if(rep->data != NULL && rep->length > 0)
krb5_addlenfield(rep->length,rep->data,1,asn1_encode_octetstring);
krb5_addfield(rep->method,0,asn1_encode_integer);
krb5_makeseq();
krb5_cleanup();
}
krb5_error_code encode_krb5_etype_info(const krb5_etype_info_entry **rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_etype_info(buf,rep,&length, 0);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_etype_info2(const krb5_etype_info_entry **rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_etype_info(buf,rep,&length, 1);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_enc_data(const krb5_enc_data *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_encrypted_data(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_pa_enc_ts(const krb5_pa_enc_ts *rep, krb5_data **code)
{
krb5_setup();
if (rep->pausec)
krb5_addfield(rep->pausec,1,asn1_encode_integer);
krb5_addfield(rep->patimestamp,0,asn1_encode_kerberos_time);
krb5_makeseq();
krb5_cleanup();
}
krb5_error_code encode_krb5_pwd_sequence(const passwd_phrase_element *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_passwdsequence(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_pwd_data(const krb5_pwd_data *rep, krb5_data **code)
{
krb5_setup();
krb5_addfield((const passwd_phrase_element**)rep->element,1,asn1_encode_sequence_of_passwdsequence);
krb5_addfield(rep->sequence_count,0,asn1_encode_integer);
krb5_makeseq();
krb5_cleanup();
}
krb5_error_code encode_krb5_padata_sequence(const krb5_pa_data **rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_sequence_of_pa_data(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_sam_challenge(const krb5_sam_challenge *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_sam_challenge(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_sam_challenge_2(const krb5_sam_challenge_2 *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_sam_challenge_2(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_sam_challenge_2_body(const krb5_sam_challenge_2_body *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_sam_challenge_2_body(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_sam_key(const krb5_sam_key *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_sam_key(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_enc_sam_response_enc(const krb5_enc_sam_response_enc *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_enc_sam_response_enc(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_enc_sam_response_enc_2(const krb5_enc_sam_response_enc_2 *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_enc_sam_response_enc_2(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_sam_response(const krb5_sam_response *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_sam_response(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_sam_response_2(const krb5_sam_response_2 *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_sam_response_2(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_predicted_sam_response(const krb5_predicted_sam_response *rep, krb5_data **code)
{
krb5_setup();
retval = asn1_encode_predicted_sam_response(buf,rep,&length);
if(retval) return retval;
sum += length;
krb5_cleanup();
}
krb5_error_code encode_krb5_setpw_req(const krb5_principal target,
char *password, krb5_data **code)
{
const char *rep = "dummy string";
krb5_setup();
krb5_addfield(target,2,asn1_encode_realm);
krb5_addfield(target,1,asn1_encode_principal_name);
krb5_addlenfield(strlen(password), password,0,asn1_encode_octetstring);
krb5_makeseq();
krb5_cleanup();
}