From c52cfef9abd88edc151fd3ec7cb2467db740fbe8 Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Mon, 13 Apr 2009 20:26:35 +0000 Subject: [PATCH] pull up r21927, r21928, r21940, r21969, r21981, r22004 from trunk ------------------------------------------------------------------------ r22004 | ghudson | 2009-02-13 17:05:48 -0500 (Fri, 13 Feb 2009) | 3 lines Changed paths: M /trunk/src/lib/krb5/asn.1/asn1_k_decode.c M /trunk/src/lib/krb5/asn.1/asn1_k_decode.h M /trunk/src/lib/krb5/asn.1/krb5_decode.c Correct numerous memory leaks on error conditions in the ASN.1 decoder functions. ------------------------------------------------------------------------ r21981 | ghudson | 2009-02-12 13:21:33 -0500 (Thu, 12 Feb 2009) | 4 lines Changed paths: M /trunk/src/lib/krb5/asn.1/asn1_encode.c M /trunk/src/lib/krb5/asn.1/asn1buf.c Modify asn12krb5_buf and asn1_do_full_encode to make output parameter values well-defined on error. Clean up memory handling and an unused variable in asn1_do_full_encode. ------------------------------------------------------------------------ r21969 | ghudson | 2009-02-11 15:18:43 -0500 (Wed, 11 Feb 2009) | 6 lines Changed paths: M /trunk/src/include/k5-int.h M /trunk/src/lib/krb5/krb/kfree.c M /trunk/src/lib/krb5/libkrb5.exports Ensure we have a free function for every data type we have an ASN.1 decoder for. Export the new free functions, but only declare them in k5-int.h since they shouldn't be needed by applications. Also export a couple of encoder and decoder functions not previously exported. ------------------------------------------------------------------------ r21940 | ghudson | 2009-02-09 21:01:58 -0500 (Mon, 09 Feb 2009) | 5 lines Changed paths: M /trunk/src/lib/krb5/asn.1/krb5_decode.c Adjust the structure of krb5_decode.c functions to initialize output parameters to NULL and not set them to the real values until a successful return is guaranteed. Also fix get_eoc which was returning without clean_return. ------------------------------------------------------------------------ r21928 | ghudson | 2009-02-09 16:25:53 -0500 (Mon, 09 Feb 2009) | 4 lines Changed paths: M /trunk/src/lib/krb5/asn.1/asn1buf.c M /trunk/src/lib/krb5/asn.1/asn1buf.h M /trunk/src/lib/krb5/asn.1/krb5_encode.c Make asn1buf_destroy return void, since it's a free function. In krb5_encode.c functions, make *code well-defined in case of error, and clean up some memory leaks. ------------------------------------------------------------------------ r21927 | ghudson | 2009-02-09 16:23:00 -0500 (Mon, 09 Feb 2009) | 3 lines Changed paths: M /trunk/src/lib/krb5/asn.1/asn1_k_encode.c In asn1_k_encode.c, stop inconsistently destroying buf on some errors. It belongs to the caller. ticket: 6425 version_fixed: 1.7 git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-7@22207 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/k5-int.h | 6 + src/lib/krb5/asn.1/asn1_encode.c | 16 +- src/lib/krb5/asn.1/asn1_k_decode.c | 1094 ++++++++++++++++++++++------ src/lib/krb5/asn.1/asn1_k_decode.h | 26 + src/lib/krb5/asn.1/asn1_k_encode.c | 30 +- src/lib/krb5/asn.1/asn1buf.c | 32 +- src/lib/krb5/asn.1/asn1buf.h | 2 +- src/lib/krb5/asn.1/krb5_decode.c | 892 +++++++++++++---------- src/lib/krb5/asn.1/krb5_encode.c | 41 +- src/lib/krb5/krb/kfree.c | 43 +- src/lib/krb5/libkrb5.exports | 8 + 11 files changed, 1507 insertions(+), 683 deletions(-) diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 2a73127bd..2b937112d 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -2537,6 +2537,12 @@ void KRB5_CALLCONV krb5_free_pwd_data (krb5_context, krb5_pwd_data *); void KRB5_CALLCONV krb5_free_pwd_sequences (krb5_context, passwd_phrase_element **); +void KRB5_CALLCONV krb5_free_passwd_phrase_element + (krb5_context, passwd_phrase_element *); +void KRB5_CALLCONV krb5_free_alt_method + (krb5_context, krb5_alt_method *); +void KRB5_CALLCONV krb5_free_enc_data + (krb5_context, krb5_enc_data *); krb5_error_code krb5_set_config_files (krb5_context, const char **); diff --git a/src/lib/krb5/asn.1/asn1_encode.c b/src/lib/krb5/asn.1/asn1_encode.c index d79546493..f67c8cfee 100644 --- a/src/lib/krb5/asn.1/asn1_encode.c +++ b/src/lib/krb5/asn.1/asn1_encode.c @@ -675,10 +675,13 @@ krb5int_asn1_do_full_encode(const void *rep, krb5_data **code, { unsigned int length; asn1_error_code retval; - unsigned int sum = 0; asn1buf *buf = NULL; + krb5_data *d; + + *code = NULL; - if (rep == NULL) return ASN1_MISSING_FIELD; + if (rep == NULL) + return ASN1_MISSING_FIELD; retval = asn1buf_create(&buf); if (retval) @@ -686,9 +689,12 @@ krb5int_asn1_do_full_encode(const void *rep, krb5_data **code, retval = krb5int_asn1_encode_a_thing(buf, rep, a, &length); if (retval) - return retval; - sum += length; - retval = asn12krb5_buf(buf, code); + goto cleanup; + retval = asn12krb5_buf(buf, &d); + if (retval) + goto cleanup; + *code = d; +cleanup: asn1buf_destroy(&buf); return retval; } diff --git a/src/lib/krb5/asn.1/asn1_k_decode.c b/src/lib/krb5/asn.1/asn1_k_decode.c index cc3168c00..c5d200628 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.c +++ b/src/lib/krb5/asn.1/asn1_k_decode.c @@ -30,6 +30,8 @@ #include "asn1_get.h" #include "asn1_misc.h" +#define clean_return(val) { retval = val; goto error_out; } + /* Declare useful decoder variables. */ #define setup() \ asn1_error_code retval; \ @@ -44,7 +46,7 @@ #define next_tag() \ { taginfo t2; \ retval = asn1_get_tag_2(&subbuf, &t2); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ /* Copy out to match previous functionality, until better integrated. */ \ asn1class = t2.asn1class; \ construction = t2.construction; \ @@ -71,21 +73,38 @@ asn1_get_eoc_tag (asn1buf *buf) #define get_eoc() \ { \ retval = asn1_get_eoc_tag(&subbuf); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ } -#define alloc_field(var, type) \ - var = (type*)calloc(1, sizeof(type)); \ - if ((var) == NULL) return ENOMEM +#define alloc_field(var) \ + var = calloc(1, sizeof(*var)); \ + if ((var) == NULL) clean_return(ENOMEM) + +/* + * Allocate a principal and initialize enough fields for + * krb5_free_principal to have defined behavior. + */ +#define alloc_principal(var) \ + alloc_field(var); \ + var->realm.data = NULL; \ + var->data = NULL + +/* + * Allocate a data structure and initialize enough fields for + * krb5_free_data to have defined behavior. + */ +#define alloc_data(var) \ + alloc_field(var); \ + var->data = NULL /* Fetch an expected APPLICATION class tag and verify. */ #define apptag(tagexpect) \ { \ taginfo t1; \ retval = asn1_get_tag_2(buf, &t1); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED || \ - t1.tagnum != (tagexpect)) return ASN1_BAD_ID; \ + t1.tagnum != (tagexpect)) clean_return(ASN1_BAD_ID); \ /* Copy out to match previous functionality, until better integrated. */ \ asn1class = t1.asn1class; \ construction = t1.construction; \ @@ -104,7 +123,7 @@ asn1_get_eoc_tag (asn1buf *buf) */ #define get_field_body(var, decoder) \ retval = decoder(&subbuf, &(var)); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ if (!taglen && indef) { get_eoc(); } \ next_tag() @@ -115,7 +134,7 @@ asn1_get_eoc_tag (asn1buf *buf) * if not. */ #define error_if_bad_tag(tagexpect) \ - if (tagnum != (tagexpect)) { return (tagnum < (tagexpect)) ? ASN1_MISPLACED_FIELD : ASN1_MISSING_FIELD; } + if (tagnum != (tagexpect)) { clean_return((tagnum < (tagexpect)) ? ASN1_MISPLACED_FIELD : ASN1_MISSING_FIELD); } /* * get_field @@ -128,7 +147,7 @@ asn1_get_eoc_tag (asn1buf *buf) error_if_bad_tag(tagexpect); \ if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) \ && (tagnum || taglen || asn1class != UNIVERSAL)) \ - return ASN1_BAD_ID; \ + clean_return(ASN1_BAD_ID); \ get_field_body(var,decoder) /* @@ -143,7 +162,7 @@ asn1_get_eoc_tag (asn1buf *buf) if (asn1buf_remains(&subbuf, seqindef)) { \ if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) \ && (tagnum || taglen || asn1class != UNIVERSAL)) \ - return ASN1_BAD_ID; \ + clean_return(ASN1_BAD_ID); \ if (tagnum == (tagexpect)) { \ get_field_body(var, decoder); \ } else var = optvalue; \ @@ -154,7 +173,7 @@ asn1_get_eoc_tag (asn1buf *buf) /* similar to get_field_body */ #define get_lenfield_body(len, var, decoder) \ retval = decoder(&subbuf, &(len), &(var)); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ if (!taglen && indef) { get_eoc(); } \ next_tag() @@ -163,7 +182,7 @@ asn1_get_eoc_tag (asn1buf *buf) error_if_bad_tag(tagexpect); \ if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) \ && (tagnum || taglen || asn1class != UNIVERSAL)) \ - return ASN1_BAD_ID; \ + clean_return(ASN1_BAD_ID); \ get_lenfield_body(len, var, decoder) /* similar to opt_field */ @@ -176,20 +195,20 @@ asn1_get_eoc_tag (asn1buf *buf) * Deal with implicitly tagged fields */ #define get_implicit_octet_string(len, var, tagexpect) \ - if (tagnum != (tagexpect)) return ASN1_MISSING_FIELD; \ + if (tagnum != (tagexpect)) clean_return(ASN1_MISSING_FIELD); \ if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \ - return ASN1_BAD_ID; \ + clean_return(ASN1_BAD_ID); \ retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var)); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ (len) = taglen; \ next_tag() #define opt_implicit_octet_string(len, var, tagexpect) \ if (tagnum == (tagexpect)) { \ if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \ - return ASN1_BAD_ID; \ + clean_return(ASN1_BAD_ID); \ retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var)); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ (len) = taglen; \ next_tag(); \ } else { (len) = 0; (var) = NULL; } @@ -206,9 +225,9 @@ asn1_get_eoc_tag (asn1buf *buf) int seqindef; \ int indef; \ retval = asn1_get_sequence(buf, &length, &seqindef); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ retval = asn1buf_imbed(&subbuf, buf, length, seqindef); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ next_tag() /* @@ -221,15 +240,15 @@ asn1_get_eoc_tag (asn1buf *buf) int seqindef; \ int indef; \ retval = asn1_get_sequence(buf, &length, &seqindef); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ retval = asn1buf_imbed(&subbuf, buf, length, seqindef); \ - if (retval) return retval + if (retval) clean_return(retval) /* skip trailing garbage */ #define end_structure() \ retval = asn1buf_sync(buf, &subbuf, asn1class, tagnum, \ length, indef, seqindef); \ - if (retval) return retval + if (retval) clean_return(retval) /* * begin_choice @@ -244,7 +263,7 @@ asn1_get_eoc_tag (asn1buf *buf) int indef; \ taginfo t; \ retval = asn1_get_tag_2(buf, &t); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ tagnum = t.tagnum; \ taglen = t.length; \ indef = t.indef; \ @@ -253,14 +272,14 @@ asn1_get_eoc_tag (asn1buf *buf) asn1class = t.asn1class; \ construction = t.construction; \ retval = asn1buf_imbed(&subbuf, buf, length, seqindef); \ - if (retval) return retval + if (retval) clean_return(retval) /* skip trailing garbage */ #define end_choice() \ length -= t.length; \ retval = asn1buf_sync(buf, &subbuf, t.asn1class, t.tagnum, \ length, t.indef, seqindef); \ - if (retval) return retval + if (retval) clean_return(retval) /* * sequence_of @@ -295,13 +314,12 @@ asn1_get_eoc_tag (asn1buf *buf) * does not prefetch the next tag. */ #define sequence_of_common(buf) \ - int size = 0; \ asn1buf seqbuf; \ int seqofindef; \ retval = asn1_get_sequence(buf, &length, &seqofindef); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ retval = asn1buf_imbed(&seqbuf, buf, length, seqofindef); \ - if (retval) return retval + if (retval) clean_return(retval) /* * end_sequence_of @@ -313,7 +331,7 @@ asn1_get_eoc_tag (asn1buf *buf) { \ taginfo t4; \ retval = asn1_get_tag_2(&seqbuf, &t4); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ /* Copy out to match previous functionality, until better integrated. */ \ asn1class = t4.asn1class; \ construction = t4.construction; \ @@ -323,7 +341,7 @@ asn1_get_eoc_tag (asn1buf *buf) } \ retval = asn1buf_sync(buf, &seqbuf, asn1class, tagnum, \ length, indef, seqofindef); \ - if (retval) return retval; + if (retval) clean_return(retval); /* * end_sequence_of_no_tagvars @@ -348,8 +366,28 @@ end_sequence_of_no_tagvars_helper(asn1buf *buf, asn1buf *seqbufp, #define end_sequence_of_no_tagvars(buf) \ end_sequence_of_no_tagvars_helper(buf, &seqbuf, seqofindef) -#define cleanup() \ - return 0 +/* + * Function body for a pointer decoder, which allocates a pointer + * field and invokes a structure decoder to fill it in. Pointer + * decoders always fill in their output parameters with NULL (on + * error) or a valid constructed structure, making cleanup easier on + * callers. + */ +#define decode_ptr(type, structure_decoder) \ + type val; \ + asn1_error_code retval; \ +\ + *valptr = NULL; \ + val = calloc(1, sizeof(*val)); \ + if (!val) \ + return ENOMEM; \ + retval = structure_decoder(buf, val); \ + if (retval) { \ + free(val); \ + return retval; \ + } \ + *valptr = val; \ + return 0; /* scalars */ asn1_error_code asn1_decode_kerberos_time(asn1buf *buf, krb5_timestamp *val) @@ -430,25 +468,27 @@ asn1_error_code asn1_decode_realm(asn1buf *buf, krb5_principal *val) asn1_error_code asn1_decode_principal_name(asn1buf *buf, krb5_principal *val) { + int size = 0, i; + krb5_data *array = NULL, *new_array; + setup(); { begin_structure(); get_field((*val)->type,0,asn1_decode_int32); { sequence_of_no_tagvars(&subbuf); while (asn1buf_remains(&seqbuf,seqofindef) > 0) { + unsigned int len; + char *str; + + new_array = realloc(array, (size + 1) * sizeof(krb5_data)); + if (new_array == NULL) clean_return(ENOMEM); + array = new_array; + retval = asn1_decode_generalstring(&seqbuf, &len, &str); + if (retval) clean_return(retval); + array[size].data = str; + array[size].length = len; size++; - if ((*val)->data == NULL) - (*val)->data = (krb5_data*)malloc(size*sizeof(krb5_data)); - else - (*val)->data = (krb5_data*)realloc((*val)->data, - size*sizeof(krb5_data)); - if ((*val)->data == NULL) return ENOMEM; - retval = asn1_decode_generalstring(&seqbuf, - &((*val)->data[size-1].length), - &((*val)->data[size-1].data)); - if (retval) return retval; } - (*val)->length = size; end_sequence_of_no_tagvars(&subbuf); } if (indef) { @@ -456,38 +496,65 @@ asn1_error_code asn1_decode_principal_name(asn1buf *buf, krb5_principal *val) } next_tag(); end_structure(); - (*val)->magic = KV5M_PRINCIPAL; } - cleanup(); + (*val)->data = array; + (*val)->length = size; + (*val)->magic = KV5M_PRINCIPAL; + return 0; +error_out: + for (i = 0; i < size; i++) + free(array[i].data); + free(array); + return retval; } asn1_error_code asn1_decode_checksum(asn1buf *buf, krb5_checksum *val) { setup(); + val->contents = NULL; { begin_structure(); get_field(val->checksum_type,0,asn1_decode_cksumtype); get_lenfield(val->length,val->contents,1,asn1_decode_octetstring); end_structure(); val->magic = KV5M_CHECKSUM; } - cleanup(); + return 0; +error_out: + free(val->contents); + return retval; +} + +asn1_error_code asn1_decode_checksum_ptr(asn1buf *buf, krb5_checksum **valptr) +{ + decode_ptr(krb5_checksum *, asn1_decode_checksum); } asn1_error_code asn1_decode_encryption_key(asn1buf *buf, krb5_keyblock *val) { setup(); + val->contents = NULL; { begin_structure(); get_field(val->enctype,0,asn1_decode_enctype); get_lenfield(val->length,val->contents,1,asn1_decode_octetstring); end_structure(); val->magic = KV5M_KEYBLOCK; } - cleanup(); + return 0; +error_out: + free(val->contents); + return retval; +} + +asn1_error_code +asn1_decode_encryption_key_ptr(asn1buf *buf, krb5_keyblock **valptr) +{ + decode_ptr(krb5_keyblock *, asn1_decode_encryption_key); } asn1_error_code asn1_decode_encrypted_data(asn1buf *buf, krb5_enc_data *val) { setup(); + val->ciphertext.data = NULL; { begin_structure(); get_field(val->enctype,0,asn1_decode_enctype); opt_field(val->kvno,1,asn1_decode_kvno,0); @@ -495,7 +562,11 @@ asn1_error_code asn1_decode_encrypted_data(asn1buf *buf, krb5_enc_data *val) end_structure(); val->magic = KV5M_ENC_DATA; } - cleanup(); + return 0; +error_out: + free(val->ciphertext.data); + val->ciphertext.data = NULL; + return retval; } asn1_error_code asn1_decode_krb5_flags(asn1buf *buf, krb5_flags *val) @@ -551,21 +622,28 @@ asn1_error_code asn1_decode_kdc_options(asn1buf *buf, krb5_flags *val) asn1_error_code asn1_decode_transited_encoding(asn1buf *buf, krb5_transited *val) { setup(); + val->tr_contents.data = NULL; { begin_structure(); get_field(val->tr_type,0,asn1_decode_octet); get_lenfield(val->tr_contents.length,val->tr_contents.data,1,asn1_decode_charstring); end_structure(); val->magic = KV5M_TRANSITED; } - cleanup(); + return 0; +error_out: + krb5_free_data_contents(NULL, &val->tr_contents); + return retval; } asn1_error_code asn1_decode_enc_kdc_rep_part(asn1buf *buf, krb5_enc_kdc_rep_part *val) { setup(); + val->session = NULL; + val->last_req = NULL; + val->server = NULL; + val->caddrs = NULL; { begin_structure(); - alloc_field(val->session,krb5_keyblock); - get_field(*(val->session),0,asn1_decode_encryption_key); + get_field(val->session,0,asn1_decode_encryption_key_ptr); get_field(val->last_req,1,asn1_decode_last_req); get_field(val->nonce,2,asn1_decode_int32); opt_field(val->key_exp,3,asn1_decode_kerberos_time,0); @@ -575,7 +653,7 @@ asn1_error_code asn1_decode_enc_kdc_rep_part(asn1buf *buf, krb5_enc_kdc_rep_part opt_field(val->times.starttime,6,asn1_decode_kerberos_time,val->times.authtime); get_field(val->times.endtime,7,asn1_decode_kerberos_time); opt_field(val->times.renew_till,8,asn1_decode_kerberos_time,0); - alloc_field(val->server,krb5_principal_data); + alloc_principal(val->server); get_field(val->server,9,asn1_decode_realm); get_field(val->server,10,asn1_decode_principal_name); opt_field(val->caddrs,11,asn1_decode_host_addresses,NULL); @@ -583,7 +661,17 @@ asn1_error_code asn1_decode_enc_kdc_rep_part(asn1buf *buf, krb5_enc_kdc_rep_part end_structure(); val->magic = KV5M_ENC_KDC_REP_PART; } - cleanup(); + return 0; +error_out: + krb5_free_keyblock(NULL, val->session); + krb5_free_last_req(NULL, val->last_req); + krb5_free_principal(NULL, val->server); + krb5_free_addresses(NULL, val->caddrs); + val->session = NULL; + val->last_req = NULL; + val->server = NULL; + val->caddrs = NULL; + return retval; } asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val) @@ -591,11 +679,14 @@ asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val) setup(); unsigned int applen; apptag(1); + val->server = NULL; + val->enc_part.ciphertext.data = NULL; + val->enc_part2 = NULL; { begin_structure(); { krb5_kvno vno; get_field(vno,0,asn1_decode_kvno); - if (vno != KVNO) return KRB5KDC_ERR_BAD_PVNO; } - alloc_field(val->server,krb5_principal_data); + if (vno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); } + alloc_principal(val->server); get_field(val->server,1,asn1_decode_realm); get_field(val->server,2,asn1_decode_principal_name); get_field(val->enc_part,3,asn1_decode_encrypted_data); @@ -605,41 +696,64 @@ asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val) if (!applen) { taginfo t; retval = asn1_get_tag_2(buf, &t); - if (retval) return retval; + if (retval) clean_return(retval); } - cleanup(); + return 0; +error_out: + krb5_free_principal(NULL, val->server); + krb5_free_data_contents(NULL, &val->enc_part.ciphertext); + val->server = NULL; + return retval; +} + +asn1_error_code +asn1_decode_ticket_ptr(asn1buf *buf, krb5_ticket **valptr) +{ + decode_ptr(krb5_ticket *, asn1_decode_ticket); } asn1_error_code asn1_decode_kdc_req(asn1buf *buf, krb5_kdc_req *val) { setup(); + val->padata = NULL; { begin_structure(); { krb5_kvno kvno; get_field(kvno,1,asn1_decode_kvno); - if (kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; } + if (kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); } get_field(val->msg_type,2,asn1_decode_msgtype); opt_field(val->padata,3,asn1_decode_sequence_of_pa_data,NULL); get_field(*val,4,asn1_decode_kdc_req_body); end_structure(); val->magic = KV5M_KDC_REQ; } - cleanup(); + return 0; +error_out: + krb5_free_pa_data(NULL, val->padata); + val->padata = NULL; + return retval; } asn1_error_code asn1_decode_kdc_req_body(asn1buf *buf, krb5_kdc_req *val) { setup(); + val->client = NULL; + val->server = NULL; + val->ktype = NULL; + val->addresses = NULL; + val->authorization_data.ciphertext.data = NULL; + val->unenc_authdata = NULL; + val->second_ticket = NULL; { krb5_principal psave; begin_structure(); get_field(val->kdc_options,0,asn1_decode_kdc_options); - if (tagnum == 1) { alloc_field(val->client,krb5_principal_data); } + if (tagnum == 1) { alloc_principal(val->client); } opt_field(val->client,1,asn1_decode_principal_name,NULL); - alloc_field(val->server,krb5_principal_data); + alloc_principal(val->server); get_field(val->server,2,asn1_decode_realm); if (val->client != NULL) { retval = asn1_krb5_realm_copy(val->client,val->server); - if (retval) return retval; } + if (retval) clean_return(retval); } /* If opt_field server is missing, memory reference to server is lost and results in memory leak */ @@ -672,72 +786,119 @@ asn1_error_code asn1_decode_kdc_req_body(asn1buf *buf, krb5_kdc_req *val) end_structure(); val->magic = KV5M_KDC_REQ; } - cleanup(); + return 0; +error_out: + krb5_free_principal(NULL, val->client); + krb5_free_principal(NULL, val->server); + free(val->ktype); + krb5_free_addresses(NULL, val->addresses); + krb5_free_data_contents(NULL, &val->authorization_data.ciphertext); + krb5_free_tickets(NULL, val->second_ticket); + val->client = NULL; + val->server = NULL; + val->ktype = NULL; + val->addresses = NULL; + val->unenc_authdata = NULL; + val->second_ticket = NULL; + return retval; } asn1_error_code asn1_decode_krb_safe_body(asn1buf *buf, krb5_safe *val) { setup(); + val->user_data.data = NULL; + val->r_address = NULL; + val->s_address = NULL; + val->checksum = NULL; { begin_structure(); get_lenfield(val->user_data.length,val->user_data.data,0,asn1_decode_charstring); opt_field(val->timestamp,1,asn1_decode_kerberos_time,0); opt_field(val->usec,2,asn1_decode_int32,0); opt_field(val->seq_number,3,asn1_decode_seqnum,0); - alloc_field(val->s_address,krb5_address); - get_field(*(val->s_address),4,asn1_decode_host_address); + get_field(val->s_address,4,asn1_decode_host_address_ptr); if (tagnum == 5) { - alloc_field(val->r_address,krb5_address); - get_field(*(val->r_address),5,asn1_decode_host_address); - } else val->r_address = NULL; + get_field(val->r_address,5,asn1_decode_host_address_ptr); + } end_structure(); val->magic = KV5M_SAFE; } - cleanup(); + return 0; +error_out: + krb5_free_data_contents(NULL, &val->user_data); + krb5_free_address(NULL, val->r_address); + krb5_free_address(NULL, val->s_address); + val->r_address = NULL; + val->s_address = NULL; + return retval; } asn1_error_code asn1_decode_host_address(asn1buf *buf, krb5_address *val) { setup(); + val->contents = NULL; { begin_structure(); get_field(val->addrtype,0,asn1_decode_addrtype); get_lenfield(val->length,val->contents,1,asn1_decode_octetstring); end_structure(); val->magic = KV5M_ADDRESS; } - cleanup(); + return 0; +error_out: + free(val->contents); + val->contents = NULL; + return retval; +} + +asn1_error_code +asn1_decode_host_address_ptr(asn1buf *buf, krb5_address **valptr) +{ + decode_ptr(krb5_address *, asn1_decode_host_address); } asn1_error_code asn1_decode_kdc_rep(asn1buf *buf, krb5_kdc_rep *val) { setup(); + val->padata = NULL; + val->client = NULL; + val->ticket = NULL; + val->enc_part.ciphertext.data = NULL; + val->enc_part2 = NULL; { begin_structure(); { krb5_kvno pvno; get_field(pvno,0,asn1_decode_kvno); - if (pvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; } + if (pvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); } get_field(val->msg_type,1,asn1_decode_msgtype); opt_field(val->padata,2,asn1_decode_sequence_of_pa_data,NULL); - alloc_field(val->client,krb5_principal_data); + alloc_principal(val->client); get_field(val->client,3,asn1_decode_realm); get_field(val->client,4,asn1_decode_principal_name); - alloc_field(val->ticket,krb5_ticket); - get_field(*(val->ticket),5,asn1_decode_ticket); + get_field(val->ticket,5,asn1_decode_ticket_ptr); get_field(val->enc_part,6,asn1_decode_encrypted_data); end_structure(); val->magic = KV5M_KDC_REP; } - cleanup(); + return 0; +error_out: + krb5_free_pa_data(NULL, val->padata); + krb5_free_principal(NULL, val->client); + krb5_free_ticket(NULL, val->ticket); + krb5_free_data_contents(NULL, &val->enc_part.ciphertext); + val->padata = NULL; + val->client = NULL; + val->ticket = NULL; + val->enc_part.ciphertext.data = NULL; + return retval; } /* arrays */ #define get_element(element,decoder)\ -retval = decoder(&seqbuf,element);\ -if (retval) return retval +retval = decoder(&seqbuf,&element);\ +if (retval) clean_return(retval) static void * array_expand (void *array, int n_elts, size_t elt_size) { - void *new_array; size_t new_size; if (n_elts <= 0) @@ -749,74 +910,120 @@ array_expand (void *array, int n_elts, size_t elt_size) return NULL; if (new_size / elt_size != (unsigned int) n_elts) return NULL; - new_array = realloc(array, new_size); - return new_array; + return realloc(array, new_size); } #define array_append(array,size,element,type)\ -size++;\ -*(array) = array_expand(*(array), (size+1), sizeof(type*));\ -if (*(array) == NULL) return ENOMEM;\ -(*(array))[(size)-1] = elt + {\ + void *new_array = array_expand(*(array), (size)+2, sizeof(type*));\ + if (new_array == NULL) clean_return(ENOMEM);\ + *(array) = new_array;\ + (*(array))[(size)++] = elt;\ + } -#define decode_array_body(type,decoder)\ +/* + * Function body for array decoders. freefn is expected to look like + * a krb5_free_ function, so we pass a null first argument. + */ +#define decode_array_body(type,decoder,freefn)\ asn1_error_code retval;\ - type *elt;\ + type *elt = NULL, **array;\ + int size = 0, i; \ \ + array = *val = NULL;\ { sequence_of(buf);\ while (asn1buf_remains(&seqbuf,seqofindef) > 0) {\ - alloc_field(elt,type);\ get_element(elt,decoder);\ - array_append(val,size,elt,type);\ + array_append(&array,size,elt,type);\ + elt = NULL;\ }\ - if (*val == NULL)\ - *val = (type **)malloc(sizeof(type*));\ - (*val)[size] = NULL;\ + if (array == NULL)\ + array = malloc(sizeof(type*));\ + array[size] = NULL;\ end_sequence_of(buf);\ }\ - cleanup() + *val = array;\ + return 0;\ +error_out:\ + if (elt)\ + freefn(NULL,elt);\ + for (i = 0; i < size; i++)\ + freefn(NULL,array[i]);\ + free(array);\ + return retval +static void free_authdata_elt(void *dummy, krb5_authdata *val) +{ + free(val->contents); + free(val); +} asn1_error_code asn1_decode_authorization_data(asn1buf *buf, krb5_authdata ***val) { - decode_array_body(krb5_authdata,asn1_decode_authdata_elt); + decode_array_body(krb5_authdata,asn1_decode_authdata_elt_ptr, + free_authdata_elt); } asn1_error_code asn1_decode_authdata_elt(asn1buf *buf, krb5_authdata *val) { setup(); + val->contents = NULL; { begin_structure(); get_field(val->ad_type,0,asn1_decode_authdatatype); get_lenfield(val->length,val->contents,1,asn1_decode_octetstring); end_structure(); val->magic = KV5M_AUTHDATA; } - cleanup(); + return 0; +error_out: + free(val->contents); + val->contents = NULL; + return retval; +} + +asn1_error_code +asn1_decode_authdata_elt_ptr(asn1buf *buf, krb5_authdata **valptr) +{ + decode_ptr(krb5_authdata *, asn1_decode_authdata_elt); } asn1_error_code asn1_decode_host_addresses(asn1buf *buf, krb5_address ***val) { - decode_array_body(krb5_address,asn1_decode_host_address); + decode_array_body(krb5_address,asn1_decode_host_address_ptr, + krb5_free_address); } asn1_error_code asn1_decode_sequence_of_ticket(asn1buf *buf, krb5_ticket ***val) { - decode_array_body(krb5_ticket,asn1_decode_ticket); + decode_array_body(krb5_ticket,asn1_decode_ticket_ptr,krb5_free_ticket); +} + +static void free_cred_info(void *dummy, krb5_cred_info *val) +{ + krb5_free_keyblock(NULL, val->session); + krb5_free_principal(NULL, val->client); + krb5_free_principal(NULL, val->server); + krb5_free_addresses(NULL, val->caddrs); + free(val); } asn1_error_code asn1_decode_sequence_of_krb_cred_info(asn1buf *buf, krb5_cred_info ***val) { - decode_array_body(krb5_cred_info,asn1_decode_krb_cred_info); + decode_array_body(krb5_cred_info,asn1_decode_krb_cred_info_ptr, + free_cred_info); } asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val) { setup(); + val->session = NULL; + val->client = NULL; + val->server = NULL; + val->caddrs = NULL; { begin_structure(); - alloc_field(val->session,krb5_keyblock); - get_field(*(val->session),0,asn1_decode_encryption_key); + get_field(val->session,0,asn1_decode_encryption_key_ptr); if (tagnum == 1) { - alloc_field(val->client,krb5_principal_data); + alloc_principal(val->client); opt_field(val->client,1,asn1_decode_realm,NULL); opt_field(val->client,2,asn1_decode_principal_name,NULL); } opt_field(val->flags,3,asn1_decode_ticket_flags,0); @@ -825,36 +1032,74 @@ asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val) opt_field(val->times.endtime,6,asn1_decode_kerberos_time,0); opt_field(val->times.renew_till,7,asn1_decode_kerberos_time,0); if (tagnum == 8) { - alloc_field(val->server,krb5_principal_data); + alloc_principal(val->server); opt_field(val->server,8,asn1_decode_realm,NULL); opt_field(val->server,9,asn1_decode_principal_name,NULL); } opt_field(val->caddrs,10,asn1_decode_host_addresses,NULL); end_structure(); val->magic = KV5M_CRED_INFO; } - cleanup(); + return 0; +error_out: + krb5_free_keyblock(NULL, val->session); + krb5_free_principal(NULL, val->client); + krb5_free_principal(NULL, val->server); + krb5_free_addresses(NULL, val->caddrs); + val->session = NULL; + val->client = NULL; + val->server = NULL; + val->caddrs = NULL; + return retval; +} + +asn1_error_code +asn1_decode_krb_cred_info_ptr(asn1buf *buf, krb5_cred_info **valptr) +{ + decode_ptr(krb5_cred_info *, asn1_decode_krb_cred_info); +} + +static void free_pa_data(void *dummy, krb5_pa_data *val) +{ + free(val->contents); + free(val); } asn1_error_code asn1_decode_sequence_of_pa_data(asn1buf *buf, krb5_pa_data ***val) { - decode_array_body(krb5_pa_data,asn1_decode_pa_data); + decode_array_body(krb5_pa_data,asn1_decode_pa_data_ptr,free_pa_data); } asn1_error_code asn1_decode_pa_data(asn1buf *buf, krb5_pa_data *val) { setup(); + val->contents = NULL; { begin_structure(); get_field(val->pa_type,1,asn1_decode_int32); get_lenfield(val->length,val->contents,2,asn1_decode_octetstring); end_structure(); val->magic = KV5M_PA_DATA; } - cleanup(); + return 0; +error_out: + free(val->contents); + val->contents = NULL; + return retval; +} + +asn1_error_code asn1_decode_pa_data_ptr(asn1buf *buf, krb5_pa_data **valptr) +{ + decode_ptr(krb5_pa_data *, asn1_decode_pa_data); +} + +static void free_last_req_entry(void *dummy, krb5_last_req_entry *val) +{ + free(val); } asn1_error_code asn1_decode_last_req(asn1buf *buf, krb5_last_req_entry ***val) { - decode_array_body(krb5_last_req_entry,asn1_decode_last_req_entry); + decode_array_body(krb5_last_req_entry,asn1_decode_last_req_entry_ptr, + free_last_req_entry); } asn1_error_code asn1_decode_last_req_entry(asn1buf *buf, krb5_last_req_entry *val) @@ -871,147 +1116,222 @@ asn1_error_code asn1_decode_last_req_entry(asn1buf *buf, krb5_last_req_entry *va if ((val->lr_type & 0xffffff80U) == 0x80) val->lr_type |= 0xffffff00U; #endif } - cleanup(); + return 0; +error_out: + return retval; +} + +asn1_error_code +asn1_decode_last_req_entry_ptr(asn1buf *buf, krb5_last_req_entry **valptr) +{ + decode_ptr(krb5_last_req_entry *, asn1_decode_last_req_entry); } asn1_error_code asn1_decode_sequence_of_enctype(asn1buf *buf, int *num, krb5_enctype **val) { + int size = 0; + krb5_enctype *array = NULL, *new_array; + asn1_error_code retval; { sequence_of(buf); while (asn1buf_remains(&seqbuf,seqofindef) > 0) { size++; - if (*val == NULL) - *val = (krb5_enctype*)malloc(size*sizeof(krb5_enctype)); - else - *val = (krb5_enctype*)realloc(*val,size*sizeof(krb5_enctype)); - if (*val == NULL) return ENOMEM; - retval = asn1_decode_enctype(&seqbuf,&((*val)[size-1])); - if (retval) return retval; + new_array = realloc(array,size*sizeof(krb5_enctype)); + if (new_array == NULL) clean_return(ENOMEM); + array = new_array; + retval = asn1_decode_enctype(&seqbuf,&array[size-1]); + if (retval) clean_return(retval); } - *num = size; end_sequence_of(buf); } - cleanup(); + *num = size; + *val = array; + return 0; +error_out: + free(array); + return retval; } asn1_error_code asn1_decode_sequence_of_checksum(asn1buf *buf, krb5_checksum ***val) { - decode_array_body(krb5_checksum, asn1_decode_checksum); + decode_array_body(krb5_checksum, asn1_decode_checksum_ptr, + krb5_free_checksum); +} + +static void free_etype_info_entry(void *dummy, krb5_etype_info_entry *val) +{ + krb5_free_data_contents(NULL, &val->s2kparams); + free(val->salt); + free(val); } static asn1_error_code asn1_decode_etype_info2_entry(asn1buf *buf, krb5_etype_info_entry *val ) { + char *salt = NULL; + krb5_octet *params = NULL; setup(); + val->salt = NULL; + val->s2kparams.data = NULL; { begin_structure(); get_field(val->etype,0,asn1_decode_enctype); if (tagnum == 1) { - char *salt; get_lenfield(val->length,salt,1,asn1_decode_generalstring); val->salt = (krb5_octet *) salt; - } else { + salt = NULL; + } else val->length = KRB5_ETYPE_NO_SALT; - val->salt = 0; - } if ( tagnum ==2) { - krb5_octet *params ; get_lenfield( val->s2kparams.length, params, 2, asn1_decode_octetstring); val->s2kparams.data = ( char *) params; - } else { - val->s2kparams.data = NULL; + params = NULL; + } else val->s2kparams.length = 0; - } end_structure(); val->magic = KV5M_ETYPE_INFO_ENTRY; } - cleanup(); + return 0; +error_out: + free(salt); + free(params); + krb5_free_data_contents(NULL, &val->s2kparams); + free(val->salt); + val->salt = NULL; + return retval; +} + +static asn1_error_code +asn1_decode_etype_info2_entry_ptr(asn1buf *buf, krb5_etype_info_entry **valptr) +{ + decode_ptr(krb5_etype_info_entry *, asn1_decode_etype_info2_entry); } static asn1_error_code asn1_decode_etype_info2_entry_1_3(asn1buf *buf, krb5_etype_info_entry *val ) { setup(); + val->salt = NULL; + val->s2kparams.data = NULL; { begin_structure(); get_field(val->etype,0,asn1_decode_enctype); if (tagnum == 1) { get_lenfield(val->length,val->salt,1,asn1_decode_octetstring); - } else { + } else val->length = KRB5_ETYPE_NO_SALT; - val->salt = 0; - } if ( tagnum ==2) { krb5_octet *params ; get_lenfield( val->s2kparams.length, params, 2, asn1_decode_octetstring); val->s2kparams.data = ( char *) params; - } else { - val->s2kparams.data = NULL; + } else val->s2kparams.length = 0; - } end_structure(); val->magic = KV5M_ETYPE_INFO_ENTRY; } - cleanup(); + return 0; +error_out: + krb5_free_data_contents(NULL, &val->s2kparams); + free(val->salt); + val->salt = NULL; + return retval; } +static asn1_error_code +asn1_decode_etype_info2_entry_1_3_ptr(asn1buf *buf, + krb5_etype_info_entry **valptr) +{ + decode_ptr(krb5_etype_info_entry *, asn1_decode_etype_info2_entry_1_3); +} static asn1_error_code asn1_decode_etype_info_entry(asn1buf *buf, krb5_etype_info_entry *val ) { setup(); + val->salt = NULL; + val->s2kparams.data = NULL; { begin_structure(); get_field(val->etype,0,asn1_decode_enctype); if (tagnum == 1) { get_lenfield(val->length,val->salt,1,asn1_decode_octetstring); - } else { + } else val->length = KRB5_ETYPE_NO_SALT; - val->salt = 0; - } - val->s2kparams.data = NULL; val->s2kparams.length = 0; end_structure(); val->magic = KV5M_ETYPE_INFO_ENTRY; } - cleanup(); + return 0; +error_out: + free(val->salt); + val->salt = NULL; + return retval; +} + +static asn1_error_code +asn1_decode_etype_info_entry_ptr(asn1buf *buf, krb5_etype_info_entry **valptr) +{ + decode_ptr(krb5_etype_info_entry *, asn1_decode_etype_info_entry); } asn1_error_code asn1_decode_etype_info(asn1buf *buf, krb5_etype_info_entry ***val ) { - decode_array_body(krb5_etype_info_entry,asn1_decode_etype_info_entry); + decode_array_body(krb5_etype_info_entry,asn1_decode_etype_info_entry_ptr, + free_etype_info_entry); +} + +static asn1_error_code decode_etype_info2_13(asn1buf *buf, krb5_etype_info_entry ***val) +{ + decode_array_body(krb5_etype_info_entry, + asn1_decode_etype_info2_entry_1_3_ptr, + free_etype_info_entry); } asn1_error_code asn1_decode_etype_info2(asn1buf *buf, krb5_etype_info_entry ***val , krb5_boolean v1_3_behavior) { - if (v1_3_behavior) { + if (v1_3_behavior) + return decode_etype_info2_13(buf, val); + else { decode_array_body(krb5_etype_info_entry, - asn1_decode_etype_info2_entry_1_3); - } else { - decode_array_body(krb5_etype_info_entry, - asn1_decode_etype_info2_entry); + asn1_decode_etype_info2_entry_ptr, + free_etype_info_entry); } } asn1_error_code asn1_decode_passwdsequence(asn1buf *buf, passwd_phrase_element *val) { setup(); + val->passwd = NULL; + val->phrase = NULL; { begin_structure(); - alloc_field(val->passwd,krb5_data); + alloc_data(val->passwd); get_lenfield(val->passwd->length,val->passwd->data, 0,asn1_decode_charstring); val->passwd->magic = KV5M_DATA; - alloc_field(val->phrase,krb5_data); + alloc_data(val->phrase); get_lenfield(val->phrase->length,val->phrase->data, 1,asn1_decode_charstring); val->phrase->magic = KV5M_DATA; end_structure(); val->magic = KV5M_PASSWD_PHRASE_ELEMENT; } - cleanup(); + return 0; +error_out: + krb5_free_data(NULL, val->passwd); + krb5_free_data(NULL, val->phrase); + val->passwd = NULL; + val->phrase = NULL; + return 0; +} + +asn1_error_code +asn1_decode_passwdsequence_ptr(asn1buf *buf, passwd_phrase_element **valptr) +{ + decode_ptr(passwd_phrase_element *, asn1_decode_passwdsequence); } asn1_error_code asn1_decode_sequence_of_passwdsequence(asn1buf *buf, passwd_phrase_element ***val) { - decode_array_body(passwd_phrase_element,asn1_decode_passwdsequence); + decode_array_body(passwd_phrase_element,asn1_decode_passwdsequence_ptr, + krb5_free_passwd_phrase_element); } asn1_error_code asn1_decode_sam_flags(asn1buf *buf, krb5_flags *val) @@ -1026,6 +1346,12 @@ else var.length = 0 asn1_error_code asn1_decode_sam_challenge(asn1buf *buf, krb5_sam_challenge *val) { setup(); + val->sam_type_name.data = NULL; + val->sam_track_id.data = NULL; + val->sam_challenge_label.data = NULL; + val->sam_response_prompt.data = NULL; + val->sam_pk_for_sad.data = NULL; + val->sam_cksum.contents = NULL; { begin_structure(); get_field(val->sam_type,0,asn1_decode_int32); get_field(val->sam_flags,1,asn1_decode_sam_flags); @@ -1040,37 +1366,58 @@ asn1_error_code asn1_decode_sam_challenge(asn1buf *buf, krb5_sam_challenge *val) end_structure(); val->magic = KV5M_SAM_CHALLENGE; } - cleanup(); + return 0; +error_out: + krb5_free_sam_challenge_contents(NULL, val); + return retval; } asn1_error_code asn1_decode_sam_challenge_2(asn1buf *buf, krb5_sam_challenge_2 *val) { + krb5_checksum **cksump; setup(); + val->sam_challenge_2_body.data = NULL; + val->sam_cksum = NULL; { char *save, *end; size_t alloclen; begin_structure(); - if (tagnum != 0) return ASN1_MISSING_FIELD; + if (tagnum != 0) clean_return(ASN1_MISSING_FIELD); if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) - return ASN1_BAD_ID; + clean_return(ASN1_BAD_ID); save = subbuf.next; { sequence_of_no_tagvars(&subbuf); - unused_var(size); end_sequence_of_no_tagvars(&subbuf); } end = subbuf.next; alloclen = end - save; - if ((val->sam_challenge_2_body.data = (char *) malloc(alloclen)) == NULL) - return ENOMEM; + val->sam_challenge_2_body.data = malloc(alloclen); + if (!val->sam_challenge_2_body.data) + clean_return(ENOMEM); val->sam_challenge_2_body.length = alloclen; memcpy(val->sam_challenge_2_body.data, save, alloclen); next_tag(); get_field(val->sam_cksum, 1, asn1_decode_sequence_of_checksum); end_structure(); } - cleanup(); + return 0; +error_out: + krb5_free_data_contents(NULL, &val->sam_challenge_2_body); + if (val->sam_cksum) { + for (cksump = val->sam_cksum; *cksump; cksump++) + krb5_free_checksum(NULL, *cksump); + free(val->sam_cksum); + val->sam_cksum = NULL; + } + return retval; } asn1_error_code asn1_decode_sam_challenge_2_body(asn1buf *buf, krb5_sam_challenge_2_body *val) { setup(); + val->sam_type_name.data = NULL; + val->sam_track_id.data = NULL; + val->sam_challenge_label.data = NULL; + val->sam_challenge.data = NULL; + val->sam_response_prompt.data = NULL; + val->sam_pk_for_sad.data = NULL; { begin_structure(); get_field(val->sam_type,0,asn1_decode_int32); get_field(val->sam_flags,1,asn1_decode_sam_flags); @@ -1085,23 +1432,30 @@ asn1_error_code asn1_decode_sam_challenge_2_body(asn1buf *buf, krb5_sam_challeng end_structure(); val->magic = KV5M_SAM_CHALLENGE; } - cleanup(); + return 0; +error_out: + krb5_free_sam_challenge_2_body_contents(NULL, val); + return retval; } asn1_error_code asn1_decode_enc_sam_key(asn1buf *buf, krb5_sam_key *val) { setup(); + val->sam_key.contents = NULL; { begin_structure(); - /* alloc_field(val->sam_key,krb5_keyblock); */ get_field(val->sam_key,0,asn1_decode_encryption_key); end_structure(); val->magic = KV5M_SAM_KEY; } - cleanup(); + return 0; +error_out: + krb5_free_keyblock_contents(NULL, &val->sam_key); + return retval; } asn1_error_code asn1_decode_enc_sam_response_enc(asn1buf *buf, krb5_enc_sam_response_enc *val) { setup(); + val->sam_sad.data = NULL; { begin_structure(); opt_field(val->sam_nonce,0,asn1_decode_int32,0); opt_field(val->sam_timestamp,1,asn1_decode_kerberos_time,0); @@ -1110,19 +1464,26 @@ asn1_error_code asn1_decode_enc_sam_response_enc(asn1buf *buf, krb5_enc_sam_resp end_structure(); val->magic = KV5M_ENC_SAM_RESPONSE_ENC; } - cleanup(); + return 0; +error_out: + krb5_free_enc_sam_response_enc_contents(NULL, val); + return retval; } asn1_error_code asn1_decode_enc_sam_response_enc_2(asn1buf *buf, krb5_enc_sam_response_enc_2 *val) { setup(); + val->sam_sad.data = NULL; { begin_structure(); get_field(val->sam_nonce,0,asn1_decode_int32); opt_string(val->sam_sad,1,asn1_decode_charstring); end_structure(); val->magic = KV5M_ENC_SAM_RESPONSE_ENC_2; } - cleanup(); + return 0; +error_out: + krb5_free_enc_sam_response_enc_2_contents(NULL, val); + return retval; } #define opt_encfield(fld,tag,fn) \ @@ -1139,6 +1500,9 @@ asn1_error_code asn1_decode_enc_sam_response_enc_2(asn1buf *buf, krb5_enc_sam_re asn1_error_code asn1_decode_sam_response(asn1buf *buf, krb5_sam_response *val) { setup(); + val->sam_track_id.data = NULL; + val->sam_enc_key.ciphertext.data = NULL; + val->sam_enc_nonce_or_ts.ciphertext.data = NULL; { begin_structure(); get_field(val->sam_type,0,asn1_decode_int32); get_field(val->sam_flags,1,asn1_decode_sam_flags); @@ -1150,12 +1514,17 @@ asn1_error_code asn1_decode_sam_response(asn1buf *buf, krb5_sam_response *val) end_structure(); val->magic = KV5M_SAM_RESPONSE; } - cleanup(); + return 0; +error_out: + krb5_free_sam_response_contents(NULL, val); + return retval; } asn1_error_code asn1_decode_sam_response_2(asn1buf *buf, krb5_sam_response_2 *val) { setup(); + val->sam_track_id.data = NULL; + val->sam_enc_nonce_or_sad.ciphertext.data = NULL; { begin_structure(); get_field(val->sam_type,0,asn1_decode_int32); get_field(val->sam_flags,1,asn1_decode_sam_flags); @@ -1165,57 +1534,82 @@ asn1_error_code asn1_decode_sam_response_2(asn1buf *buf, krb5_sam_response_2 *va end_structure(); val->magic = KV5M_SAM_RESPONSE; } - cleanup(); + return 0; +error_out: + krb5_free_sam_response_2_contents(NULL, val); + return retval; } asn1_error_code asn1_decode_predicted_sam_response(asn1buf *buf, krb5_predicted_sam_response *val) { setup(); + val->sam_key.contents = NULL; + val->client = NULL; + val->msd.data = NULL; { begin_structure(); get_field(val->sam_key,0,asn1_decode_encryption_key); get_field(val->sam_flags,1,asn1_decode_sam_flags); get_field(val->stime,2,asn1_decode_kerberos_time); get_field(val->susec,3,asn1_decode_int32); - alloc_field(val->client,krb5_principal_data); + alloc_principal(val->client); get_field(val->client,4,asn1_decode_realm); get_field(val->client,5,asn1_decode_principal_name); opt_string(val->msd,6,asn1_decode_charstring); /* should be octet */ end_structure(); val->magic = KV5M_PREDICTED_SAM_RESPONSE; } - cleanup(); + return 0; +error_out: + krb5_free_predicted_sam_response_contents(NULL, val); + return retval; } asn1_error_code asn1_decode_setpw_req(asn1buf *buf, krb5_data *newpasswd, krb5_principal *principal) { + krb5_principal princ = NULL; setup(); *principal = NULL; + newpasswd->data = NULL; { begin_structure(); get_lenfield(newpasswd->length, newpasswd->data, 0, asn1_decode_charstring); if (tagnum == 1) { - alloc_field(*principal, krb5_principal_data); - opt_field(*principal, 1, asn1_decode_principal_name, 0); - opt_field(*principal, 2, asn1_decode_realm, 0); + alloc_principal(princ); + opt_field(princ, 1, asn1_decode_principal_name, 0); + opt_field(princ, 2, asn1_decode_realm, 0); } end_structure(); } - cleanup(); + *principal = princ; + return 0; +error_out: + krb5_free_data_contents(NULL, newpasswd); + krb5_free_principal(NULL, princ); + return retval; } asn1_error_code asn1_decode_pa_for_user(asn1buf *buf, krb5_pa_for_user *val) { setup(); + val->user = NULL; + val->cksum.contents = NULL; + val->auth_package.data = NULL; { begin_structure(); - alloc_field(val->user, krb5_principal_data); + alloc_principal(val->user); get_field(val->user,0,asn1_decode_principal_name); get_field(val->user,1,asn1_decode_realm); get_field(val->cksum,2,asn1_decode_checksum); get_lenfield(val->auth_package.length,val->auth_package.data,3,asn1_decode_generalstring); end_structure(); } - cleanup(); + return 0; +error_out: + krb5_free_principal(NULL, val->user); + krb5_free_checksum_contents(NULL, &val->cksum); + krb5_free_data_contents(NULL, &val->auth_package); + val->user = NULL; + return retval; } asn1_error_code asn1_decode_pa_pac_req(asn1buf *buf, krb5_pa_pac_req *val) @@ -1225,7 +1619,9 @@ asn1_error_code asn1_decode_pa_pac_req(asn1buf *buf, krb5_pa_pac_req *val) get_field(val->include_pac,0,asn1_decode_boolean); end_structure(); } - cleanup(); + return 0; +error_out: + return retval; } #ifndef DISABLE_PKINIT @@ -1234,6 +1630,9 @@ asn1_error_code asn1_decode_pa_pac_req(asn1buf *buf, krb5_pa_pac_req *val) asn1_error_code asn1_decode_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier *val) { setup(); + val->subjectName.data = NULL; + val->issuerAndSerialNumber.data = NULL; + val->subjectKeyIdentifier.data = NULL; { begin_structure(); opt_implicit_octet_string(val->subjectName.length, val->subjectName.data, 0); @@ -1241,17 +1640,49 @@ asn1_error_code asn1_decode_external_principal_identifier(asn1buf *buf, krb5_ext opt_implicit_octet_string(val->subjectKeyIdentifier.length, val->subjectKeyIdentifier.data, 2); end_structure(); } - cleanup(); + return 0; +error_out: + free(val->subjectName.data); + free(val->issuerAndSerialNumber.data); + free(val->subjectKeyIdentifier.data); + val->subjectName.data = NULL; + val->issuerAndSerialNumber.data = NULL; + val->subjectKeyIdentifier.data = NULL; + return retval; +} + +asn1_error_code +asn1_decode_external_principal_identifier_ptr + (asn1buf *buf, + krb5_external_principal_identifier **valptr) +{ + decode_ptr(krb5_external_principal_identifier *, + asn1_decode_external_principal_identifier); +} + +static void +free_external_principal_identifier(void *dummy, + krb5_external_principal_identifier *val) +{ + free(val->subjectName.data); + free(val->issuerAndSerialNumber.data); + free(val->subjectKeyIdentifier.data); + free(val); } asn1_error_code asn1_decode_sequence_of_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier ***val) { - decode_array_body(krb5_external_principal_identifier,asn1_decode_external_principal_identifier); + decode_array_body(krb5_external_principal_identifier, + asn1_decode_external_principal_identifier_ptr, + free_external_principal_identifier); } asn1_error_code asn1_decode_pa_pk_as_req(asn1buf *buf, krb5_pa_pk_as_req *val) { setup(); + val->signedAuthPack.data = NULL; + val->trustedCertifiers = NULL; + val->kdcPkId.data = NULL; { begin_structure(); get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0); @@ -1259,13 +1690,22 @@ asn1_error_code asn1_decode_pa_pk_as_req(asn1buf *buf, krb5_pa_pk_as_req *val) opt_implicit_octet_string(val->kdcPkId.length, val->kdcPkId.data, 2); end_structure(); } - cleanup(); + return 0; +error_out: + free(val->signedAuthPack.data); + free(val->trustedCertifiers); + free(val->kdcPkId.data); + val->signedAuthPack.data = NULL; + val->trustedCertifiers = NULL; + val->kdcPkId.data = NULL; + return retval; } #if 0 /* XXX This needs to be tested!!! XXX */ asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val) { setup(); + val->choice = choice_trusted_cas_UNKNOWN; { char *start, *end; size_t alloclen; @@ -1275,6 +1715,7 @@ asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val) val->choice = choice_trusted_cas_principalName; } else if (t.tagnum == choice_trusted_cas_caName) { val->choice = choice_trusted_cas_caName; + val->u.caName.data = NULL; start = subbuf.next; { sequence_of_no_tagvars(&subbuf); @@ -1285,12 +1726,13 @@ asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val) alloclen = end - start; val->u.caName.data = malloc(alloclen); if (val->u.caName.data == NULL) - return ENOMEM; + clean_return(ENOMEM); memcpy(val->u.caName.data, start, alloclen); val->u.caName.length = alloclen; next_tag(); } else if (t.tagnum == choice_trusted_cas_issuerAndSerial) { val->choice = choice_trusted_cas_issuerAndSerial; + val->u.issuerAndSerial.data = NULL; start = subbuf.next; { sequence_of_no_tagvars(&subbuf); @@ -1301,45 +1743,84 @@ asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val) alloclen = end - start; val->u.issuerAndSerial.data = malloc(alloclen); if (val->u.issuerAndSerial.data == NULL) - return ENOMEM; + clean_return(ENOMEM); memcpy(val->u.issuerAndSerial.data, start, alloclen); val->u.issuerAndSerial.length = alloclen; next_tag(); - } else return ASN1_BAD_ID; + } else clean_return(ASN1_BAD_ID); end_explicit_choice(); } - cleanup(); + return 0; +error_out: + if (val->choice == choice_trusted_cas_caName) + free(val->u.caName.data); + else if (val->choice == choice_trusted_cas_issuerAndSerial) + free(val->u.issuerAndSerial.data); + val->choice = choice_trusted_cas_UNKNOWN; + return retval; } #else asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val) { setup(); + val->choice = choice_trusted_cas_UNKNOWN; { begin_choice(); if (tagnum == choice_trusted_cas_principalName) { val->choice = choice_trusted_cas_principalName; + val->u.principalName = NULL; asn1_decode_krb5_principal_name(&subbuf, &(val->u.principalName)); } else if (tagnum == choice_trusted_cas_caName) { val->choice = choice_trusted_cas_caName; + val->u.caName.data = NULL; get_implicit_octet_string(val->u.caName.length, val->u.caName.data, choice_trusted_cas_caName); } else if (tagnum == choice_trusted_cas_issuerAndSerial) { val->choice = choice_trusted_cas_issuerAndSerial; + val->u.issuerAndSerial.data = NULL; get_implicit_octet_string(val->u.issuerAndSerial.length, val->u.issuerAndSerial.data, choice_trusted_cas_issuerAndSerial); - } else return ASN1_BAD_ID; + } else clean_return(ASN1_BAD_ID); end_choice(); } - cleanup(); + return 0; +error_out: + if (val->choice == choice_trusted_cas_caName) + free(val->u.caName.data); + else if (val->choice == choice_trusted_cas_issuerAndSerial) + free(val->u.issuerAndSerial.data); + val->choice = choice_trusted_cas_UNKNOWN; + return retval; } #endif +asn1_error_code +asn1_decode_trusted_ca_ptr(asn1buf *buf, krb5_trusted_ca **valptr) +{ + decode_ptr(krb5_trusted_ca *, asn1_decode_trusted_ca); +} + +static void free_trusted_ca(void *dummy, krb5_trusted_ca *val) +{ + if (val->choice == choice_trusted_cas_caName) + free(val->u.caName.data); + else if (val->choice == choice_trusted_cas_issuerAndSerial) + free(val->u.issuerAndSerial.data); + free(val); +} + asn1_error_code asn1_decode_sequence_of_trusted_ca(asn1buf *buf, krb5_trusted_ca ***val) { - decode_array_body(krb5_trusted_ca, asn1_decode_trusted_ca); + decode_array_body(krb5_trusted_ca, asn1_decode_trusted_ca_ptr, + free_trusted_ca); } asn1_error_code asn1_decode_pa_pk_as_req_draft9(asn1buf *buf, krb5_pa_pk_as_req_draft9 *val) { + int i; setup(); + val->signedAuthPack.data = NULL; + val->kdcCert.data = NULL; + val->encryptionCert.data = NULL; + val->trustedCertifiers = NULL; { begin_structure(); get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0); opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_trusted_ca, NULL); @@ -1347,24 +1828,47 @@ asn1_error_code asn1_decode_pa_pk_as_req_draft9(asn1buf *buf, krb5_pa_pk_as_req_ opt_lenfield(val->encryptionCert.length, val->encryptionCert.data, 2, asn1_decode_octetstring); end_structure(); } - cleanup(); + return 0; +error_out: + free(val->signedAuthPack.data); + free(val->kdcCert.data); + free(val->encryptionCert.data); + if (val->trustedCertifiers) { + for (i = 0; val->trustedCertifiers[i]; i++) + free_trusted_ca(NULL, val->trustedCertifiers[i]); + free(val->trustedCertifiers); + } + val->signedAuthPack.data = NULL; + val->kdcCert.data = NULL; + val->encryptionCert.data = NULL; + val->trustedCertifiers = NULL; + return retval; } asn1_error_code asn1_decode_dh_rep_info(asn1buf *buf, krb5_dh_rep_info *val) { setup(); + val->dhSignedData.data = NULL; + val->serverDHNonce.data = NULL; { begin_structure(); get_implicit_octet_string(val->dhSignedData.length, val->dhSignedData.data, 0); opt_lenfield(val->serverDHNonce.length, val->serverDHNonce.data, 1, asn1_decode_octetstring); end_structure(); } - cleanup(); + return 0; +error_out: + free(val->dhSignedData.data); + free(val->serverDHNonce.data); + val->dhSignedData.data = NULL; + val->serverDHNonce.data = NULL; + return retval; } asn1_error_code asn1_decode_pk_authenticator(asn1buf *buf, krb5_pk_authenticator *val) { setup(); + val->paChecksum.contents = NULL; { begin_structure(); get_field(val->cusec, 0, asn1_decode_int32); get_field(val->ctime, 1, asn1_decode_kerberos_time); @@ -1372,14 +1876,19 @@ asn1_error_code asn1_decode_pk_authenticator(asn1buf *buf, krb5_pk_authenticator opt_lenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_decode_octetstring); end_structure(); } - cleanup(); + return 0; +error_out: + krb5_free_checksum_contents(NULL, &val->paChecksum); + return retval; } asn1_error_code asn1_decode_pk_authenticator_draft9(asn1buf *buf, krb5_pk_authenticator_draft9 *val) { setup(); + val->kdcName = NULL; + val->kdcRealm.data = NULL; { begin_structure(); - alloc_field(val->kdcName,krb5_principal_data); + alloc_principal(val->kdcName); get_field(val->kdcName, 0, asn1_decode_principal_name); get_field(val->kdcName, 1, asn1_decode_realm); get_field(val->cusec, 2, asn1_decode_int32); @@ -1387,19 +1896,24 @@ asn1_error_code asn1_decode_pk_authenticator_draft9(asn1buf *buf, krb5_pk_authen get_field(val->nonce, 4, asn1_decode_int32); end_structure(); } - cleanup(); + return 0; +error_out: + krb5_free_principal(NULL, val->kdcName); + return retval; } asn1_error_code asn1_decode_algorithm_identifier(asn1buf *buf, krb5_algorithm_identifier *val) { setup(); + val->algorithm.data = NULL; + val->parameters.data = NULL; { begin_structure_no_tag(); /* * Forbid indefinite encoding because we don't read enough tag * information from the trailing octets ("ANY DEFINED BY") to * synchronize EOC tags, etc. */ - if (seqindef) return ASN1_BAD_FORMAT; + if (seqindef) clean_return(ASN1_BAD_FORMAT); /* * Set up tag variables because we don't actually call anything * that fetches tag info for us; it's all buried in the decoder @@ -1412,7 +1926,7 @@ asn1_error_code asn1_decode_algorithm_identifier(asn1buf *buf, krb5_algorithm_i indef = 0; retval = asn1_decode_oid(&subbuf, &val->algorithm.length, &val->algorithm.data); - if (retval) return retval; + if (retval) clean_return(retval); val->parameters.length = 0; val->parameters.data = NULL; @@ -1421,43 +1935,59 @@ asn1_error_code asn1_decode_algorithm_identifier(asn1buf *buf, krb5_algorithm_i unsigned int size = length - (subbuf.next - subbuf.base); retval = asn1buf_remove_octetstring(&subbuf, size, &val->parameters.data); - if (retval) return retval; + if (retval) clean_return(retval); val->parameters.length = size; } end_structure(); } - cleanup(); + return 0; +error_out: + free(val->algorithm.data); + free(val->parameters.data); + val->algorithm.data = NULL; + val->parameters.data = NULL; + return retval; +} + +asn1_error_code +asn1_decode_algorithm_identifier_ptr(asn1buf *buf, + krb5_algorithm_identifier **valptr) +{ + decode_ptr(krb5_algorithm_identifier *, asn1_decode_algorithm_identifier); } asn1_error_code asn1_decode_subject_pk_info(asn1buf *buf, krb5_subject_pk_info *val) { asn1_octet unused; setup(); + val->algorithm.algorithm.data = NULL; + val->algorithm.parameters.data = NULL; + val->subjectPublicKey.data = NULL; { begin_structure_no_tag(); retval = asn1_decode_algorithm_identifier(&subbuf, &val->algorithm); - if (retval) return retval; + if (retval) clean_return(retval); /* SubjectPublicKey encoded as a BIT STRING */ next_tag(); if (asn1class != UNIVERSAL || construction != PRIMITIVE || tagnum != ASN1_BITSTRING) - return ASN1_BAD_ID; + clean_return(ASN1_BAD_ID); retval = asn1buf_remove_octet(&subbuf, &unused); - if (retval) return retval; + if (retval) clean_return(retval); /* Number of unused bits must be between 0 and 7. */ /* What to do if unused is not zero? */ - if (unused > 7) return ASN1_BAD_FORMAT; + if (unused > 7) clean_return(ASN1_BAD_FORMAT); taglen--; val->subjectPublicKey.length = 0; val->subjectPublicKey.data = NULL; retval = asn1buf_remove_octetstring(&subbuf, taglen, &val->subjectPublicKey.data); - if (retval) return retval; + if (retval) clean_return(retval); val->subjectPublicKey.length = taglen; /* * We didn't call any macro that does next_tag(); do so now to @@ -1466,77 +1996,137 @@ asn1_error_code asn1_decode_subject_pk_info(asn1buf *buf, krb5_subject_pk_info * next_tag(); end_structure(); } - cleanup(); + return 0; +error_out: + free(val->algorithm.algorithm.data); + free(val->algorithm.parameters.data); + free(val->subjectPublicKey.data); + val->algorithm.algorithm.data = NULL; + val->algorithm.parameters.data = NULL; + val->subjectPublicKey.data = NULL; + return 0; +} + +static void +free_algorithm_identifier(void *dummy, krb5_algorithm_identifier *val) +{ + free(val->algorithm.data); + free(val->parameters.data); + free(val); } asn1_error_code asn1_decode_sequence_of_algorithm_identifier(asn1buf *buf, krb5_algorithm_identifier ***val) { - decode_array_body(krb5_algorithm_identifier, asn1_decode_algorithm_identifier); + decode_array_body(krb5_algorithm_identifier, + asn1_decode_algorithm_identifier_ptr, + free_algorithm_identifier); } asn1_error_code asn1_decode_kdc_dh_key_info (asn1buf *buf, krb5_kdc_dh_key_info *val) { setup(); + val->subjectPublicKey.data = NULL; { begin_structure(); retval = asn1buf_remove_octetstring(&subbuf, taglen, &val->subjectPublicKey.data); - if (retval) return retval; + if (retval) clean_return(retval); val->subjectPublicKey.length = taglen; next_tag(); get_field(val->nonce, 1, asn1_decode_int32); opt_field(val->dhKeyExpiration, 2, asn1_decode_kerberos_time, 0); end_structure(); } - cleanup(); + return 0; +error_out: + free(val->subjectPublicKey.data); + val->subjectPublicKey.data = NULL; + return retval; } asn1_error_code asn1_decode_reply_key_pack (asn1buf *buf, krb5_reply_key_pack *val) { setup(); + val->replyKey.contents = NULL; + val->asChecksum.contents = NULL; { begin_structure(); get_field(val->replyKey, 0, asn1_decode_encryption_key); get_field(val->asChecksum, 1, asn1_decode_checksum); end_structure(); } - cleanup(); + return 0; +error_out: + free(val->replyKey.contents); + free(val->asChecksum.contents); + val->replyKey.contents = NULL; + val->asChecksum.contents = NULL; + return retval; } asn1_error_code asn1_decode_reply_key_pack_draft9 (asn1buf *buf, krb5_reply_key_pack_draft9 *val) { setup(); + val->replyKey.contents = NULL; { begin_structure(); get_field(val->replyKey, 0, asn1_decode_encryption_key); get_field(val->nonce, 1, asn1_decode_int32); end_structure(); } - cleanup(); + return 0; +error_out: + free(val->replyKey.contents); + val->replyKey.contents = NULL; + return retval; } asn1_error_code asn1_decode_krb5_principal_name (asn1buf *buf, krb5_principal *val) { + int i; setup(); + (*val)->realm.data = NULL; + (*val)->data = NULL; { begin_structure(); get_field(*val, 0, asn1_decode_realm); get_field(*val, 1, asn1_decode_principal_name); end_structure(); } - cleanup(); + return 0; +error_out: + krb5_free_data_contents(NULL, &(*val)->realm); + if ((*val)->data) { + for (i = 0; i < (*val)->length; i++) + krb5_free_data_contents(NULL, &(*val)->data[i]); + free((*val)->data); + } + (*val)->realm.data = NULL; + (*val)->data = NULL; + return retval; } asn1_error_code asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val) { + int i; setup(); + val->clientPublicValue = NULL; + val->pkAuthenticator.paChecksum.contents = NULL; + val->supportedCMSTypes = NULL; + val->clientDHNonce.data = NULL; { begin_structure(); get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator); - if (tagnum == 1) { alloc_field(val->clientPublicValue, krb5_subject_pk_info); } + if (tagnum == 1) { + alloc_field(val->clientPublicValue); + val->clientPublicValue->algorithm.algorithm.data = NULL; + val->clientPublicValue->algorithm.parameters.data = NULL; + val->clientPublicValue->subjectPublicKey.data = NULL; + } /* can't call opt_field because it does decoder(&subbuf, &(val)); */ if (asn1buf_remains(&subbuf, seqindef)) { if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) && (tagnum || taglen || asn1class != UNIVERSAL)) - return ASN1_BAD_ID; + clean_return(ASN1_BAD_ID); if (tagnum == 1) { retval = asn1_decode_subject_pk_info(&subbuf, val->clientPublicValue); + if (retval) clean_return(retval); if (!taglen && indef) { get_eoc(); } next_tag(); } else val->clientPublicValue = NULL; @@ -1544,7 +2134,8 @@ asn1_error_code asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val) /* can't call opt_field because it does decoder(&subbuf, &(val)); */ if (asn1buf_remains(&subbuf, seqindef)) { if (tagnum == 2) { - asn1_decode_sequence_of_algorithm_identifier(&subbuf, &val->supportedCMSTypes); + retval = asn1_decode_sequence_of_algorithm_identifier(&subbuf, &val->supportedCMSTypes); + if (retval) clean_return(retval); if (!taglen && indef) { get_eoc(); } next_tag(); } else val->supportedCMSTypes = NULL; @@ -1552,24 +2143,49 @@ asn1_error_code asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val) opt_lenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_decode_octetstring); end_structure(); } - cleanup(); + return 0; +error_out: + if (val->clientPublicValue) { + free(val->clientPublicValue->algorithm.algorithm.data); + free(val->clientPublicValue->algorithm.parameters.data); + free(val->clientPublicValue->subjectPublicKey.data); + free(val->clientPublicValue); + } + free(val->pkAuthenticator.paChecksum.contents); + if (val->supportedCMSTypes) { + for (i = 0; val->supportedCMSTypes[i]; i++) + free_algorithm_identifier(NULL, val->supportedCMSTypes[i]); + free(val->supportedCMSTypes); + } + free(val->clientDHNonce.data); + val->clientPublicValue = NULL; + val->pkAuthenticator.paChecksum.contents = NULL; + val->supportedCMSTypes = NULL; + val->clientDHNonce.data = NULL; + return retval; } asn1_error_code asn1_decode_auth_pack_draft9(asn1buf *buf, krb5_auth_pack_draft9 *val) { setup(); + val->pkAuthenticator.kdcName = NULL; + val->clientPublicValue = NULL; { begin_structure(); get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator_draft9); if (tagnum == 1) { - alloc_field(val->clientPublicValue, krb5_subject_pk_info); + alloc_field(val->clientPublicValue); + val->clientPublicValue->algorithm.algorithm.data = NULL; + val->clientPublicValue->algorithm.parameters.data = NULL; + val->clientPublicValue->subjectPublicKey.data = NULL; /* can't call opt_field because it does decoder(&subbuf, &(val)); */ if (asn1buf_remains(&subbuf, seqindef)) { if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) && (tagnum || taglen || asn1class != UNIVERSAL)) - return ASN1_BAD_ID; + clean_return(ASN1_BAD_ID); if (tagnum == 1) { retval = asn1_decode_subject_pk_info(&subbuf, val->clientPublicValue); + if (retval) clean_return(retval); if (!taglen && indef) { get_eoc(); } next_tag(); } else val->clientPublicValue = NULL; @@ -1577,18 +2193,33 @@ asn1_error_code asn1_decode_auth_pack_draft9(asn1buf *buf, krb5_auth_pack_draft9 } end_structure(); } - cleanup(); + return 0; +error_out: + free(val->pkAuthenticator.kdcName); + if (val->clientPublicValue) { + free(val->clientPublicValue->algorithm.algorithm.data); + free(val->clientPublicValue->algorithm.parameters.data); + free(val->clientPublicValue->subjectPublicKey.data); + free(val->clientPublicValue); + } + val->pkAuthenticator.kdcName = NULL; + val->clientPublicValue = NULL; + return retval; } asn1_error_code asn1_decode_pa_pk_as_rep(asn1buf *buf, krb5_pa_pk_as_rep *val) { setup(); + val->choice = choice_pa_pk_as_rep_UNKNOWN; { begin_choice(); if (tagnum == choice_pa_pk_as_rep_dhInfo) { val->choice = choice_pa_pk_as_rep_dhInfo; + val->u.dh_Info.dhSignedData.data = NULL; + val->u.dh_Info.serverDHNonce.data = NULL; get_field_body(val->u.dh_Info, asn1_decode_dh_rep_info); } else if (tagnum == choice_pa_pk_as_rep_encKeyPack) { val->choice = choice_pa_pk_as_rep_encKeyPack; + val->u.encKeyPack.data = NULL; get_implicit_octet_string(val->u.encKeyPack.length, val->u.encKeyPack.data, choice_pa_pk_as_rep_encKeyPack); } else { @@ -1596,19 +2227,31 @@ asn1_error_code asn1_decode_pa_pk_as_rep(asn1buf *buf, krb5_pa_pk_as_rep *val) } end_choice(); } - cleanup(); + return 0; +error_out: + if (val->choice == choice_pa_pk_as_rep_dhInfo) { + free(val->u.dh_Info.dhSignedData.data); + free(val->u.dh_Info.serverDHNonce.data); + } else if (val->choice == choice_pa_pk_as_rep_encKeyPack) { + free(val->u.encKeyPack.data); + } + val->choice = choice_pa_pk_as_rep_UNKNOWN; + return retval; } asn1_error_code asn1_decode_pa_pk_as_rep_draft9(asn1buf *buf, krb5_pa_pk_as_rep_draft9 *val) { setup(); + val->choice = choice_pa_pk_as_rep_draft9_UNKNOWN; { begin_structure(); if (tagnum == choice_pa_pk_as_rep_draft9_dhSignedData) { val->choice = choice_pa_pk_as_rep_draft9_dhSignedData; + val->u.dhSignedData.data = NULL; get_lenfield(val->u.dhSignedData.length, val->u.dhSignedData.data, choice_pa_pk_as_rep_draft9_dhSignedData, asn1_decode_octetstring); } else if (tagnum == choice_pa_pk_as_rep_draft9_encKeyPack) { val->choice = choice_pa_pk_as_rep_draft9_encKeyPack; + val->u.encKeyPack.data = NULL; get_lenfield(val->u.encKeyPack.length, val->u.encKeyPack.data, choice_pa_pk_as_rep_draft9_encKeyPack, asn1_decode_octetstring); } else { @@ -1616,22 +2259,47 @@ asn1_error_code asn1_decode_pa_pk_as_rep_draft9(asn1buf *buf, krb5_pa_pk_as_rep_ } end_structure(); } - cleanup(); + return 0; +error_out: + if (val->choice == choice_pa_pk_as_rep_draft9_dhSignedData) + free(val->u.dhSignedData.data); + else if (val->choice == choice_pa_pk_as_rep_draft9_encKeyPack) + free(val->u.encKeyPack.data); + val->choice = choice_pa_pk_as_rep_draft9_UNKNOWN; + return retval; +} + +static void free_typed_data(void *dummy, krb5_typed_data *val) +{ + free(val->data); + free(val); } asn1_error_code asn1_decode_sequence_of_typed_data(asn1buf *buf, krb5_typed_data ***val) { - decode_array_body(krb5_typed_data,asn1_decode_typed_data); + decode_array_body(krb5_typed_data,asn1_decode_typed_data_ptr, + free_typed_data); } asn1_error_code asn1_decode_typed_data(asn1buf *buf, krb5_typed_data *val) { setup(); + val->data = NULL; { begin_structure(); get_field(val->type,0,asn1_decode_int32); get_lenfield(val->length,val->data,1,asn1_decode_octetstring); end_structure(); } - cleanup(); + return 0; +error_out: + free(val->data); + val->data = NULL; + return retval; +} + +asn1_error_code +asn1_decode_typed_data_ptr(asn1buf *buf, krb5_typed_data **valptr) +{ + decode_ptr(krb5_typed_data *, asn1_decode_typed_data); } #endif /* DISABLE_PKINIT */ diff --git a/src/lib/krb5/asn.1/asn1_k_decode.h b/src/lib/krb5/asn.1/asn1_k_decode.h index 3ec84c051..f258f65c4 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.h +++ b/src/lib/krb5/asn.1/asn1_k_decode.h @@ -104,8 +104,12 @@ asn1_error_code asn1_decode_principal_name (asn1buf *buf, krb5_principal *val); asn1_error_code asn1_decode_checksum (asn1buf *buf, krb5_checksum *val); +asn1_error_code asn1_decode_checksum_ptr + (asn1buf *buf, krb5_checksum **valptr); asn1_error_code asn1_decode_encryption_key (asn1buf *buf, krb5_keyblock *val); +asn1_error_code asn1_decode_encryption_key_ptr + (asn1buf *buf, krb5_keyblock **valptr); asn1_error_code asn1_decode_encrypted_data (asn1buf *buf, krb5_enc_data *val); asn1_error_code asn1_decode_ticket_flags @@ -122,6 +126,8 @@ asn1_error_code asn1_decode_kdc_options (asn1buf *buf, krb5_flags *val); asn1_error_code asn1_decode_ticket (asn1buf *buf, krb5_ticket *val); +asn1_error_code asn1_decode_ticket_ptr + (asn1buf *buf, krb5_ticket **valptr); asn1_error_code asn1_decode_kdc_req (asn1buf *buf, krb5_kdc_req *val); asn1_error_code asn1_decode_kdc_req_body @@ -130,18 +136,30 @@ asn1_error_code asn1_decode_krb_safe_body (asn1buf *buf, krb5_safe *val); asn1_error_code asn1_decode_host_address (asn1buf *buf, krb5_address *val); +asn1_error_code asn1_decode_host_address_ptr + (asn1buf *buf, krb5_address **valptr); asn1_error_code asn1_decode_kdc_rep (asn1buf *buf, krb5_kdc_rep *val); asn1_error_code asn1_decode_last_req_entry (asn1buf *buf, krb5_last_req_entry *val); +asn1_error_code asn1_decode_last_req_entry_ptr + (asn1buf *buf, krb5_last_req_entry **valptr); asn1_error_code asn1_decode_authdata_elt (asn1buf *buf, krb5_authdata *val); +asn1_error_code asn1_decode_authdata_elt_ptr + (asn1buf *buf, krb5_authdata **valptr); asn1_error_code asn1_decode_krb_cred_info (asn1buf *buf, krb5_cred_info *val); +asn1_error_code asn1_decode_krb_cred_info_ptr + (asn1buf *buf, krb5_cred_info **valptr); asn1_error_code asn1_decode_pa_data (asn1buf *buf, krb5_pa_data *val); +asn1_error_code asn1_decode_pa_data_ptr + (asn1buf *buf, krb5_pa_data **valptr); asn1_error_code asn1_decode_passwdsequence (asn1buf *buf, passwd_phrase_element *val); +asn1_error_code asn1_decode_passwdsequence_ptr + (asn1buf *buf, passwd_phrase_element **valptr); asn1_error_code asn1_decode_sam_challenge (asn1buf *buf, krb5_sam_challenge *val); asn1_error_code asn1_decode_sam_challenge_2 @@ -162,10 +180,14 @@ asn1_error_code asn1_decode_predicted_sam_response (asn1buf *buf, krb5_predicted_sam_response *val); asn1_error_code asn1_decode_external_principal_identifier (asn1buf *buf, krb5_external_principal_identifier *val); +asn1_error_code asn1_decode_external_principal_identifier_ptr + (asn1buf *buf, krb5_external_principal_identifier **valptr); asn1_error_code asn1_decode_pa_pk_as_req (asn1buf *buf, krb5_pa_pk_as_req *val); asn1_error_code asn1_decode_trusted_ca (asn1buf *buf, krb5_trusted_ca *val); +asn1_error_code asn1_decode_trusted_ca_ptr + (asn1buf *buf, krb5_trusted_ca **valptr); asn1_error_code asn1_decode_pa_pk_as_req_draft9 (asn1buf *buf, krb5_pa_pk_as_req_draft9 *val); asn1_error_code asn1_decode_dh_rep_info @@ -178,6 +200,8 @@ asn1_error_code asn1_decode_subject_pk_info (asn1buf *buf, krb5_subject_pk_info *val); asn1_error_code asn1_decode_algorithm_identifier (asn1buf *buf, krb5_algorithm_identifier *val); +asn1_error_code asn1_decode_algorithm_identifier_ptr + (asn1buf *buf, krb5_algorithm_identifier **valptr); asn1_error_code asn1_decode_auth_pack (asn1buf *buf, krb5_auth_pack *val); asn1_error_code asn1_decode_auth_pack_draft9 @@ -198,6 +222,8 @@ asn1_error_code asn1_decode_sequence_of_typed_data (asn1buf *buf, krb5_typed_data ***val); asn1_error_code asn1_decode_typed_data (asn1buf *buf, krb5_typed_data *val); +asn1_error_code asn1_decode_typed_data_ptr + (asn1buf *buf, krb5_typed_data **valptr); /* arrays */ asn1_error_code asn1_decode_authorization_data diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index 1f2cce803..57a83f1f8 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -1304,12 +1304,10 @@ MAKE_FULL_ENCODER(encode_krb5_etype_list, etype_list); { unsigned int length; \ 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; } @@ -1402,10 +1400,8 @@ asn1_error_code asn1_encode_algorithm_identifier(asn1buf *buf, const krb5_algori if (val->parameters.length != 0) { retval = asn1buf_insert_octetstring(buf, val->parameters.length, val->parameters.data); - if (retval) { - asn1buf_destroy(&buf); + if (retval) return retval; - } sum += val->parameters.length; } @@ -1415,10 +1411,8 @@ asn1_error_code asn1_encode_algorithm_identifier(asn1buf *buf, const krb5_algori val->algorithm.data, &length); - if (retval) { - asn1buf_destroy(&buf); + if (retval) return retval; - } sum += length; } @@ -1440,20 +1434,16 @@ asn1_error_code asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_ retval = asn1buf_insert_octetstring(buf, val->algorithm.parameters.length, val->algorithm.parameters.data); - if (retval) { - asn1buf_destroy(&buf); + if (retval) return retval; - } sum += val->algorithm.parameters.length; retval = asn1_encode_oid(buf, val->algorithm.algorithm.length, val->algorithm.algorithm.data, &length); - if (retval) { - asn1buf_destroy(&buf); + if (retval) return retval; - } sum += length; @@ -1461,10 +1451,8 @@ asn1_error_code asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_ val->algorithm.parameters.length + length, &length); - if (retval) { - asn1buf_destroy(&buf); + if (retval) return retval; - } sum += length; } @@ -1661,10 +1649,8 @@ asn1_error_code asn1_encode_kdc_dh_key_info(asn1buf *buf, const krb5_kdc_dh_key_ retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, val->subjectPublicKey.length + 1 + length, &length); - if (retval) { - asn1buf_destroy(&buf); + if (retval) return retval; - } sum += length; } @@ -1738,10 +1724,8 @@ asn1_error_code asn1_encode_td_trusted_certifiers(asn1buf *buf, const krb5_exter { unsigned int length; retval = asn1_encode_sequence_of_external_principal_identifier(buf, val, &length); - if (retval) { - asn1buf_destroy(&buf); + if (retval) return retval; - } /* length set but ignored? sum not updated? */ } asn1_cleanup(); diff --git a/src/lib/krb5/asn.1/asn1buf.c b/src/lib/krb5/asn.1/asn1buf.c index 71ad03b24..5793a0303 100644 --- a/src/lib/krb5/asn.1/asn1buf.c +++ b/src/lib/krb5/asn.1/asn1buf.c @@ -154,14 +154,13 @@ asn1_error_code asn1buf_skiptail(asn1buf *buf, const unsigned int length, const return 0; } -asn1_error_code asn1buf_destroy(asn1buf **buf) +void asn1buf_destroy(asn1buf **buf) { if (*buf != NULL) { free((*buf)->base); free(*buf); *buf = NULL; } - return 0; } #ifdef asn1buf_insert_octet @@ -254,21 +253,24 @@ int asn1buf_remains(asn1buf *buf, int indef) asn1_error_code asn12krb5_buf(const asn1buf *buf, krb5_data **code) { unsigned int i; - *code = (krb5_data*)calloc(1,sizeof(krb5_data)); - if (*code == NULL) return ENOMEM; - (*code)->magic = KV5M_DATA; - (*code)->data = NULL; - (*code)->length = 0; - (*code)->length = asn1buf_len(buf); - (*code)->data = (char*)malloc((((*code)->length)+1)*sizeof(char)); - if ((*code)->data == NULL) { - free(*code); - *code = NULL; + krb5_data *d; + + *code = NULL; + + d = calloc(1, sizeof(krb5_data)); + if (d == NULL) + return ENOMEM; + d->length = asn1buf_len(buf); + d->data = malloc(d->length + 1); + if (d->data == NULL) { + free(d); return ENOMEM; } - for (i=0; i < (*code)->length; i++) - ((*code)->data)[i] = (buf->base)[((*code)->length)-i-1]; - ((*code)->data)[(*code)->length] = '\0'; + for (i=0; i < d->length; i++) + d->data[i] = buf->base[d->length - i - 1]; + d->data[d->length] = '\0'; + d->magic = KV5M_DATA; + *code = d; return 0; } diff --git a/src/lib/krb5/asn.1/asn1buf.h b/src/lib/krb5/asn.1/asn1buf.h index 874d6db5c..33affbb07 100644 --- a/src/lib/krb5/asn.1/asn1buf.h +++ b/src/lib/krb5/asn.1/asn1buf.h @@ -129,7 +129,7 @@ asn1_error_code asn1buf_skiptail constructed indefinite sequence. effects skips trailing fields. */ -asn1_error_code asn1buf_destroy +void asn1buf_destroy (asn1buf **buf); /* effects Deallocates **buf, sets *buf to NULL. */ diff --git a/src/lib/krb5/asn.1/krb5_decode.c b/src/lib/krb5/asn.1/krb5_decode.c index 2d9a3daf7..b118c453c 100644 --- a/src/lib/krb5/asn.1/krb5_decode.c +++ b/src/lib/krb5/asn.1/krb5_decode.c @@ -35,34 +35,45 @@ /* set up variables */ /* the setup* macros can return, but are always used at function start and thus need no malloc cleanup */ -#define setup_buf_only()\ +#define setup_buf_only(type)\ asn1_error_code retval;\ asn1buf buf;\ +type rep = NULL;\ \ +*repptr = NULL;\ retval = asn1buf_wrap_data(&buf,code);\ if (retval) return retval -#define setup_no_tagnum()\ +#define setup_no_tagnum(type)\ asn1_class asn1class;\ asn1_construction construction;\ -setup_buf_only() +setup_buf_only(type) -#define setup_no_length()\ +#define setup_no_length(type)\ asn1_tagnum tagnum;\ -setup_no_tagnum() +setup_no_tagnum(type) -#define setup()\ +#define setup(type)\ unsigned int length;\ -setup_no_length() +setup_no_length(type) /* helper macros for cleanup */ #define clean_return(val) { retval = val; goto error_out; } /* alloc_field is the first thing to allocate storage that may need cleanup */ -#define alloc_field(var,type)\ -var = (type*)calloc(1,sizeof(type));\ +#define alloc_field(var)\ +var = calloc(1,sizeof(*var));\ if ((var) == NULL) clean_return(ENOMEM) +/* + * Allocate a principal and initialize enough fields for + * krb5_free_principal to have defined behavior. + */ +#define alloc_principal(var) \ + alloc_field(var); \ + var->realm.data = NULL; \ + var->data = NULL + /* process encoding header ***************************************/ /* decode tag and check that it == [APPLICATION tagnum] */ #define check_apptag(tagexpect) \ @@ -111,7 +122,7 @@ asn1_get_eoc_tag (asn1buf *buf) #define get_eoc() \ { \ retval = asn1_get_eoc_tag(&subbuf); \ - if (retval) return retval; \ + if (retval) clean_return(retval); \ } /* decode sequence header and initialize tagnum with the first field */ @@ -196,79 +207,76 @@ get_lenfield_body(len,var,decoder) /* finish up */ /* to make things less painful, assume the cleanup is passed rep */ #define cleanup(cleanup_routine)\ + *repptr = rep; \ return 0; \ error_out: \ - if (rep && *rep) { \ - cleanup_routine(*rep); \ - *rep = NULL; \ - } \ + if (rep) \ + cleanup_routine(rep); \ return retval; #define cleanup_none()\ + *repptr = rep; \ return 0; \ error_out: \ return retval; #define cleanup_manual()\ + *repptr = rep; \ return 0; #define free_field(rep,f) free((rep)->f) -#define clear_field(rep,f) (*(rep))->f = 0 +#define clear_field(rep,f) (rep)->f = 0 #ifndef LEAN_CLIENT -krb5_error_code decode_krb5_authenticator(const krb5_data *code, krb5_authenticator **rep) +krb5_error_code +decode_krb5_authenticator(const krb5_data *code, krb5_authenticator **repptr) { - setup(); - alloc_field(*rep,krb5_authenticator); + setup(krb5_authenticator *); + alloc_field(rep); clear_field(rep,subkey); clear_field(rep,checksum); clear_field(rep,client); + clear_field(rep,authorization_data); check_apptag(2); { begin_structure(); { krb5_kvno kvno; get_field(kvno,0,asn1_decode_kvno); if (kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); } - alloc_field((*rep)->client,krb5_principal_data); - get_field((*rep)->client,1,asn1_decode_realm); - get_field((*rep)->client,2,asn1_decode_principal_name); - if (tagnum == 3) { - alloc_field((*rep)->checksum,krb5_checksum); - get_field(*((*rep)->checksum),3,asn1_decode_checksum); } - get_field((*rep)->cusec,4,asn1_decode_int32); - get_field((*rep)->ctime,5,asn1_decode_kerberos_time); - if (tagnum == 6) { alloc_field((*rep)->subkey,krb5_keyblock); } - opt_field(*((*rep)->subkey),6,asn1_decode_encryption_key); - opt_field((*rep)->seq_number,7,asn1_decode_seqnum); - opt_field((*rep)->authorization_data,8,asn1_decode_authorization_data); - (*rep)->magic = KV5M_AUTHENTICATOR; + alloc_principal(rep->client); + get_field(rep->client,1,asn1_decode_realm); + get_field(rep->client,2,asn1_decode_principal_name); + opt_field(rep->checksum,3,asn1_decode_checksum_ptr); + get_field(rep->cusec,4,asn1_decode_int32); + get_field(rep->ctime,5,asn1_decode_kerberos_time); + opt_field(rep->subkey,6,asn1_decode_encryption_key_ptr); + opt_field(rep->seq_number,7,asn1_decode_seqnum); + opt_field(rep->authorization_data,8,asn1_decode_authorization_data); + rep->magic = KV5M_AUTHENTICATOR; end_structure(); } cleanup_manual(); error_out: - if (rep && *rep) { - free_field(*rep,subkey); - free_field(*rep,checksum); - free_field(*rep,client); - free(*rep); - *rep = NULL; - } + krb5_free_authenticator(NULL, rep); return retval; } #endif krb5_error_code KRB5_CALLCONV -krb5_decode_ticket(const krb5_data *code, krb5_ticket **rep) +krb5_decode_ticket(const krb5_data *code, krb5_ticket **repptr) { - return decode_krb5_ticket(code, rep); + return decode_krb5_ticket(code, repptr); } -krb5_error_code decode_krb5_ticket(const krb5_data *code, krb5_ticket **rep) +krb5_error_code +decode_krb5_ticket(const krb5_data *code, krb5_ticket **repptr) { - setup(); - alloc_field(*rep,krb5_ticket); + setup(krb5_ticket *); + alloc_field(rep); clear_field(rep,server); + clear_field(rep,enc_part.ciphertext.data); + clear_field(rep,enc_part2); check_apptag(1); { begin_structure(); @@ -276,131 +284,152 @@ krb5_error_code decode_krb5_ticket(const krb5_data *code, krb5_ticket **rep) get_field(kvno,0,asn1_decode_kvno); if (kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); } - alloc_field((*rep)->server,krb5_principal_data); - get_field((*rep)->server,1,asn1_decode_realm); - get_field((*rep)->server,2,asn1_decode_principal_name); - get_field((*rep)->enc_part,3,asn1_decode_encrypted_data); - (*rep)->magic = KV5M_TICKET; + alloc_principal(rep->server); + get_field(rep->server,1,asn1_decode_realm); + get_field(rep->server,2,asn1_decode_principal_name); + get_field(rep->enc_part,3,asn1_decode_encrypted_data); + rep->magic = KV5M_TICKET; end_structure(); } cleanup_manual(); error_out: - if (rep && *rep) { - free_field(*rep,server); - free(*rep); - *rep = NULL; - } + krb5_free_ticket(NULL, rep); return retval; } -krb5_error_code decode_krb5_encryption_key(const krb5_data *code, krb5_keyblock **rep) +krb5_error_code +decode_krb5_encryption_key(const krb5_data *code, krb5_keyblock **repptr) { - setup(); - alloc_field(*rep,krb5_keyblock); + setup(krb5_keyblock *); + alloc_field(rep); + clear_field(rep,contents); { begin_structure(); - get_field((*rep)->enctype,0,asn1_decode_enctype); - get_lenfield((*rep)->length,(*rep)->contents,1,asn1_decode_octetstring); + get_field(rep->enctype,0,asn1_decode_enctype); + get_lenfield(rep->length,rep->contents,1,asn1_decode_octetstring); end_structure(); - (*rep)->magic = KV5M_KEYBLOCK; + rep->magic = KV5M_KEYBLOCK; } - cleanup(free); + cleanup_manual(); +error_out: + krb5_free_keyblock(NULL, rep); + return retval; } -krb5_error_code decode_krb5_enc_tkt_part(const krb5_data *code, krb5_enc_tkt_part **rep) +krb5_error_code +decode_krb5_enc_tkt_part(const krb5_data *code, krb5_enc_tkt_part **repptr) { - setup(); - alloc_field(*rep,krb5_enc_tkt_part); + setup(krb5_enc_tkt_part *); + alloc_field(rep); clear_field(rep,session); clear_field(rep,client); + clear_field(rep,transited.tr_contents.data); + clear_field(rep,caddrs); + clear_field(rep,authorization_data); check_apptag(3); { begin_structure(); - get_field((*rep)->flags,0,asn1_decode_ticket_flags); - alloc_field((*rep)->session,krb5_keyblock); - get_field(*((*rep)->session),1,asn1_decode_encryption_key); - alloc_field((*rep)->client,krb5_principal_data); - get_field((*rep)->client,2,asn1_decode_realm); - get_field((*rep)->client,3,asn1_decode_principal_name); - get_field((*rep)->transited,4,asn1_decode_transited_encoding); - get_field((*rep)->times.authtime,5,asn1_decode_kerberos_time); + get_field(rep->flags,0,asn1_decode_ticket_flags); + get_field(rep->session,1,asn1_decode_encryption_key_ptr); + alloc_principal(rep->client); + get_field(rep->client,2,asn1_decode_realm); + get_field(rep->client,3,asn1_decode_principal_name); + get_field(rep->transited,4,asn1_decode_transited_encoding); + get_field(rep->times.authtime,5,asn1_decode_kerberos_time); if (tagnum == 6) - { get_field((*rep)->times.starttime,6,asn1_decode_kerberos_time); } + { get_field(rep->times.starttime,6,asn1_decode_kerberos_time); } else - (*rep)->times.starttime=(*rep)->times.authtime; - get_field((*rep)->times.endtime,7,asn1_decode_kerberos_time); - opt_field((*rep)->times.renew_till,8,asn1_decode_kerberos_time); - opt_field((*rep)->caddrs,9,asn1_decode_host_addresses); - opt_field((*rep)->authorization_data,10,asn1_decode_authorization_data); - (*rep)->magic = KV5M_ENC_TKT_PART; + rep->times.starttime=rep->times.authtime; + get_field(rep->times.endtime,7,asn1_decode_kerberos_time); + opt_field(rep->times.renew_till,8,asn1_decode_kerberos_time); + opt_field(rep->caddrs,9,asn1_decode_host_addresses); + opt_field(rep->authorization_data,10,asn1_decode_authorization_data); + rep->magic = KV5M_ENC_TKT_PART; end_structure(); } cleanup_manual(); error_out: - if (rep && *rep) { - free_field(*rep,session); - free_field(*rep,client); - free(*rep); - *rep = NULL; - } + krb5_free_enc_tkt_part(NULL, rep); return retval; } -krb5_error_code decode_krb5_enc_kdc_rep_part(const krb5_data *code, krb5_enc_kdc_rep_part **rep) +krb5_error_code +decode_krb5_enc_kdc_rep_part(const krb5_data *code, + krb5_enc_kdc_rep_part **repptr) { taginfo t4; - setup_buf_only(); - alloc_field(*rep,krb5_enc_kdc_rep_part); + setup_buf_only(krb5_enc_kdc_rep_part *); + alloc_field(rep); retval = asn1_get_tag_2(&buf, &t4); if (retval) clean_return(retval); if (t4.asn1class != APPLICATION || t4.construction != CONSTRUCTED) clean_return(ASN1_BAD_ID); - if (t4.tagnum == 25) (*rep)->msg_type = KRB5_AS_REP; - else if (t4.tagnum == 26) (*rep)->msg_type = KRB5_TGS_REP; + if (t4.tagnum == 25) rep->msg_type = KRB5_AS_REP; + else if (t4.tagnum == 26) rep->msg_type = KRB5_TGS_REP; else clean_return(KRB5_BADMSGTYPE); - retval = asn1_decode_enc_kdc_rep_part(&buf,*rep); + retval = asn1_decode_enc_kdc_rep_part(&buf,rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_as_rep(const krb5_data *code, krb5_kdc_rep **rep) +krb5_error_code +decode_krb5_as_rep(const krb5_data *code, krb5_kdc_rep **repptr) { - setup_no_length(); - alloc_field(*rep,krb5_kdc_rep); + setup_no_length(krb5_kdc_rep *); + alloc_field(rep); + clear_field(rep,padata); + clear_field(rep,client); + clear_field(rep,ticket); + clear_field(rep,enc_part.ciphertext.data); + clear_field(rep,enc_part2); check_apptag(11); - retval = asn1_decode_kdc_rep(&buf,*rep); + retval = asn1_decode_kdc_rep(&buf,rep); if (retval) clean_return(retval); #ifdef KRB5_MSGTYPE_STRICT - if ((*rep)->msg_type != KRB5_AS_REP) + if (rep->msg_type != KRB5_AS_REP) clean_return(KRB5_BADMSGTYPE); #endif - cleanup(free); + cleanup_manual(); +error_out: + krb5_free_kdc_rep(NULL, rep); + return retval; } -krb5_error_code decode_krb5_tgs_rep(const krb5_data *code, krb5_kdc_rep **rep) +krb5_error_code +decode_krb5_tgs_rep(const krb5_data *code, krb5_kdc_rep **repptr) { - setup_no_length(); - alloc_field(*rep,krb5_kdc_rep); + setup_no_length(krb5_kdc_rep *); + alloc_field(rep); + clear_field(rep,padata); + clear_field(rep,client); + clear_field(rep,ticket); + clear_field(rep,enc_part.ciphertext.data); + clear_field(rep,enc_part2); check_apptag(13); - retval = asn1_decode_kdc_rep(&buf,*rep); + retval = asn1_decode_kdc_rep(&buf,rep); if (retval) clean_return(retval); #ifdef KRB5_MSGTYPE_STRICT - if ((*rep)->msg_type != KRB5_TGS_REP) clean_return(KRB5_BADMSGTYPE); + if (rep->msg_type != KRB5_TGS_REP) clean_return(KRB5_BADMSGTYPE); #endif - cleanup(free); + cleanup_manual(); +error_out: + krb5_free_kdc_rep(NULL, rep); + return retval; } -krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep) +krb5_error_code +decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **repptr) { - setup(); - alloc_field(*rep,krb5_ap_req); + setup(krb5_ap_req *); + alloc_field(rep); clear_field(rep,ticket); + clear_field(rep,authenticator.ciphertext.data); check_apptag(14); { begin_structure(); @@ -413,27 +442,24 @@ krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep) if (msg_type != KRB5_AP_REQ) clean_return(KRB5_BADMSGTYPE); #endif } - get_field((*rep)->ap_options,2,asn1_decode_ap_options); - alloc_field((*rep)->ticket,krb5_ticket); - get_field(*((*rep)->ticket),3,asn1_decode_ticket); - get_field((*rep)->authenticator,4,asn1_decode_encrypted_data); + get_field(rep->ap_options,2,asn1_decode_ap_options); + get_field(rep->ticket,3,asn1_decode_ticket_ptr); + get_field(rep->authenticator,4,asn1_decode_encrypted_data); end_structure(); - (*rep)->magic = KV5M_AP_REQ; + rep->magic = KV5M_AP_REQ; } cleanup_manual(); error_out: - if (rep && *rep) { - free_field(*rep,ticket); - free(*rep); - *rep = NULL; - } + krb5_free_ap_req(NULL, rep); return retval; } -krb5_error_code decode_krb5_ap_rep(const krb5_data *code, krb5_ap_rep **rep) +krb5_error_code +decode_krb5_ap_rep(const krb5_data *code, krb5_ap_rep **repptr) { - setup(); - alloc_field(*rep,krb5_ap_rep); + setup(krb5_ap_rep *); + alloc_field(rep); + clear_field(rep,enc_part.ciphertext.data); check_apptag(15); { begin_structure(); @@ -446,75 +472,100 @@ krb5_error_code decode_krb5_ap_rep(const krb5_data *code, krb5_ap_rep **rep) if (msg_type != KRB5_AP_REP) clean_return(KRB5_BADMSGTYPE); #endif } - get_field((*rep)->enc_part,2,asn1_decode_encrypted_data); + get_field(rep->enc_part,2,asn1_decode_encrypted_data); end_structure(); - (*rep)->magic = KV5M_AP_REP; + rep->magic = KV5M_AP_REP; } - cleanup(free); + cleanup_manual(); +error_out: + krb5_free_ap_rep(NULL, rep); + return retval; } -krb5_error_code decode_krb5_ap_rep_enc_part(const krb5_data *code, krb5_ap_rep_enc_part **rep) +krb5_error_code +decode_krb5_ap_rep_enc_part(const krb5_data *code, + krb5_ap_rep_enc_part **repptr) { - setup(); - alloc_field(*rep,krb5_ap_rep_enc_part); + setup(krb5_ap_rep_enc_part *); + alloc_field(rep); clear_field(rep,subkey); check_apptag(27); { begin_structure(); - get_field((*rep)->ctime,0,asn1_decode_kerberos_time); - get_field((*rep)->cusec,1,asn1_decode_int32); - if (tagnum == 2) { alloc_field((*rep)->subkey,krb5_keyblock); } - opt_field(*((*rep)->subkey),2,asn1_decode_encryption_key); - opt_field((*rep)->seq_number,3,asn1_decode_seqnum); + get_field(rep->ctime,0,asn1_decode_kerberos_time); + get_field(rep->cusec,1,asn1_decode_int32); + opt_field(rep->subkey,2,asn1_decode_encryption_key_ptr); + opt_field(rep->seq_number,3,asn1_decode_seqnum); end_structure(); - (*rep)->magic = KV5M_AP_REP_ENC_PART; + rep->magic = KV5M_AP_REP_ENC_PART; } cleanup_manual(); error_out: - if (rep && *rep) { - free_field(*rep,subkey); - free(*rep); - *rep = NULL; - } + krb5_free_ap_rep_enc_part(NULL, rep); return retval; } -krb5_error_code decode_krb5_as_req(const krb5_data *code, krb5_kdc_req **rep) +krb5_error_code +decode_krb5_as_req(const krb5_data *code, krb5_kdc_req **repptr) { - setup_no_length(); - alloc_field(*rep,krb5_kdc_req); + setup_no_length(krb5_kdc_req *); + alloc_field(rep); + clear_field(rep,padata); + clear_field(rep,client); + clear_field(rep,server); + clear_field(rep,ktype); + clear_field(rep,addresses); + clear_field(rep,authorization_data.ciphertext.data); + clear_field(rep,unenc_authdata); + clear_field(rep,second_ticket); check_apptag(10); - retval = asn1_decode_kdc_req(&buf,*rep); + retval = asn1_decode_kdc_req(&buf,rep); if (retval) clean_return(retval); #ifdef KRB5_MSGTYPE_STRICT - if ((*rep)->msg_type != KRB5_AS_REQ) clean_return(KRB5_BADMSGTYPE); + if (rep->msg_type != KRB5_AS_REQ) clean_return(KRB5_BADMSGTYPE); #endif - cleanup(free); + cleanup_manual(); +error_out: + krb5_free_kdc_req(NULL, rep); + return retval; } -krb5_error_code decode_krb5_tgs_req(const krb5_data *code, krb5_kdc_req **rep) +krb5_error_code +decode_krb5_tgs_req(const krb5_data *code, krb5_kdc_req **repptr) { - setup_no_length(); - alloc_field(*rep,krb5_kdc_req); + setup_no_length(krb5_kdc_req *); + alloc_field(rep); + clear_field(rep,padata); + clear_field(rep,client); + clear_field(rep,server); + clear_field(rep,ktype); + clear_field(rep,addresses); + clear_field(rep,authorization_data.ciphertext.data); + clear_field(rep,unenc_authdata); + clear_field(rep,second_ticket); check_apptag(12); - retval = asn1_decode_kdc_req(&buf,*rep); + retval = asn1_decode_kdc_req(&buf,rep); if (retval) clean_return(retval); #ifdef KRB5_MSGTYPE_STRICT - if ((*rep)->msg_type != KRB5_TGS_REQ) clean_return(KRB5_BADMSGTYPE); + if (rep->msg_type != KRB5_TGS_REQ) clean_return(KRB5_BADMSGTYPE); #endif - cleanup(free); + cleanup_manual(); +error_out: + krb5_free_kdc_req(NULL, rep); + return retval; } -krb5_error_code decode_krb5_kdc_req_body(const krb5_data *code, krb5_kdc_req **rep) +krb5_error_code +decode_krb5_kdc_req_body(const krb5_data *code, krb5_kdc_req **repptr) { - setup_buf_only(); - alloc_field(*rep,krb5_kdc_req); + setup_buf_only(krb5_kdc_req *); + alloc_field(rep); - retval = asn1_decode_kdc_req_body(&buf,*rep); + retval = asn1_decode_kdc_req_body(&buf,rep); if (retval) clean_return(retval); cleanup(free); @@ -534,14 +585,16 @@ krb5_error_code decode_krb5_kdc_req_body(const krb5_data *code, krb5_kdc_req **r * This does *not* perform any copying; the returned pointer to the * encoded KRB-SAFE-BODY points into the input buffer. */ -krb5_error_code decode_krb5_safe_with_body( - const krb5_data *code, - krb5_safe **rep, - krb5_data *body) +krb5_error_code +decode_krb5_safe_with_body(const krb5_data *code, krb5_safe **repptr, + krb5_data *body) { krb5_data tmpbody; - setup(); - alloc_field(*rep,krb5_safe); + setup(krb5_safe *); + alloc_field(rep); + clear_field(rep,user_data.data); + clear_field(rep,r_address); + clear_field(rep,s_address); clear_field(rep,checksum); tmpbody.magic = 0; @@ -568,33 +621,31 @@ krb5_error_code decode_krb5_safe_with_body( tmpbody.length = 0; tmpbody.data = NULL; } - get_field(**rep,2,asn1_decode_krb_safe_body); - alloc_field((*rep)->checksum,krb5_checksum); - get_field(*((*rep)->checksum),3,asn1_decode_checksum); - (*rep)->magic = KV5M_SAFE; + get_field(*rep,2,asn1_decode_krb_safe_body); + get_field(rep->checksum,3,asn1_decode_checksum_ptr); + rep->magic = KV5M_SAFE; end_structure(); } if (body != NULL) *body = tmpbody; cleanup_manual(); error_out: - if (rep && *rep) { - free_field(*rep,checksum); - free(*rep); - *rep = NULL; - } + krb5_free_safe(NULL, rep); return retval; } -krb5_error_code decode_krb5_safe(const krb5_data *code, krb5_safe **rep) +krb5_error_code +decode_krb5_safe(const krb5_data *code, krb5_safe **repptr) { - return decode_krb5_safe_with_body(code, rep, NULL); + return decode_krb5_safe_with_body(code, repptr, NULL); } -krb5_error_code decode_krb5_priv(const krb5_data *code, krb5_priv **rep) +krb5_error_code +decode_krb5_priv(const krb5_data *code, krb5_priv **repptr) { - setup(); - alloc_field(*rep,krb5_priv); + setup(krb5_priv *); + alloc_field(rep); + clear_field(rep,enc_part.ciphertext.data); check_apptag(21); { begin_structure(); @@ -607,48 +658,49 @@ krb5_error_code decode_krb5_priv(const krb5_data *code, krb5_priv **rep) if (msg_type != KRB5_PRIV) clean_return(KRB5_BADMSGTYPE); #endif } - get_field((*rep)->enc_part,3,asn1_decode_encrypted_data); - (*rep)->magic = KV5M_PRIV; + get_field(rep->enc_part,3,asn1_decode_encrypted_data); + rep->magic = KV5M_PRIV; end_structure(); } - cleanup(free); + cleanup_manual(); +error_out: + krb5_free_priv(NULL, rep); + return retval; } -krb5_error_code decode_krb5_enc_priv_part(const krb5_data *code, krb5_priv_enc_part **rep) +krb5_error_code +decode_krb5_enc_priv_part(const krb5_data *code, krb5_priv_enc_part **repptr) { - setup(); - alloc_field(*rep,krb5_priv_enc_part); + setup(krb5_priv_enc_part *); + alloc_field(rep); + clear_field(rep,user_data.data); clear_field(rep,r_address); clear_field(rep,s_address); check_apptag(28); { begin_structure(); - get_lenfield((*rep)->user_data.length,(*rep)->user_data.data,0,asn1_decode_charstring); - opt_field((*rep)->timestamp,1,asn1_decode_kerberos_time); - opt_field((*rep)->usec,2,asn1_decode_int32); - opt_field((*rep)->seq_number,3,asn1_decode_seqnum); - alloc_field((*rep)->s_address,krb5_address); - get_field(*((*rep)->s_address),4,asn1_decode_host_address); - if (tagnum == 5) { alloc_field((*rep)->r_address,krb5_address); } - opt_field(*((*rep)->r_address),5,asn1_decode_host_address); - (*rep)->magic = KV5M_PRIV_ENC_PART; + get_lenfield(rep->user_data.length,rep->user_data.data,0,asn1_decode_charstring); + opt_field(rep->timestamp,1,asn1_decode_kerberos_time); + opt_field(rep->usec,2,asn1_decode_int32); + opt_field(rep->seq_number,3,asn1_decode_seqnum); + get_field(rep->s_address,4,asn1_decode_host_address_ptr); + opt_field(rep->r_address,5,asn1_decode_host_address_ptr); + rep->magic = KV5M_PRIV_ENC_PART; end_structure(); } cleanup_manual(); error_out: - if (rep && *rep) { - free_field(*rep,r_address); - free_field(*rep,s_address); - free(*rep); - *rep = NULL; - } + krb5_free_priv_enc_part(NULL, rep); return retval; } -krb5_error_code decode_krb5_cred(const krb5_data *code, krb5_cred **rep) +krb5_error_code +decode_krb5_cred(const krb5_data *code, krb5_cred **repptr) { - setup(); - alloc_field(*rep,krb5_cred); + setup(krb5_cred *); + alloc_field(rep); + clear_field(rep,tickets); + clear_field(rep,enc_part.ciphertext.data); check_apptag(22); { begin_structure(); @@ -661,52 +713,55 @@ krb5_error_code decode_krb5_cred(const krb5_data *code, krb5_cred **rep) if (msg_type != KRB5_CRED) clean_return(KRB5_BADMSGTYPE); #endif } - get_field((*rep)->tickets,2,asn1_decode_sequence_of_ticket); - get_field((*rep)->enc_part,3,asn1_decode_encrypted_data); - (*rep)->magic = KV5M_CRED; + get_field(rep->tickets,2,asn1_decode_sequence_of_ticket); + get_field(rep->enc_part,3,asn1_decode_encrypted_data); + rep->magic = KV5M_CRED; end_structure(); } - cleanup(free); + cleanup_manual(); +error_out: + krb5_free_cred(NULL, rep); + return retval; } -krb5_error_code decode_krb5_enc_cred_part(const krb5_data *code, krb5_cred_enc_part **rep) +krb5_error_code +decode_krb5_enc_cred_part(const krb5_data *code, krb5_cred_enc_part **repptr) { - setup(); - alloc_field(*rep,krb5_cred_enc_part); + setup(krb5_cred_enc_part *); + alloc_field(rep); clear_field(rep,r_address); clear_field(rep,s_address); + clear_field(rep,ticket_info); check_apptag(29); { begin_structure(); - get_field((*rep)->ticket_info,0,asn1_decode_sequence_of_krb_cred_info); - opt_field((*rep)->nonce,1,asn1_decode_int32); - opt_field((*rep)->timestamp,2,asn1_decode_kerberos_time); - opt_field((*rep)->usec,3,asn1_decode_int32); - if (tagnum == 4) { alloc_field((*rep)->s_address,krb5_address); } - opt_field(*((*rep)->s_address),4,asn1_decode_host_address); - if (tagnum == 5) { alloc_field((*rep)->r_address,krb5_address); } - opt_field(*((*rep)->r_address),5,asn1_decode_host_address); - (*rep)->magic = KV5M_CRED_ENC_PART; + get_field(rep->ticket_info,0,asn1_decode_sequence_of_krb_cred_info); + opt_field(rep->nonce,1,asn1_decode_int32); + opt_field(rep->timestamp,2,asn1_decode_kerberos_time); + opt_field(rep->usec,3,asn1_decode_int32); + opt_field(rep->s_address,4,asn1_decode_host_address_ptr); + opt_field(rep->r_address,5,asn1_decode_host_address_ptr); + rep->magic = KV5M_CRED_ENC_PART; end_structure(); } cleanup_manual(); error_out: - if (rep && *rep) { - free_field(*rep,r_address); - free_field(*rep,s_address); - free(*rep); - *rep = NULL; - } + /* Despite the name, krb5_free_cred_enc_part is contents only. */ + krb5_free_cred_enc_part(NULL, rep); + free(rep); return retval; } -krb5_error_code decode_krb5_error(const krb5_data *code, krb5_error **rep) +krb5_error_code +decode_krb5_error(const krb5_data *code, krb5_error **repptr) { - setup(); - alloc_field(*rep,krb5_error); + setup(krb5_error *); + alloc_field(rep); clear_field(rep,server); clear_field(rep,client); + clear_field(rep,text.data); + clear_field(rep,e_data.data); check_apptag(30); { begin_structure(); @@ -719,427 +774,466 @@ krb5_error_code decode_krb5_error(const krb5_data *code, krb5_error **rep) if (msg_type != KRB5_ERROR) clean_return(KRB5_BADMSGTYPE); #endif } - opt_field((*rep)->ctime,2,asn1_decode_kerberos_time); - opt_field((*rep)->cusec,3,asn1_decode_int32); - get_field((*rep)->stime,4,asn1_decode_kerberos_time); - get_field((*rep)->susec,5,asn1_decode_int32); - get_field((*rep)->error,6,asn1_decode_ui_4); - if (tagnum == 7) { alloc_field((*rep)->client,krb5_principal_data); } - opt_field((*rep)->client,7,asn1_decode_realm); - opt_field((*rep)->client,8,asn1_decode_principal_name); - alloc_field((*rep)->server,krb5_principal_data); - get_field((*rep)->server,9,asn1_decode_realm); - get_field((*rep)->server,10,asn1_decode_principal_name); - opt_lenfield((*rep)->text.length,(*rep)->text.data,11,asn1_decode_generalstring); - opt_lenfield((*rep)->e_data.length,(*rep)->e_data.data,12,asn1_decode_charstring); - (*rep)->magic = KV5M_ERROR; + opt_field(rep->ctime,2,asn1_decode_kerberos_time); + opt_field(rep->cusec,3,asn1_decode_int32); + get_field(rep->stime,4,asn1_decode_kerberos_time); + get_field(rep->susec,5,asn1_decode_int32); + get_field(rep->error,6,asn1_decode_ui_4); + if (tagnum == 7) { alloc_principal(rep->client); } + opt_field(rep->client,7,asn1_decode_realm); + opt_field(rep->client,8,asn1_decode_principal_name); + alloc_principal(rep->server); + get_field(rep->server,9,asn1_decode_realm); + get_field(rep->server,10,asn1_decode_principal_name); + opt_lenfield(rep->text.length,rep->text.data,11,asn1_decode_generalstring); + opt_lenfield(rep->e_data.length,rep->e_data.data,12,asn1_decode_charstring); + rep->magic = KV5M_ERROR; end_structure(); } cleanup_manual(); error_out: - if (rep && *rep) { - free_field(*rep,server); - free_field(*rep,client); - free(*rep); - *rep = NULL; - } + krb5_free_error(NULL, rep); return retval; } -krb5_error_code decode_krb5_authdata(const krb5_data *code, krb5_authdata ***rep) +krb5_error_code +decode_krb5_authdata(const krb5_data *code, krb5_authdata ***repptr) { - setup_buf_only(); - *rep = 0; - retval = asn1_decode_authorization_data(&buf,rep); + setup_buf_only(krb5_authdata **); + retval = asn1_decode_authorization_data(&buf,&rep); if (retval) clean_return(retval); cleanup_none(); /* we're not allocating anything here... */ } -krb5_error_code decode_krb5_pwd_sequence(const krb5_data *code, passwd_phrase_element **rep) +krb5_error_code +decode_krb5_pwd_sequence(const krb5_data *code, passwd_phrase_element **repptr) { - setup_buf_only(); - alloc_field(*rep,passwd_phrase_element); - retval = asn1_decode_passwdsequence(&buf,*rep); + setup_buf_only(passwd_phrase_element *); + alloc_field(rep); + retval = asn1_decode_passwdsequence(&buf,rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_pwd_data(const krb5_data *code, krb5_pwd_data **rep) +krb5_error_code +decode_krb5_pwd_data(const krb5_data *code, krb5_pwd_data **repptr) { - setup(); - alloc_field(*rep,krb5_pwd_data); + setup(krb5_pwd_data *); + alloc_field(rep); + clear_field(rep,element); { begin_structure(); - get_field((*rep)->sequence_count,0,asn1_decode_int); - get_field((*rep)->element,1,asn1_decode_sequence_of_passwdsequence); - (*rep)->magic = KV5M_PWD_DATA; + get_field(rep->sequence_count,0,asn1_decode_int); + get_field(rep->element,1,asn1_decode_sequence_of_passwdsequence); + rep->magic = KV5M_PWD_DATA; end_structure (); } - cleanup(free); + cleanup_manual(); +error_out: + krb5_free_pwd_data(NULL, rep); + return retval; } -krb5_error_code decode_krb5_padata_sequence(const krb5_data *code, krb5_pa_data ***rep) +krb5_error_code +decode_krb5_padata_sequence(const krb5_data *code, krb5_pa_data ***repptr) { - setup_buf_only(); - *rep = 0; - retval = asn1_decode_sequence_of_pa_data(&buf,rep); + setup_buf_only(krb5_pa_data **); + retval = asn1_decode_sequence_of_pa_data(&buf,&rep); if (retval) clean_return(retval); cleanup_none(); /* we're not allocating anything here */ } -krb5_error_code decode_krb5_alt_method(const krb5_data *code, krb5_alt_method **rep) +krb5_error_code +decode_krb5_alt_method(const krb5_data *code, krb5_alt_method **repptr) { - setup(); - alloc_field(*rep,krb5_alt_method); + setup(krb5_alt_method *); + alloc_field(rep); + clear_field(rep,data); { begin_structure(); - get_field((*rep)->method,0,asn1_decode_int32); + get_field(rep->method,0,asn1_decode_int32); if (tagnum == 1) { - get_lenfield((*rep)->length,(*rep)->data,1,asn1_decode_octetstring); + get_lenfield(rep->length,rep->data,1,asn1_decode_octetstring); } else { - (*rep)->length = 0; - (*rep)->data = 0; + rep->length = 0; + rep->data = 0; } - (*rep)->magic = KV5M_ALT_METHOD; + rep->magic = KV5M_ALT_METHOD; end_structure(); } - cleanup(free); + cleanup_manual(); +error_out: + krb5_free_alt_method(NULL, rep); + return retval; } -krb5_error_code decode_krb5_etype_info(const krb5_data *code, krb5_etype_info_entry ***rep) +krb5_error_code +decode_krb5_etype_info(const krb5_data *code, krb5_etype_info_entry ***repptr) { - setup_buf_only(); - *rep = 0; - retval = asn1_decode_etype_info(&buf,rep); + setup_buf_only(krb5_etype_info_entry **); + retval = asn1_decode_etype_info(&buf,&rep); if (retval) clean_return(retval); cleanup_none(); /* we're not allocating anything here */ } -krb5_error_code decode_krb5_etype_info2(const krb5_data *code, krb5_etype_info_entry ***rep) +krb5_error_code +decode_krb5_etype_info2(const krb5_data *code, krb5_etype_info_entry ***repptr) { - setup_buf_only(); - *rep = 0; - retval = asn1_decode_etype_info2(&buf,rep, 0); + setup_buf_only(krb5_etype_info_entry **); + retval = asn1_decode_etype_info2(&buf,&rep, 0); if (retval == ASN1_BAD_ID) { retval = asn1buf_wrap_data(&buf,code); if (retval) clean_return(retval); - retval = asn1_decode_etype_info2(&buf, rep, 1); + retval = asn1_decode_etype_info2(&buf, &rep, 1); } if (retval) clean_return(retval); cleanup_none(); /* we're not allocating anything here */ } -krb5_error_code decode_krb5_enc_data(const krb5_data *code, krb5_enc_data **rep) +krb5_error_code +decode_krb5_enc_data(const krb5_data *code, krb5_enc_data **repptr) { - setup_buf_only(); - alloc_field(*rep,krb5_enc_data); + setup_buf_only(krb5_enc_data *); + alloc_field(rep); - retval = asn1_decode_encrypted_data(&buf,*rep); + retval = asn1_decode_encrypted_data(&buf,rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_pa_enc_ts(const krb5_data *code, krb5_pa_enc_ts **rep) +krb5_error_code +decode_krb5_pa_enc_ts(const krb5_data *code, krb5_pa_enc_ts **repptr) { - setup(); - alloc_field(*rep,krb5_pa_enc_ts); + setup(krb5_pa_enc_ts *); + alloc_field(rep); { begin_structure(); - get_field((*rep)->patimestamp,0,asn1_decode_kerberos_time); + get_field(rep->patimestamp,0,asn1_decode_kerberos_time); if (tagnum == 1) { - get_field((*rep)->pausec,1,asn1_decode_int32); + get_field(rep->pausec,1,asn1_decode_int32); } else - (*rep)->pausec = 0; + rep->pausec = 0; end_structure (); } cleanup(free); } -krb5_error_code decode_krb5_sam_challenge(const krb5_data *code, krb5_sam_challenge **rep) +krb5_error_code +decode_krb5_sam_challenge(const krb5_data *code, krb5_sam_challenge **repptr) { - setup_buf_only(); - alloc_field(*rep,krb5_sam_challenge); + setup_buf_only(krb5_sam_challenge *); + alloc_field(rep); - retval = asn1_decode_sam_challenge(&buf,*rep); + retval = asn1_decode_sam_challenge(&buf,rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_sam_challenge_2(const krb5_data *code, krb5_sam_challenge_2 **rep) +krb5_error_code +decode_krb5_sam_challenge_2(const krb5_data *code, + krb5_sam_challenge_2 **repptr) { - setup_buf_only(); - alloc_field(*rep,krb5_sam_challenge_2); + setup_buf_only(krb5_sam_challenge_2 *); + alloc_field(rep); - retval = asn1_decode_sam_challenge_2(&buf,*rep); + retval = asn1_decode_sam_challenge_2(&buf,rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_sam_challenge_2_body(const krb5_data *code, krb5_sam_challenge_2_body **rep) +krb5_error_code +decode_krb5_sam_challenge_2_body(const krb5_data *code, + krb5_sam_challenge_2_body **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_sam_challenge_2_body); + setup_buf_only(krb5_sam_challenge_2_body *); + alloc_field(rep); - retval = asn1_decode_sam_challenge_2_body(&buf, *rep); + retval = asn1_decode_sam_challenge_2_body(&buf, rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_enc_sam_key(const krb5_data *code, krb5_sam_key **rep) +krb5_error_code +decode_krb5_enc_sam_key(const krb5_data *code, krb5_sam_key **repptr) { - setup_buf_only(); - alloc_field(*rep,krb5_sam_key); + setup_buf_only(krb5_sam_key *); + alloc_field(rep); - retval = asn1_decode_enc_sam_key(&buf,*rep); + retval = asn1_decode_enc_sam_key(&buf,rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_enc_sam_response_enc(const krb5_data *code, krb5_enc_sam_response_enc **rep) +krb5_error_code +decode_krb5_enc_sam_response_enc(const krb5_data *code, + krb5_enc_sam_response_enc **repptr) { - setup_buf_only(); - alloc_field(*rep,krb5_enc_sam_response_enc); + setup_buf_only(krb5_enc_sam_response_enc *); + alloc_field(rep); - retval = asn1_decode_enc_sam_response_enc(&buf,*rep); + retval = asn1_decode_enc_sam_response_enc(&buf,rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_enc_sam_response_enc_2(const krb5_data *code, krb5_enc_sam_response_enc_2 **rep) +krb5_error_code +decode_krb5_enc_sam_response_enc_2(const krb5_data *code, + krb5_enc_sam_response_enc_2 **repptr) { - setup_buf_only(); - alloc_field(*rep,krb5_enc_sam_response_enc_2); + setup_buf_only(krb5_enc_sam_response_enc_2 *); + alloc_field(rep); - retval = asn1_decode_enc_sam_response_enc_2(&buf,*rep); + retval = asn1_decode_enc_sam_response_enc_2(&buf,rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_sam_response(const krb5_data *code, krb5_sam_response **rep) +krb5_error_code +decode_krb5_sam_response(const krb5_data *code, + krb5_sam_response **repptr) { - setup_buf_only(); - alloc_field(*rep,krb5_sam_response); + setup_buf_only(krb5_sam_response *); + alloc_field(rep); - retval = asn1_decode_sam_response(&buf,*rep); + retval = asn1_decode_sam_response(&buf,rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_sam_response_2(const krb5_data *code, krb5_sam_response_2 **rep) +krb5_error_code +decode_krb5_sam_response_2(const krb5_data *code, + krb5_sam_response_2 **repptr) { - setup_buf_only(); - alloc_field(*rep,krb5_sam_response_2); + setup_buf_only(krb5_sam_response_2 *); + alloc_field(rep); - retval = asn1_decode_sam_response_2(&buf,*rep); + retval = asn1_decode_sam_response_2(&buf,rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_predicted_sam_response(const krb5_data *code, krb5_predicted_sam_response **rep) +krb5_error_code +decode_krb5_predicted_sam_response(const krb5_data *code, + krb5_predicted_sam_response **repptr) { - setup_buf_only(); /* preallocated */ - alloc_field(*rep,krb5_predicted_sam_response); + setup_buf_only(krb5_predicted_sam_response *); /* preallocated */ + alloc_field(rep); - retval = asn1_decode_predicted_sam_response(&buf,*rep); + retval = asn1_decode_predicted_sam_response(&buf,rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_setpw_req(const krb5_data *code, - krb5_data **rep, - krb5_principal *principal) +krb5_error_code +decode_krb5_setpw_req(const krb5_data *code, krb5_data **repptr, + krb5_principal *principal) { - setup_buf_only(); - alloc_field(*rep, krb5_data); + setup_buf_only(krb5_data *); + alloc_field(rep); *principal = NULL; - retval = asn1_decode_setpw_req(&buf, *rep, principal); + retval = asn1_decode_setpw_req(&buf, rep, principal); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_pa_for_user(const krb5_data *code, krb5_pa_for_user **rep) +krb5_error_code +decode_krb5_pa_for_user(const krb5_data *code, krb5_pa_for_user **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_pa_for_user); + setup_buf_only(krb5_pa_for_user *); + alloc_field(rep); - retval = asn1_decode_pa_for_user(&buf, *rep); + retval = asn1_decode_pa_for_user(&buf, rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_pa_pac_req(const krb5_data *code, krb5_pa_pac_req **rep) +krb5_error_code +decode_krb5_pa_pac_req(const krb5_data *code, krb5_pa_pac_req **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_pa_pac_req); + setup_buf_only(krb5_pa_pac_req *); + alloc_field(rep); - retval = asn1_decode_pa_pac_req(&buf, *rep); + retval = asn1_decode_pa_pac_req(&buf, rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_etype_list(const krb5_data *code, krb5_etype_list **rep) +krb5_error_code +decode_krb5_etype_list(const krb5_data *code, krb5_etype_list **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_etype_list); + setup_buf_only(krb5_etype_list *); + alloc_field(rep); - retval = asn1_decode_sequence_of_enctype(&buf, &(*rep)->length, &(*rep)->etypes); + retval = asn1_decode_sequence_of_enctype(&buf, &rep->length, &rep->etypes); if (retval) clean_return(retval); cleanup(free); } #ifndef DISABLE_PKINIT -krb5_error_code decode_krb5_pa_pk_as_req(const krb5_data *code, krb5_pa_pk_as_req **rep) +krb5_error_code +decode_krb5_pa_pk_as_req(const krb5_data *code, krb5_pa_pk_as_req **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_pa_pk_as_req); + setup_buf_only(krb5_pa_pk_as_req *); + alloc_field(rep); - retval = asn1_decode_pa_pk_as_req(&buf, *rep); + retval = asn1_decode_pa_pk_as_req(&buf, rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_pa_pk_as_req_draft9(const krb5_data *code, krb5_pa_pk_as_req_draft9 **rep) +krb5_error_code +decode_krb5_pa_pk_as_req_draft9(const krb5_data *code, + krb5_pa_pk_as_req_draft9 **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_pa_pk_as_req_draft9); + setup_buf_only(krb5_pa_pk_as_req_draft9 *); + alloc_field(rep); - retval = asn1_decode_pa_pk_as_req_draft9(&buf, *rep); + retval = asn1_decode_pa_pk_as_req_draft9(&buf, rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_pa_pk_as_rep(const krb5_data *code, krb5_pa_pk_as_rep **rep) +krb5_error_code +decode_krb5_pa_pk_as_rep(const krb5_data *code, krb5_pa_pk_as_rep **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_pa_pk_as_rep); + setup_buf_only(krb5_pa_pk_as_rep *); + alloc_field(rep); - retval = asn1_decode_pa_pk_as_rep(&buf, *rep); + retval = asn1_decode_pa_pk_as_rep(&buf, rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_pa_pk_as_rep_draft9(const krb5_data *code, krb5_pa_pk_as_rep_draft9 **rep) +krb5_error_code +decode_krb5_pa_pk_as_rep_draft9(const krb5_data *code, + krb5_pa_pk_as_rep_draft9 **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_pa_pk_as_rep_draft9); + setup_buf_only(krb5_pa_pk_as_rep_draft9 *); + alloc_field(rep); - retval = asn1_decode_pa_pk_as_rep_draft9(&buf, *rep); + retval = asn1_decode_pa_pk_as_rep_draft9(&buf, rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_auth_pack(const krb5_data *code, krb5_auth_pack **rep) +krb5_error_code +decode_krb5_auth_pack(const krb5_data *code, krb5_auth_pack **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_auth_pack); + setup_buf_only(krb5_auth_pack *); + alloc_field(rep); - retval = asn1_decode_auth_pack(&buf, *rep); + retval = asn1_decode_auth_pack(&buf, rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_auth_pack_draft9(const krb5_data *code, krb5_auth_pack_draft9 **rep) +krb5_error_code +decode_krb5_auth_pack_draft9(const krb5_data *code, + krb5_auth_pack_draft9 **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_auth_pack_draft9); + setup_buf_only(krb5_auth_pack_draft9 *); + alloc_field(rep); - retval = asn1_decode_auth_pack_draft9(&buf, *rep); + retval = asn1_decode_auth_pack_draft9(&buf, rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_kdc_dh_key_info(const krb5_data *code, krb5_kdc_dh_key_info **rep) +krb5_error_code +decode_krb5_kdc_dh_key_info(const krb5_data *code, + krb5_kdc_dh_key_info **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_kdc_dh_key_info); + setup_buf_only(krb5_kdc_dh_key_info *); + alloc_field(rep); - retval = asn1_decode_kdc_dh_key_info(&buf, *rep); + retval = asn1_decode_kdc_dh_key_info(&buf, rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_principal_name(const krb5_data *code, krb5_principal_data **rep) +krb5_error_code +decode_krb5_principal_name(const krb5_data *code, krb5_principal_data **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_principal_data); + setup_buf_only(krb5_principal_data *); + alloc_field(rep); - retval = asn1_decode_krb5_principal_name(&buf, rep); + retval = asn1_decode_krb5_principal_name(&buf, &rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_reply_key_pack(const krb5_data *code, krb5_reply_key_pack **rep) +krb5_error_code +decode_krb5_reply_key_pack(const krb5_data *code, krb5_reply_key_pack **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_reply_key_pack); + setup_buf_only(krb5_reply_key_pack *); + alloc_field(rep); - retval = asn1_decode_reply_key_pack(&buf, *rep); + retval = asn1_decode_reply_key_pack(&buf, rep); if (retval) goto error_out; - cleanup_manual(); -error_out: - if (rep && *rep) { - free((*rep)->replyKey.contents); - free((*rep)->asChecksum.contents); - free(*rep); - *rep = NULL; - } - return retval; + cleanup(free); } -krb5_error_code decode_krb5_reply_key_pack_draft9(const krb5_data *code, krb5_reply_key_pack_draft9 **rep) +krb5_error_code +decode_krb5_reply_key_pack_draft9(const krb5_data *code, + krb5_reply_key_pack_draft9 **repptr) { - setup_buf_only(); - alloc_field(*rep, krb5_reply_key_pack_draft9); + setup_buf_only(krb5_reply_key_pack_draft9 *); + alloc_field(rep); - retval = asn1_decode_reply_key_pack_draft9(&buf, *rep); + retval = asn1_decode_reply_key_pack_draft9(&buf, rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_typed_data(const krb5_data *code, krb5_typed_data ***rep) +krb5_error_code +decode_krb5_typed_data(const krb5_data *code, krb5_typed_data ***repptr) { - setup_buf_only(); - retval = asn1_decode_sequence_of_typed_data(&buf, rep); + setup_buf_only(krb5_typed_data **); + retval = asn1_decode_sequence_of_typed_data(&buf, &rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_td_trusted_certifiers(const krb5_data *code, krb5_external_principal_identifier ***rep) +krb5_error_code +decode_krb5_td_trusted_certifiers(const krb5_data *code, + krb5_external_principal_identifier ***repptr) { - setup_buf_only(); - retval = asn1_decode_sequence_of_external_principal_identifier(&buf, rep); + setup_buf_only(krb5_external_principal_identifier **); + retval = asn1_decode_sequence_of_external_principal_identifier(&buf, &rep); if (retval) clean_return(retval); cleanup(free); } -krb5_error_code decode_krb5_td_dh_parameters(const krb5_data *code, krb5_algorithm_identifier ***rep) +krb5_error_code +decode_krb5_td_dh_parameters(const krb5_data *code, + krb5_algorithm_identifier ***repptr) { - setup_buf_only(); - retval = asn1_decode_sequence_of_algorithm_identifier(&buf, rep); + setup_buf_only(krb5_algorithm_identifier **); + retval = asn1_decode_sequence_of_algorithm_identifier(&buf, &rep); if (retval) clean_return(retval); cleanup(free); diff --git a/src/lib/krb5/asn.1/krb5_encode.c b/src/lib/krb5/asn.1/krb5_encode.c index a6fa305e6..a8ac06a54 100644 --- a/src/lib/krb5/asn.1/krb5_encode.c +++ b/src/lib/krb5/asn.1/krb5_encode.c @@ -44,6 +44,9 @@ asn1_error_code retval;\ unsigned int length, sum = 0;\ asn1buf *buf=NULL;\ + krb5_data *tmpcode;\ +\ + *code = NULL;\ \ if (rep == NULL) return ASN1_MISSING_FIELD;\ \ @@ -52,21 +55,19 @@ /* produce the final output and clean up the workspace */ #define krb5_cleanup()\ - retval = asn12krb5_buf(buf,code);\ - if (retval) {\ - asn1buf_destroy(&buf);\ - return retval; }\ - retval = asn1buf_destroy(&buf);\ - if (retval) {\ - return retval; }\ -\ + retval = asn12krb5_buf(buf,&tmpcode);\ +error:\ + asn1buf_destroy(&buf);\ + if (retval)\ + return retval;\ + *code = tmpcode;\ return 0 krb5_error_code encode_krb5_pa_pk_as_req(const krb5_pa_pk_as_req *rep, krb5_data **code) { krb5_setup(); retval = asn1_encode_pa_pk_as_req(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } @@ -75,7 +76,7 @@ krb5_error_code encode_krb5_pa_pk_as_req_draft9(const krb5_pa_pk_as_req_draft9 * { krb5_setup(); retval = asn1_encode_pa_pk_as_req_draft9(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } @@ -84,7 +85,7 @@ krb5_error_code encode_krb5_pa_pk_as_rep(const krb5_pa_pk_as_rep *rep, krb5_data { krb5_setup(); retval = asn1_encode_pa_pk_as_rep(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } @@ -93,7 +94,7 @@ krb5_error_code encode_krb5_pa_pk_as_rep_draft9(const krb5_pa_pk_as_rep_draft9 * { krb5_setup(); retval = asn1_encode_pa_pk_as_rep_draft9(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } @@ -102,7 +103,7 @@ krb5_error_code encode_krb5_auth_pack(const krb5_auth_pack *rep, krb5_data **cod { krb5_setup(); retval = asn1_encode_auth_pack(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } @@ -111,7 +112,7 @@ krb5_error_code encode_krb5_auth_pack_draft9(const krb5_auth_pack_draft9 *rep, k { krb5_setup(); retval = asn1_encode_auth_pack_draft9(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } @@ -120,7 +121,7 @@ krb5_error_code encode_krb5_kdc_dh_key_info(const krb5_kdc_dh_key_info *rep, krb { krb5_setup(); retval = asn1_encode_kdc_dh_key_info(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } @@ -129,7 +130,7 @@ krb5_error_code encode_krb5_reply_key_pack(const krb5_reply_key_pack *rep, krb5_ { krb5_setup(); retval = asn1_encode_reply_key_pack(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } @@ -138,7 +139,7 @@ krb5_error_code encode_krb5_reply_key_pack_draft9(const krb5_reply_key_pack_draf { krb5_setup(); retval = asn1_encode_reply_key_pack_draft9(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } @@ -147,7 +148,7 @@ krb5_error_code encode_krb5_td_trusted_certifiers(const krb5_external_principal_ { krb5_setup(); retval = asn1_encode_td_trusted_certifiers(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } @@ -156,7 +157,7 @@ krb5_error_code encode_krb5_typed_data(const krb5_typed_data **rep, krb5_data ** { krb5_setup(); retval = asn1_encode_sequence_of_typed_data(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } @@ -165,7 +166,7 @@ krb5_error_code encode_krb5_td_dh_parameters(const krb5_algorithm_identifier **r { krb5_setup(); retval = asn1_encode_sequence_of_algorithm_identifier(buf,rep,&length); - if (retval) return retval; + if (retval) goto error; sum += length; krb5_cleanup(); } diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c index c7c1c602c..e0e71746d 100644 --- a/src/lib/krb5/krb/kfree.c +++ b/src/lib/krb5/krb/kfree.c @@ -79,6 +79,15 @@ krb5_free_addresses(krb5_context context, krb5_address **val) } +void KRB5_CALLCONV +krb5_free_alt_method(krb5_context context, + krb5_alt_method *alt) +{ + if (alt) { + free(alt->data); + free(alt); + } +} void KRB5_CALLCONV krb5_free_ap_rep(krb5_context context, register krb5_ap_rep *val) { @@ -254,6 +263,15 @@ krb5_free_data_contents(krb5_context context, krb5_data *val) } } +void KRB5_CALLCONV +krb5_free_enc_data(krb5_context context, krb5_enc_data *val) +{ + if (val == NULL) + return; + krb5_free_data_contents(context, &val->ciphertext); + free(val); +} + void krb5_free_etype_info(krb5_context context, krb5_etype_info info) { int i; @@ -425,6 +443,22 @@ krb5_free_pwd_data(krb5_context context, krb5_pwd_data *val) } +void KRB5_CALLCONV +krb5_free_passwd_phrase_element(krb5_context context, + passwd_phrase_element *val) +{ + register passwd_phrase_element **temp; + + if (val == NULL) + return; + krb5_free_data(context, val->passwd); + val->passwd = NULL; + krb5_free_data(context, val->phrase); + val->phrase = NULL; + free(val); +} + + void KRB5_CALLCONV krb5_free_pwd_sequences(krb5_context context, passwd_phrase_element **val) { @@ -432,13 +466,8 @@ krb5_free_pwd_sequences(krb5_context context, passwd_phrase_element **val) if (val == NULL) return; - for (temp = val; *temp; temp++) { - krb5_free_data(context, (*temp)->passwd); - (*temp)->passwd = 0; - krb5_free_data(context, (*temp)->phrase); - (*temp)->phrase = 0; - free(*temp); - } + for (temp = val; *temp; temp++) + krb5_free_passwd_phrase_element(context, *temp); free(val); } diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index f04e8b5e6..7112411a9 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -13,10 +13,12 @@ decode_krb5_enc_data decode_krb5_enc_kdc_rep_part decode_krb5_enc_priv_part decode_krb5_enc_sam_response_enc +decode_krb5_enc_sam_response_enc_2 decode_krb5_enc_tkt_part decode_krb5_encryption_key decode_krb5_error decode_krb5_etype_info +decode_krb5_etype_info2 decode_krb5_kdc_req_body decode_krb5_pa_enc_ts decode_krb5_pa_for_user @@ -29,6 +31,7 @@ decode_krb5_pwd_sequence decode_krb5_safe decode_krb5_sam_challenge decode_krb5_sam_response +decode_krb5_sam_response_2 decode_krb5_setpw_req decode_krb5_tgs_rep decode_krb5_tgs_req @@ -47,6 +50,7 @@ encode_krb5_enc_data encode_krb5_enc_kdc_rep_part encode_krb5_enc_priv_part encode_krb5_enc_sam_response_enc +encode_krb5_enc_sam_response_enc_2 encode_krb5_enc_tkt_part encode_krb5_encryption_key encode_krb5_error @@ -66,6 +70,7 @@ encode_krb5_safe encode_krb5_sam_challenge encode_krb5_sam_key encode_krb5_sam_response +encode_krb5_sam_response_2 encode_krb5_tgs_rep encode_krb5_tgs_req encode_krb5_ticket @@ -192,6 +197,7 @@ krb5_fcc_ops krb5_find_serializer krb5_free_address krb5_free_addresses +krb5_free_alt_method krb5_free_ap_rep krb5_free_ap_rep_enc_part krb5_free_ap_req @@ -209,6 +215,7 @@ krb5_free_creds krb5_free_data krb5_free_data_contents krb5_free_default_realm +krb5_free_enc_data krb5_free_enc_kdc_rep_part krb5_free_enc_sam_response_enc krb5_free_enc_sam_response_enc_2 @@ -233,6 +240,7 @@ krb5_free_pa_pac_req krb5_free_pa_for_user krb5_free_pa_server_referral_data krb5_free_pa_svr_referral_data +krb5_free_passwd_phrase_element krb5_free_predicted_sam_response krb5_free_predicted_sam_response_contents krb5_free_principal -- 2.26.2