/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
*/
/*
*
* Copyright 1994, 2007, 2008 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original M.I.T. software.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*/
#include "asn1_k_decode.h"
#include "asn1_decode.h"
#include "asn1_get.h"
#include "asn1_misc.h"
/* Declare useful decoder variables. */
#define setup() \
#define unused_var(x) if (0) { x = 0; x = x - x; }
/* This is used for prefetch of next tag in sequence. */
#define next_tag() \
/* Copy out to match previous functionality, until better integrated. */ \
}
static asn1_error_code
{
taginfo t;
if (retval)
return retval;
return ASN1_MISSING_EOC;
return 0;
}
/* Force check for EOC tag. */
#define get_eoc() \
{ \
}
/*
* Allocate a principal and initialize enough fields for
* krb5_free_principal to have defined behavior.
*/
alloc_field(var); \
/*
* Allocate a data structure and initialize enough fields for
* krb5_free_data to have defined behavior.
*/
alloc_field(var); \
/* Fetch an expected APPLICATION class tag and verify. */
{ \
/* Copy out to match previous functionality, until better integrated. */ \
}
/**** normal fields ****/
/*
* get_field_body
*
* Get bare field. This also prefetches the next tag. The call to
* get_eoc() assumes that any values fetched by this macro are
* enclosed in a context-specific tag.
*/
next_tag()
/*
* error_if_bad_tag
*
* Checks that the next tag is the expected one; returns with an error
* if not.
*/
if (tagnum != (tagexpect)) { clean_return((tagnum < (tagexpect)) ? ASN1_MISPLACED_FIELD : ASN1_MISSING_FIELD); }
/*
* get_field
*
* Get field having an expected context specific tag. This assumes
* that context-specific tags are monotonically increasing in its
* verification of tag numbers.
*/
/*
* opt_field
*
* Get an optional field with an expected context specific tag.
* Assumes that OPTVAL will have the default value, thus failing to
* distinguish between absent optional values and present optional
* values that happen to have the value of OPTVAL.
*/
}
/**** fields w/ length ****/
/* similar to get_field_body */
next_tag()
/* similar to get_field_body */
/* similar to opt_field */
/*
* Deal with implicitly tagged fields
*/
next_tag()
next_tag(); \
/*
* begin_structure
*
* Declares some variables for decoding SEQUENCE types. This is meant
* to be called in an inner block that ends with a call to
* end_structure().
*/
#define begin_structure() \
int seqindef; \
int indef; \
next_tag()
/*
* This is used for structures which have no tagging.
* It is the same as begin_structure() except next_tag()
* is not called.
*/
#define begin_structure_no_tag() \
int seqindef; \
int indef; \
/* skip trailing garbage */
#define end_structure() \
/*
* begin_choice
*
* Declares some variables for decoding CHOICE types. This is meant
* to be called in an inner block that ends with a call to
* end_choice().
*/
#define begin_choice() \
int seqindef; \
int indef; \
taginfo t; \
construction = t.construction; \
/* skip trailing garbage */
#define end_choice() \
/*
* sequence_of
*
* Declares some variables for decoding SEQUENCE OF types. This is
* meant to be called in an inner block that ends with a call to
* end_sequence_of().
*/
int indef; \
/*
* sequence_of_no_tagvars
*
* This is meant for use inside decoder functions that have an outer
* sequence structure and thus declares variables of different names
* than does sequence_of() to avoid shadowing.
*/
/*
* sequence_of_common
*
* Fetches the outer SEQUENCE OF length info into {length,seqofindef}
* and imbeds an inner buffer seqbuf. Unlike begin_structure(), it
* does not prefetch the next tag.
*/
int seqofindef; \
/*
* end_sequence_of
*
* Attempts to fetch an EOC tag, if any, and to sync over trailing
* garbage, if any.
*/
{ \
/* Copy out to match previous functionality, until better integrated. */ \
} \
/*
* end_sequence_of_no_tagvars
*
* Like end_sequence_of(), but uses the different (non-shadowing)
* variable names.
*/
static asn1_error_code
int seqofindef)
{
taginfo t;
if (retval)
return retval;
return retval;
}
/*
* 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.
*/
\
if (!val) \
return ENOMEM; \
if (retval) { \
return retval; \
} \
return 0;
/* scalars */
{
time_t t;
if (retval)
return retval;
*val = t;
return 0;
}
{ \
long n; \
return 0; \
}
{ \
unsigned long n; \
return 0; \
}
{
unsigned long n;
return 0;
}
{
unsigned long n;
*val = (krb5_msgtype) n;
return 0;
}
/* structures */
{
return asn1_decode_generalstring(buf,
}
{
int size = 0, i;
setup();
{ begin_structure();
unsigned int len;
char *str;
size++;
}
}
if (indef) {
get_eoc();
}
next_tag();
}
return 0;
for (i = 0; i < size; i++)
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
taginfo t;
unsigned int i;
krb5_flags f=0;
unsigned int length;
t.tagnum != ASN1_BITSTRING)
return ASN1_BAD_ID;
/* Number of unused bits must be between 0 and 7. */
length--;
for (i = 0; i < length; i++) {
/* ignore bits past number 31 */
if (i < 4)
}
if (length <= 4) {
/* Mask out unused bits, but only if necessary. */
f &= ~(krb5_flags)0 << unused;
}
/* left-justify */
if (length < 4)
*val = f;
return 0;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
/* Set to authtime if missing */
}
return 0;
return retval;
}
{
setup();
unsigned int applen;
apptag(1);
{ begin_structure();
}
if (!applen) {
taginfo t;
}
return 0;
return retval;
}
{
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{
/* If opt_field server is missing, memory reference to server is
lost and results in memory leak */
}
}
if (tagnum == 10) {
else {
}
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
if (tagnum == 5) {
}
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
/* arrays */
static void *
{
if (n_elts <= 0)
return NULL;
return NULL;
if (new_size == 0)
return NULL;
return NULL;
}
{ \
}
/*
* Function body for array decoders. freefn is expected to look like
* a krb5_free_ function, so we pass a null first argument.
*/
int size = 0, i; \
\
{ sequence_of(buf); \
} \
/* Solaris Kerberos */ \
goto error_out; \
} \
end_sequence_of(buf); \
} \
return 0; \
error_out: \
if (elt) \
if (array) /* Solaris Kerberos */ \
for (i = 0; i < size; i++) \
return retval
static void
{
}
{
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
static asn1_error_code
{
setup();
*val = 0;
{ begin_structure();
}
return 0;
return retval;
}
{
int size = 0;
{ sequence_of(buf);
size++;
}
}
return 0;
return retval;
}
{
}
{
}
{
}
static void
{
}
{
}
{
setup();
{ begin_structure();
if (tagnum == 1) {
if (tagnum == 8) {
}
return 0;
return retval;
}
{
}
static void
{
}
{
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
}
static void
{
}
{
}
{
setup();
{ begin_structure();
#ifdef KRB5_GENEROUS_LR_TYPE
/* If we are only a single byte wide and negative - fill in the
other bits */
#endif
}
return 0;
return retval;
}
{
}
{
int size = 0;
{ sequence_of(buf);
size++;
}
}
return 0;
return retval;
}
{
}
static void
{
}
static asn1_error_code
{
setup();
{ begin_structure();
if (tagnum == 1) {
} else
if ( tagnum ==2) {
} else
}
return 0;
return retval;
}
static asn1_error_code
{
}
static asn1_error_code
{
setup();
{ begin_structure();
if (tagnum == 1) {
} else
if ( tagnum ==2) {
} else
}
return 0;
return retval;
}
static asn1_error_code
{
}
static asn1_error_code
{
setup();
{ begin_structure();
if (tagnum == 1) {
} else
}
return 0;
return retval;
}
static asn1_error_code
{
}
{
}
static asn1_error_code
{
}
{
if (v1_3_behavior)
else {
}
}
{
setup();
{ begin_structure();
}
return 0;
return 0;
}
{
}
{
}
{
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
}
next_tag();
}
return 0;
}
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
else { \
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
if (tagnum == 1) {
}
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{begin_structure();
}
return 0;
return retval;
}
{
}
{
setup();
{begin_structure();
}
return 0;
return retval;
}
{
}
{
setup();
{begin_structure();
if (tagnum == 1) {
}
}
return 0;
return retval;
}
{
setup();
alloc_principal((*valptr));
{ begin_structure();
}
return 0;
return retval;
}
static asn1_error_code
{
}
{
setup();
{
NULL);
}
return 0;
return retval;
}
#ifndef DISABLE_PKINIT
/* PKINIT */
{
setup();
{
}
return 0;
return retval;
}
{
}
static void
{
}
{
}
{
setup();
{
}
return 0;
return retval;
}
#if 0 /* XXX This needs to be tested!!! XXX */
{
setup();
{
if (t.tagnum == choice_trusted_cas_principalName) {
} else if (t.tagnum == choice_trusted_cas_caName) {
{
}
next_tag();
} else if (t.tagnum == choice_trusted_cas_issuerAndSerial) {
{
}
next_tag();
} else clean_return(ASN1_BAD_ID);
}
return 0;
return retval;
}
#else
{
setup();
{ begin_choice();
if (tagnum == choice_trusted_cas_principalName) {
} else if (tagnum == choice_trusted_cas_caName) {
} else if (tagnum == choice_trusted_cas_issuerAndSerial) {
} else clean_return(ASN1_BAD_ID);
end_choice();
}
return 0;
return retval;
}
#endif
{
}
static void
{
}
{
}
{
int i;
setup();
{ begin_structure();
}
return 0;
if (val->trustedCertifiers) {
for (i = 0; val->trustedCertifiers[i]; i++)
}
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
/*
* Forbid indefinite encoding because we don't read enough tag
* information from the trailing octets ("ANY DEFINED BY") to
* synchronize EOC tags, etc.
*/
/*
* Set up tag variables because we don't actually call anything
* that fetches tag info for us; it's all buried in the decoder
* primitives.
*/
taglen = 0;
indef = 0;
}
}
return 0;
return retval;
}
{
}
{
setup();
/* SubjectPublicKey encoded as a BIT STRING */
next_tag();
tagnum != ASN1_BITSTRING)
/* Number of unused bits must be between 0 and 7. */
/* What to do if unused is not zero? */
taglen--;
/*
* We didn't call any macro that does next_tag(); do so now to
* preload tag of any trailing encodings.
*/
next_tag();
}
return 0;
return 0;
}
static void
{
}
{
}
{
setup();
{ begin_structure();
next_tag();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
int i;
setup();
{ begin_structure();
}
return 0;
}
return retval;
}
{
int i;
setup();
{ begin_structure();
if (tagnum == 1) {
}
/* can't call opt_field because it does decoder(&subbuf, &(val)); */
if (tagnum == 1) {
next_tag();
}
/* can't call opt_field because it does decoder(&subbuf, &(val)); */
if (tagnum == 2) {
next_tag();
}
}
return 0;
if (val->clientPublicValue) {
}
if (val->supportedCMSTypes) {
for (i = 0; val->supportedCMSTypes[i]; i++)
}
return retval;
}
{
setup();
{ begin_structure();
if (tagnum == 1) {
/* can't call opt_field because it does decoder(&subbuf, &(val)); */
if (tagnum == 1) {
next_tag();
}
}
}
return 0;
if (val->clientPublicValue) {
}
return retval;
}
{
setup();
{ begin_choice();
if (tagnum == choice_pa_pk_as_rep_dhInfo) {
} else if (tagnum == choice_pa_pk_as_rep_encKeyPack) {
} else {
}
end_choice();
}
return 0;
}
return retval;
}
{
setup();
{ begin_structure();
} else if (tagnum == choice_pa_pk_as_rep_draft9_encKeyPack) {
} else {
}
}
return 0;
return retval;
}
#endif /* DISABLE_PKINIT */
{
}
{
}
{
setup();
{ begin_structure();
}
return 0;
return retval;
}
{
}