/* * src/lib/krb5/asn.1/asn1_k_encode.c * * Copyright 1994 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #include "asn1_k_encode.h" #include "asn1_make.h" #include "asn1_encode.h" #include /**** asn1 macros ****/ #if 0 How to write an asn1 encoder function using these macros: asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf, const krb5_type *val, int *retlen) { asn1_setup(); asn1_addfield(val->last_field, n, asn1_type); asn1_addfield(rep->next_to_last_field, n-1, asn1_type); ... /* for OPTIONAL fields */ if(rep->field_i == should_not_be_omitted) asn1_addfield(rep->field_i, i, asn1_type); /* for string fields (these encoders take an additional argument, the length of the string) */ addlenfield(rep->field_length, rep->field, i-1, asn1_type); /* if you really have to do things yourself... */ retval = asn1_encode_asn1_type(buf,rep->field,&length); if(retval) return retval; sum += length; retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag_number, length, &length); if(retval) return retval; sum += length; ... asn1_addfield(rep->second_field, 1, asn1_type); asn1_addfield(rep->first_field, 0, asn1_type); asn1_makeseq(); asn1_cleanup(); } #endif /* setup() -- create and initialize bookkeeping variables retval: stores error codes returned from subroutines length: length of the most-recently produced encoding sum: cumulative length of the entire encoding */ #define asn1_setup()\ asn1_error_code retval;\ unsigned int length, sum=0 /* asn1_addfield -- add a field, or component, to the encoding */ #define asn1_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; } /* asn1_addlenfield -- add a field whose length must be separately specified */ #define asn1_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; } /* form a sequence (by adding a sequence header to the current encoding) */ #define asn1_makeseq()\ retval = asn1_make_sequence(buf,sum,&length);\ if(retval){\ asn1buf_destroy(&buf);\ return retval; }\ sum += length /* add an APPLICATION class tag to the current encoding */ #define asn1_apptag(num)\ retval = asn1_make_etag(buf,APPLICATION,num,sum,&length);\ if(retval){\ asn1buf_destroy(&buf);\ return retval; }\ sum += length /* produce the final output and clean up the workspace */ #define asn1_cleanup()\ *retlen = sum;\ return 0 asn1_error_code asn1_encode_ui_4(asn1buf *buf, const krb5_ui_4 val, unsigned int *retlen) { return asn1_encode_unsigned_integer(buf,val,retlen); } asn1_error_code asn1_encode_realm(asn1buf *buf, const krb5_principal val, unsigned int *retlen) { if (val == NULL || (val->realm.length && val->realm.data == NULL)) return ASN1_MISSING_FIELD; return asn1_encode_generalstring(buf,val->realm.length,val->realm.data, retlen); } asn1_error_code asn1_encode_principal_name(asn1buf *buf, const krb5_principal val, unsigned int *retlen) { asn1_setup(); int n; if (val == NULL || val->data == NULL) return ASN1_MISSING_FIELD; for(n = (int) ((val->length)-1); n >= 0; n--){ if (val->data[n].length && val->data[n].data == NULL) return ASN1_MISSING_FIELD; retval = asn1_encode_generalstring(buf, (val->data)[n].length, (val->data)[n].data, &length); if(retval) return retval; sum += length; } asn1_makeseq(); retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,1,sum,&length); if(retval) return retval; sum += length; asn1_addfield(val->type,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_kerberos_time(asn1buf *buf, const krb5_timestamp val, unsigned int *retlen) { return asn1_encode_generaltime(buf,val,retlen); } asn1_error_code asn1_encode_host_address(asn1buf *buf, const krb5_address *val, unsigned int *retlen) { asn1_setup(); if (val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD; asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); asn1_addfield(val->addrtype,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_host_addresses(asn1buf *buf, const krb5_address **val, unsigned int *retlen) { asn1_setup(); int i; if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; for(i=0; val[i] != NULL; i++); /* go to end of array */ for(i--; i>=0; i--){ retval = asn1_encode_host_address(buf,val[i],&length); if(retval) return retval; sum += length; } asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_encrypted_data(asn1buf *buf, const krb5_enc_data *val, unsigned int *retlen) { asn1_setup(); if(val == NULL || (val->ciphertext.length && val->ciphertext.data == NULL)) return ASN1_MISSING_FIELD; asn1_addlenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_encode_charstring); /* krb5_kvno should be int */ if(val->kvno) asn1_addfield((int) val->kvno,1,asn1_encode_integer); asn1_addfield(val->enctype,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_krb5_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen) { asn1_setup(); krb5_flags valcopy = val; int i; for(i=0; i<4; i++){ retval = asn1buf_insert_octet(buf,(asn1_octet) (valcopy&0xFF)); if(retval) return retval; valcopy >>= 8; } retval = asn1buf_insert_octet(buf,0); /* 0 padding bits */ if(retval) return retval; sum = 5; retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_BITSTRING,sum, &length); if(retval) return retval; sum += length; *retlen = sum; return 0; } asn1_error_code asn1_encode_ap_options(asn1buf *buf, const krb5_flags val, unsigned int *retlen) { return asn1_encode_krb5_flags(buf,val,retlen); } asn1_error_code asn1_encode_ticket_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen) { return asn1_encode_krb5_flags(buf,val,retlen); } asn1_error_code asn1_encode_kdc_options(asn1buf *buf, const krb5_flags val, unsigned int *retlen) { return asn1_encode_krb5_flags(buf,val,retlen); } asn1_error_code asn1_encode_authorization_data(asn1buf *buf, const krb5_authdata **val, unsigned int *retlen) { asn1_setup(); int i; if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; for(i=0; val[i] != NULL; i++); /* get to the end of the array */ for(i--; i>=0; i--){ retval = asn1_encode_krb5_authdata_elt(buf,val[i],&length); if(retval) return retval; sum += length; } asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_krb5_authdata_elt(asn1buf *buf, const krb5_authdata *val, unsigned int *retlen) { asn1_setup(); if (val == NULL || (val->length && val->contents == NULL)) return ASN1_MISSING_FIELD; /* ad-data[1] OCTET STRING */ asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); /* ad-type[0] INTEGER */ asn1_addfield(val->ad_type,0,asn1_encode_integer); /* SEQUENCE */ asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_kdc_rep(int msg_type, asn1buf *buf, const krb5_kdc_rep *val, unsigned int *retlen) { asn1_setup(); if(val == NULL) return ASN1_MISSING_FIELD; asn1_addfield(&(val->enc_part),6,asn1_encode_encrypted_data); asn1_addfield(val->ticket,5,asn1_encode_ticket); asn1_addfield(val->client,4,asn1_encode_principal_name); asn1_addfield(val->client,3,asn1_encode_realm); if(val->padata != NULL && val->padata[0] != NULL) asn1_addfield((const krb5_pa_data**)val->padata,2,asn1_encode_sequence_of_pa_data); if (msg_type != KRB5_AS_REP && msg_type != KRB5_TGS_REP) return KRB5_BADMSGTYPE; asn1_addfield(msg_type,1,asn1_encode_integer); asn1_addfield(KVNO,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_enc_kdc_rep_part(asn1buf *buf, const krb5_enc_kdc_rep_part *val, unsigned int *retlen) { asn1_setup(); if(val == NULL) return ASN1_MISSING_FIELD; /* caddr[11] HostAddresses OPTIONAL */ if(val->caddrs != NULL && val->caddrs[0] != NULL) asn1_addfield((const krb5_address**)(val->caddrs),11,asn1_encode_host_addresses); /* sname[10] PrincipalName */ asn1_addfield(val->server,10,asn1_encode_principal_name); /* srealm[9] Realm */ asn1_addfield(val->server,9,asn1_encode_realm); /* renew-till[8] KerberosTime OPTIONAL */ if(val->flags & TKT_FLG_RENEWABLE) asn1_addfield(val->times.renew_till,8,asn1_encode_kerberos_time); /* endtime[7] KerberosTime */ asn1_addfield(val->times.endtime,7,asn1_encode_kerberos_time); /* starttime[6] KerberosTime OPTIONAL */ if(val->times.starttime) asn1_addfield(val->times.starttime,6,asn1_encode_kerberos_time); /* authtime[5] KerberosTime */ asn1_addfield(val->times.authtime,5,asn1_encode_kerberos_time); /* flags[4] TicketFlags */ asn1_addfield(val->flags,4,asn1_encode_ticket_flags); /* key-expiration[3] KerberosTime OPTIONAL */ if(val->key_exp) asn1_addfield(val->key_exp,3,asn1_encode_kerberos_time); /* nonce[2] INTEGER */ asn1_addfield(val->nonce,2,asn1_encode_integer); /* last-req[1] LastReq */ asn1_addfield((const krb5_last_req_entry**)val->last_req,1,asn1_encode_last_req); /* key[0] EncryptionKey */ asn1_addfield(val->session,0,asn1_encode_encryption_key); /* EncKDCRepPart ::= SEQUENCE */ asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_sequence_of_checksum(asn1buf *buf, const krb5_checksum ** val, unsigned int *retlen) { asn1_setup(); int i; if(val == NULL) return ASN1_MISSING_FIELD; for (i=0; val[i] != NULL; i++); for (i--; i>=0; i--){ retval = asn1_encode_checksum(buf,val[i],&length); if(retval) return retval; sum += length; } asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *rep, unsigned int *retlen) { asn1_setup(); if(rep == NULL) return ASN1_MISSING_FIELD; /* additional-tickets[11] SEQUENCE OF Ticket OPTIONAL */ if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL) asn1_addfield((const krb5_ticket**)rep->second_ticket, 11,asn1_encode_sequence_of_ticket); /* enc-authorization-data[10] EncryptedData OPTIONAL, */ /* -- Encrypted AuthorizationData encoding */ if(rep->authorization_data.ciphertext.data != NULL) asn1_addfield(&(rep->authorization_data),10,asn1_encode_encrypted_data); /* addresses[9] HostAddresses OPTIONAL, */ if(rep->addresses != NULL && rep->addresses[0] != NULL) asn1_addfield((const krb5_address**)rep->addresses,9,asn1_encode_host_addresses); /* etype[8] SEQUENCE OF INTEGER, -- EncryptionType, */ /* -- in preference order */ asn1_addlenfield(rep->nktypes,rep->ktype,8,asn1_encode_sequence_of_enctype); /* nonce[7] INTEGER, */ asn1_addfield(rep->nonce,7,asn1_encode_integer); /* rtime[6] KerberosTime OPTIONAL, */ if(rep->rtime) asn1_addfield(rep->rtime,6,asn1_encode_kerberos_time); /* till[5] KerberosTime, */ asn1_addfield(rep->till,5,asn1_encode_kerberos_time); /* from[4] KerberosTime OPTIONAL, */ if(rep->from) asn1_addfield(rep->from,4,asn1_encode_kerberos_time); /* sname[3] PrincipalName OPTIONAL, */ if(rep->server != NULL) asn1_addfield(rep->server,3,asn1_encode_principal_name); /* realm[2] Realm, -- Server's realm */ /* -- Also client's in AS-REQ */ if(rep->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY){ if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL){ asn1_addfield(rep->second_ticket[0]->server,2,asn1_encode_realm) } else return ASN1_MISSING_FIELD; }else if(rep->server != NULL){ asn1_addfield(rep->server,2,asn1_encode_realm); }else return ASN1_MISSING_FIELD; /* cname[1] PrincipalName OPTIONAL, */ /* -- Used only in AS-REQ */ if(rep->client != NULL) asn1_addfield(rep->client,1,asn1_encode_principal_name); /* kdc-options[0] KDCOptions, */ asn1_addfield(rep->kdc_options,0,asn1_encode_kdc_options); /* KDC-REQ-BODY ::= SEQUENCE */ asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_encryption_key(asn1buf *buf, const krb5_keyblock *val, unsigned int *retlen) { asn1_setup(); if (val == NULL || (val->length && val->contents == NULL)) return ASN1_MISSING_FIELD; asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); asn1_addfield(val->enctype,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_checksum(asn1buf *buf, const krb5_checksum *val, unsigned int *retlen) { asn1_setup(); if (val == NULL || (val->length && val->contents == NULL)) return ASN1_MISSING_FIELD; asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring); asn1_addfield(val->checksum_type,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_transited_encoding(asn1buf *buf, const krb5_transited *val, unsigned int *retlen) { asn1_setup(); if(val == NULL || (val->tr_contents.length != 0 && val->tr_contents.data == NULL)) return ASN1_MISSING_FIELD; asn1_addlenfield(val->tr_contents.length,val->tr_contents.data, 1,asn1_encode_charstring); asn1_addfield(val->tr_type,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_last_req(asn1buf *buf, const krb5_last_req_entry **val, unsigned int *retlen) { asn1_setup(); int i; if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; for(i=0; val[i] != NULL; i++); /* go to end of array */ for(i--; i>=0; i--){ retval = asn1_encode_last_req_entry(buf,val[i],&length); if(retval) return retval; sum += length; } asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_last_req_entry(asn1buf *buf, const krb5_last_req_entry *val, unsigned int *retlen) { asn1_setup(); if(val == NULL) return ASN1_MISSING_FIELD; asn1_addfield(val->value,1,asn1_encode_kerberos_time); asn1_addfield(val->lr_type,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_sequence_of_pa_data(asn1buf *buf, const krb5_pa_data **val, unsigned int *retlen) { asn1_setup(); int i; if (val == NULL) return ASN1_MISSING_FIELD; for(i=0; val[i] != NULL; i++); for(i--; i>=0; i--){ retval = asn1_encode_pa_data(buf,val[i],&length); if(retval) return retval; sum += length; } asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_pa_data(asn1buf *buf, const krb5_pa_data *val, unsigned int *retlen) { asn1_setup(); if(val == NULL || (val->length != 0 && val->contents == NULL)) return ASN1_MISSING_FIELD; asn1_addlenfield(val->length,val->contents,2,asn1_encode_octetstring); asn1_addfield(val->pa_type,1,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_sequence_of_ticket(asn1buf *buf, const krb5_ticket **val, unsigned int *retlen) { asn1_setup(); int i; if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; for(i=0; val[i] != NULL; i++); for(i--; i>=0; i--){ retval = asn1_encode_ticket(buf,val[i],&length); if(retval) return retval; sum += length; } asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_ticket(asn1buf *buf, const krb5_ticket *val, unsigned int *retlen) { asn1_setup(); if(val == NULL) return ASN1_MISSING_FIELD; asn1_addfield(&(val->enc_part),3,asn1_encode_encrypted_data); asn1_addfield(val->server,2,asn1_encode_principal_name); asn1_addfield(val->server,1,asn1_encode_realm); asn1_addfield(KVNO,0,asn1_encode_integer); asn1_makeseq(); asn1_apptag(1); asn1_cleanup(); } asn1_error_code asn1_encode_sequence_of_enctype(asn1buf *buf, const int len, const krb5_enctype *val, unsigned int *retlen) { asn1_setup(); int i; if(val == NULL) return ASN1_MISSING_FIELD; for(i=len-1; i>=0; i--){ retval = asn1_encode_integer(buf,val[i],&length); if(retval) return retval; sum += length; } asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_kdc_req(int msg_type, asn1buf *buf, const krb5_kdc_req *val, unsigned int *retlen) { asn1_setup(); if(val == NULL) return ASN1_MISSING_FIELD; asn1_addfield(val,4,asn1_encode_kdc_req_body); if(val->padata != NULL && val->padata[0] != NULL) asn1_addfield((const krb5_pa_data**)val->padata,3,asn1_encode_sequence_of_pa_data); if (msg_type != KRB5_AS_REQ && msg_type != KRB5_TGS_REQ) return KRB5_BADMSGTYPE; asn1_addfield(msg_type,2,asn1_encode_integer); asn1_addfield(KVNO,1,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_krb_safe_body(asn1buf *buf, const krb5_safe *val, unsigned int *retlen) { asn1_setup(); if(val == NULL) return ASN1_MISSING_FIELD; if(val->r_address != NULL) asn1_addfield(val->r_address,5,asn1_encode_host_address); asn1_addfield(val->s_address,4,asn1_encode_host_address); if(val->seq_number) asn1_addfield(val->seq_number,3,asn1_encode_unsigned_integer); if(val->timestamp){ asn1_addfield(val->usec,2,asn1_encode_integer); asn1_addfield(val->timestamp,1,asn1_encode_kerberos_time); } if (val->user_data.length && val->user_data.data == NULL) return ASN1_MISSING_FIELD; asn1_addlenfield(val->user_data.length,val->user_data.data,0,asn1_encode_charstring) ; asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_sequence_of_krb_cred_info(asn1buf *buf, const krb5_cred_info **val, unsigned int *retlen) { asn1_setup(); int i; if(val == NULL) return ASN1_MISSING_FIELD; for(i=0; val[i] != NULL; i++); for(i--; i>=0; i--){ retval = asn1_encode_krb_cred_info(buf,val[i],&length); if(retval) return retval; sum += length; } asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_krb_cred_info(asn1buf *buf, const krb5_cred_info *val, unsigned int *retlen) { asn1_setup(); if(val == NULL) return ASN1_MISSING_FIELD; if(val->caddrs != NULL && val->caddrs[0] != NULL) asn1_addfield((const krb5_address**)val->caddrs,10,asn1_encode_host_addresses); if(val->server != NULL){ asn1_addfield(val->server,9,asn1_encode_principal_name); asn1_addfield(val->server,8,asn1_encode_realm); } if(val->times.renew_till) asn1_addfield(val->times.renew_till,7,asn1_encode_kerberos_time); if(val->times.endtime) asn1_addfield(val->times.endtime,6,asn1_encode_kerberos_time); if(val->times.starttime) asn1_addfield(val->times.starttime,5,asn1_encode_kerberos_time); if(val->times.authtime) asn1_addfield(val->times.authtime,4,asn1_encode_kerberos_time); if(val->flags) asn1_addfield(val->flags,3,asn1_encode_ticket_flags); if(val->client != NULL){ asn1_addfield(val->client,2,asn1_encode_principal_name); asn1_addfield(val->client,1,asn1_encode_realm); } asn1_addfield(val->session,0,asn1_encode_encryption_key); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_etype_info_entry(asn1buf *buf, const krb5_etype_info_entry *val, unsigned int *retlen, int etype_info2) { asn1_setup(); assert(val->s2kparams.data == NULL || etype_info2); if(val == NULL || (val->length > 0 && val->length != KRB5_ETYPE_NO_SALT && val->salt == NULL)) return ASN1_MISSING_FIELD; if(val->s2kparams.data != NULL) asn1_addlenfield(val->s2kparams.length, val->s2kparams.data, 2, asn1_encode_octetstring); if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT){ if (etype_info2) asn1_addlenfield(val->length,val->salt,1, asn1_encode_generalstring) else asn1_addlenfield(val->length,val->salt,1, asn1_encode_octetstring); } asn1_addfield(val->etype,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_etype_info(asn1buf *buf, const krb5_etype_info_entry **val, unsigned int *retlen, int etype_info2) { asn1_setup(); int i; if (val == NULL) return ASN1_MISSING_FIELD; for(i=0; val[i] != NULL; i++); /* get to the end of the array */ for(i--; i>=0; i--){ retval = asn1_encode_etype_info_entry(buf,val[i],&length, etype_info2); if(retval) return retval; sum += length; } asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_sequence_of_passwdsequence(asn1buf *buf, const passwd_phrase_element **val, unsigned int *retlen) { asn1_setup(); int i; if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; for(i=0; val[i] != NULL; i++); /* get to the end of the array */ for(i--; i>=0; i--){ retval = asn1_encode_passwdsequence(buf,val[i],&length); if(retval) return retval; sum += length; } asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_passwdsequence(asn1buf *buf, const passwd_phrase_element *val, unsigned int *retlen) { asn1_setup(); asn1_addlenfield(val->phrase->length,val->phrase->data,1,asn1_encode_charstring); asn1_addlenfield(val->passwd->length,val->passwd->data,0,asn1_encode_charstring); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_sam_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen) { return asn1_encode_krb5_flags(buf,val,retlen); } #define add_optstring(val,n,fn) \ if ((val).length > 0) {asn1_addlenfield((val).length,(val).data,n,fn);} asn1_error_code asn1_encode_sam_challenge(asn1buf *buf, const krb5_sam_challenge *val, unsigned int *retlen) { asn1_setup(); /* possibly wrong */ if (val->sam_cksum.length) asn1_addfield(&(val->sam_cksum),9,asn1_encode_checksum); if (val->sam_nonce) asn1_addfield(val->sam_nonce,8,asn1_encode_integer); add_optstring(val->sam_pk_for_sad,7,asn1_encode_charstring); add_optstring(val->sam_response_prompt,6,asn1_encode_charstring); add_optstring(val->sam_challenge,5,asn1_encode_charstring); add_optstring(val->sam_challenge_label,4,asn1_encode_charstring); add_optstring(val->sam_track_id,3,asn1_encode_charstring); add_optstring(val->sam_type_name,2,asn1_encode_charstring); asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); asn1_addfield(val->sam_type,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_sam_challenge_2(asn1buf *buf, const krb5_sam_challenge_2 *val, unsigned int *retlen) { asn1_setup(); if ( (!val) || (!val->sam_cksum) || (!val->sam_cksum[0])) return ASN1_MISSING_FIELD; asn1_addfield((const krb5_checksum **) val->sam_cksum, 1, asn1_encode_sequence_of_checksum); retval = asn1buf_insert_octetstring(buf, val->sam_challenge_2_body.length, (unsigned char *)val->sam_challenge_2_body.data); if(retval){ asn1buf_destroy(&buf); return retval; } sum += val->sam_challenge_2_body.length; retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, val->sam_challenge_2_body.length, &length); if(retval) { asn1buf_destroy(&buf); return retval; } sum += length; asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_sam_challenge_2_body(asn1buf *buf, const krb5_sam_challenge_2_body *val, unsigned int *retlen) { asn1_setup(); asn1_addfield(val->sam_etype, 9, asn1_encode_integer); asn1_addfield(val->sam_nonce,8,asn1_encode_integer); add_optstring(val->sam_pk_for_sad,7,asn1_encode_charstring); add_optstring(val->sam_response_prompt,6,asn1_encode_charstring); add_optstring(val->sam_challenge,5,asn1_encode_charstring); add_optstring(val->sam_challenge_label,4,asn1_encode_charstring); add_optstring(val->sam_track_id,3,asn1_encode_charstring); add_optstring(val->sam_type_name,2,asn1_encode_charstring); asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); asn1_addfield(val->sam_type,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_sam_key(asn1buf *buf, const krb5_sam_key *val, unsigned int *retlen) { asn1_setup(); asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_enc_sam_response_enc(asn1buf *buf, const krb5_enc_sam_response_enc *val, unsigned int *retlen) { asn1_setup(); add_optstring(val->sam_sad,3,asn1_encode_charstring); asn1_addfield(val->sam_usec,2,asn1_encode_integer); asn1_addfield(val->sam_timestamp,1,asn1_encode_kerberos_time); asn1_addfield(val->sam_nonce,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_enc_sam_response_enc_2(asn1buf *buf, const krb5_enc_sam_response_enc_2 *val, unsigned int *retlen) { asn1_setup(); add_optstring(val->sam_sad,1,asn1_encode_charstring); asn1_addfield(val->sam_nonce,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_sam_response(asn1buf *buf, const krb5_sam_response *val, unsigned int *retlen) { asn1_setup(); if (val->sam_patimestamp) asn1_addfield(val->sam_patimestamp,6,asn1_encode_kerberos_time); if (val->sam_nonce) asn1_addfield(val->sam_nonce,5,asn1_encode_integer); asn1_addfield(&(val->sam_enc_nonce_or_ts),4,asn1_encode_encrypted_data); if (val->sam_enc_key.ciphertext.length) asn1_addfield(&(val->sam_enc_key),3,asn1_encode_encrypted_data); add_optstring(val->sam_track_id,2,asn1_encode_charstring); asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); asn1_addfield(val->sam_type,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_sam_response_2(asn1buf *buf, const krb5_sam_response_2 *val, unsigned int *retlen) { asn1_setup(); asn1_addfield(val->sam_nonce,4,asn1_encode_integer); asn1_addfield(&(val->sam_enc_nonce_or_sad),3,asn1_encode_encrypted_data); add_optstring(val->sam_track_id,2,asn1_encode_charstring); asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); asn1_addfield(val->sam_type,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); } asn1_error_code asn1_encode_predicted_sam_response(asn1buf *buf, const krb5_predicted_sam_response *val, unsigned int *retlen) { asn1_setup(); add_optstring(val->msd,6,asn1_encode_charstring); asn1_addfield(val->client,5,asn1_encode_principal_name); asn1_addfield(val->client,4,asn1_encode_realm); asn1_addfield(val->susec,3,asn1_encode_integer); asn1_addfield(val->stime,2,asn1_encode_kerberos_time); asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags); asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key); asn1_makeseq(); asn1_cleanup(); } /* * Do some ugliness to insert a raw pre-encoded KRB-SAFE-BODY. */ asn1_error_code asn1_encode_krb_saved_safe_body(asn1buf *buf, const krb5_data *body, unsigned int *retlen) { asn1_error_code retval; retval = asn1buf_insert_octetstring(buf, body->length, (krb5_octet *)body->data); if (retval){ asn1buf_destroy(&buf); return retval; } *retlen = body->length; return 0; }