#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; \
#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; \
#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; \
*/
#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()
* 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
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)
/*
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; \
/* 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()
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 */
* 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; }
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()
/*
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
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; \
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
* 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
{ \
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; \
} \
retval = asn1buf_sync(buf, &seqbuf, asn1class, tagnum, \
length, indef, seqofindef); \
- if (retval) return retval;
+ if (retval) clean_return(retval);
/*
* end_sequence_of_no_tagvars
#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)
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) {
}
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);
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)
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);
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);
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)
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);
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 */
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)
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);
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)
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)
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);
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);
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);
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) \
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);
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);
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)
get_field(val->include_pac,0,asn1_decode_boolean);
end_structure();
}
- cleanup();
+ return 0;
+error_out:
+ return retval;
}
#ifndef DISABLE_PKINIT
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);
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);
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;
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);
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);
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);
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);
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);
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
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;
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
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;
/* 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;
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;
}
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 {
}
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 {
}
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 */
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) \
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);
+ alloc_principal(rep->client);
get_field(rep->client,1,asn1_decode_realm);
get_field(rep->client,2,asn1_decode_principal_name);
- if (tagnum == 3) {
- alloc_field(rep->checksum);
- get_field(*(rep->checksum),3,asn1_decode_checksum); }
+ 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);
- if (tagnum == 6) { alloc_field(rep->subkey); }
- opt_field(*(rep->subkey),6,asn1_decode_encryption_key);
+ 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;
}
cleanup_manual();
error_out:
- if (rep) {
- free_field(rep,subkey);
- free_field(rep,checksum);
- free_field(rep,client);
- free(rep);
- }
+ krb5_free_authenticator(NULL, rep);
return retval;
}
#endif
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();
get_field(kvno,0,asn1_decode_kvno);
if (kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO);
}
- alloc_field(rep->server);
+ 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);
}
cleanup_manual();
error_out:
- if (rep) {
- free_field(rep,server);
- free(rep);
- }
+ krb5_free_ticket(NULL, rep);
return retval;
}
{
setup(krb5_keyblock *);
alloc_field(rep);
+ clear_field(rep,contents);
{ begin_structure();
get_field(rep->enctype,0,asn1_decode_enctype);
end_structure();
rep->magic = KV5M_KEYBLOCK;
}
- cleanup(free);
+ cleanup_manual();
+error_out:
+ krb5_free_keyblock(NULL, rep);
+ return retval;
}
krb5_error_code
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);
- get_field(*(rep->session),1,asn1_decode_encryption_key);
- alloc_field(rep->client);
+ 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);
}
cleanup_manual();
error_out:
- if (rep) {
- free_field(rep,session);
- free_field(rep,client);
- free(rep);
- }
+ krb5_free_enc_tkt_part(NULL, rep);
return retval;
}
{
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);
clean_return(KRB5_BADMSGTYPE);
#endif
- cleanup(free);
+ cleanup_manual();
+error_out:
+ krb5_free_kdc_rep(NULL, rep);
+ return retval;
}
krb5_error_code
{
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);
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
setup(krb5_ap_req *);
alloc_field(rep);
clear_field(rep,ticket);
+ clear_field(rep,authenticator.ciphertext.data);
check_apptag(14);
{ begin_structure();
#endif
}
get_field(rep->ap_options,2,asn1_decode_ap_options);
- alloc_field(rep->ticket);
- get_field(*(rep->ticket),3,asn1_decode_ticket);
+ 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;
}
cleanup_manual();
error_out:
- if (rep) {
- free_field(rep,ticket);
- free(rep);
- }
+ krb5_free_ap_req(NULL, rep);
return retval;
}
{
setup(krb5_ap_rep *);
alloc_field(rep);
+ clear_field(rep,enc_part.ciphertext.data);
check_apptag(15);
{ begin_structure();
end_structure();
rep->magic = KV5M_AP_REP;
}
- cleanup(free);
+ cleanup_manual();
+error_out:
+ krb5_free_ap_rep(NULL, rep);
+ return retval;
}
krb5_error_code
{ 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); }
- opt_field(*(rep->subkey),2,asn1_decode_encryption_key);
+ 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;
}
cleanup_manual();
error_out:
- if (rep) {
- free_field(rep,subkey);
- free(rep);
- }
+ krb5_free_ap_rep_enc_part(NULL, rep);
return retval;
}
{
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);
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
{
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);
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
krb5_data tmpbody;
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;
tmpbody.data = NULL;
}
get_field(*rep,2,asn1_decode_krb_safe_body);
- alloc_field(rep->checksum);
- get_field(*(rep->checksum),3,asn1_decode_checksum);
+ get_field(rep->checksum,3,asn1_decode_checksum_ptr);
rep->magic = KV5M_SAFE;
end_structure();
}
*body = tmpbody;
cleanup_manual();
error_out:
- if (rep) {
- free_field(rep,checksum);
- free(rep);
- }
+ krb5_free_safe(NULL, rep);
return retval;
}
{
setup(krb5_priv *);
alloc_field(rep);
+ clear_field(rep,enc_part.ciphertext.data);
check_apptag(21);
{ begin_structure();
rep->magic = KV5M_PRIV;
end_structure();
}
- cleanup(free);
+ cleanup_manual();
+error_out:
+ krb5_free_priv(NULL, rep);
+ return retval;
}
krb5_error_code
{
setup(krb5_priv_enc_part *);
alloc_field(rep);
+ clear_field(rep,user_data.data);
clear_field(rep,r_address);
clear_field(rep,s_address);
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);
- get_field(*(rep->s_address),4,asn1_decode_host_address);
- if (tagnum == 5) { alloc_field(rep->r_address); }
- opt_field(*(rep->r_address),5,asn1_decode_host_address);
+ 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) {
- free_field(rep,r_address);
- free_field(rep,s_address);
- free(rep);
- }
+ krb5_free_priv_enc_part(NULL, rep);
return retval;
}
{
setup(krb5_cred *);
alloc_field(rep);
+ clear_field(rep,tickets);
+ clear_field(rep,enc_part.ciphertext.data);
check_apptag(22);
{ begin_structure();
rep->magic = KV5M_CRED;
end_structure();
}
- cleanup(free);
+ cleanup_manual();
+error_out:
+ krb5_free_cred(NULL, rep);
+ return retval;
}
krb5_error_code
alloc_field(rep);
clear_field(rep,r_address);
clear_field(rep,s_address);
+ clear_field(rep,ticket_info);
check_apptag(29);
{ begin_structure();
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); }
- opt_field(*(rep->s_address),4,asn1_decode_host_address);
- if (tagnum == 5) { alloc_field(rep->r_address); }
- opt_field(*(rep->r_address),5,asn1_decode_host_address);
+ 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) {
- free_field(rep,r_address);
- free_field(rep,s_address);
- free(rep);
- }
+ /* Despite the name, krb5_free_cred_enc_part is contents only. */
+ krb5_free_cred_enc_part(NULL, rep);
+ free(rep);
return retval;
}
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();
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); }
+ 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_field(rep->server);
+ 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);
}
cleanup_manual();
error_out:
- if (rep) {
- free_field(rep,server);
- free_field(rep,client);
- free(rep);
- }
+ krb5_free_error(NULL, rep);
return retval;
}
{
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;
end_structure (); }
- cleanup(free);
+ cleanup_manual();
+error_out:
+ krb5_free_pwd_data(NULL, rep);
+ return retval;
}
krb5_error_code
{
setup(krb5_alt_method *);
alloc_field(rep);
+ clear_field(rep,data);
{ begin_structure();
get_field(rep->method,0,asn1_decode_int32);
if (tagnum == 1) {
rep->magic = KV5M_ALT_METHOD;
end_structure();
}
- cleanup(free);
+ cleanup_manual();
+error_out:
+ krb5_free_alt_method(NULL, rep);
+ return retval;
}
krb5_error_code
if (retval)
goto error_out;
- cleanup_manual();
-error_out:
- if (rep) {
- free(rep->replyKey.contents);
- free(rep->asChecksum.contents);
- free(rep);
- }
- return retval;
+ cleanup(free);
}
krb5_error_code