+2003-03-11 Ken Raeburn <raeburn@mit.edu>
+
+ * asn1_get.c (asn1_get_tag): Deleted.
+ (asn1_get_tag_2): Renamed from asn1_get_tag_indef, now uses a
+ pointer to taginfo rather than a bunch of pointer args.
+ (asn1_get_id, asn1_get_length): Folded into asn1_get_tag_2.
+ (asn1_get_sequence): Call asn1_get_tag_2.
+ * asn1_get.h (taginfo): New structure.
+ (asn1_get_tag_indef, asn1_get_tag, asn1_get_id, asn1_get_length):
+ Declarations deleted.
+ (asn1_get_tag_2): Declare.
+ * asn1_decode.c (setup): Declare only a taginfo variable.
+ (asn1class, construction, tagnum, length): New macros.
+ (tag): Call asn1_get_tag_2.
+ * asn1_k_decode.c (next_tag, get_eoc, apptag, end_sequence_of,
+ end_sequence_of_no_tagvars, asn1_decode_krb5_flags): Call
+ asn1_get_tag_2; if no error, copy out values into scalar
+ variables.
+ (asn1_decode_ticket): Call asn1_get_tag_2.
+ * asn1buf.c (asn1buf_skiptail): Call asn1_get_tag_2.
+ * krb5_decode.c (check_apptag, next_tag, get_eoc): Call
+ asn1_get_tag_2; if no error, copy out values into scalar
+ variables.
+ (decode_krb5_enc_kdc_rep_part): Call asn1_get_tag_2.
+
2003-01-10 Ken Raeburn <raeburn@mit.edu>
* Makefile.in: Add AC_SUBST_FILE marker for libobj_frag.
#define setup()\
asn1_error_code retval;\
-asn1_class asn1class;\
-asn1_construction construction;\
-asn1_tagnum tagnum;\
-unsigned int length
+taginfo tinfo
+
+#define asn1class (tinfo.asn1class)
+#define construction (tinfo.construction)
+#define tagnum (tinfo.tagnum)
+#define length (tinfo.length)
#define tag(type)\
-retval = asn1_get_tag(buf,&asn1class,&construction,&tagnum,&length);\
+retval = asn1_get_tag_2(buf,&tinfo);\
if(retval) return retval;\
if(asn1class != UNIVERSAL || construction != PRIMITIVE || tagnum != type)\
return ASN1_BAD_ID
#include "asn1_get.h"
asn1_error_code
-asn1_get_tag_indef(asn1buf *buf, asn1_class *asn1class,
- asn1_construction *construction, asn1_tagnum *tagnum,
- unsigned int *retlen, int *indef)
+asn1_get_tag_2(asn1buf *buf, taginfo *t)
{
- asn1_error_code retval;
-
- if (buf == NULL || buf->base == NULL ||
- buf->bound - buf->next + 1 <= 0) {
- *tagnum = ASN1_TAGNUM_CEILING; /* emphatically not an EOC tag */
- if (asn1class != NULL)
- *asn1class = UNIVERSAL;
- if (construction != NULL)
- *construction = PRIMITIVE;
- if (retlen != NULL)
- *retlen = 0;
- if (indef != NULL)
- *indef = 0;
- return 0;
- }
- retval = asn1_get_id(buf,asn1class,construction,tagnum);
- if(retval) return retval;
- retval = asn1_get_length(buf,retlen,indef);
- if(retval) return retval;
- if (indef != NULL && *indef &&
- construction != NULL && *construction != CONSTRUCTED)
- return ASN1_MISMATCH_INDEF;
- return 0;
-}
-
-asn1_error_code
-asn1_get_tag(asn1buf *buf, asn1_class *asn1class,
- asn1_construction *construction, asn1_tagnum *tagnum,
- unsigned int *retlen)
-{
- int indef;
-
- return asn1_get_tag_indef(buf, asn1class, construction, tagnum, retlen,
- &indef);
-}
-
-asn1_error_code asn1_get_sequence(asn1buf *buf, unsigned int *retlen, int *indef)
-{
- asn1_error_code retval;
- asn1_class asn1class;
- asn1_construction construction;
- asn1_tagnum tagnum;
-
- retval = asn1_get_tag_indef(buf,&asn1class,&construction,&tagnum,retlen,indef);
- if(retval) return retval;
- if(retval) return (krb5_error_code)retval;
- if(asn1class != UNIVERSAL || construction != CONSTRUCTED ||
- tagnum != ASN1_SEQUENCE) return ASN1_BAD_ID;
- return 0;
-}
-
-/****************************************************************/
-/* Private Procedures */
+ asn1_error_code retval;
-asn1_error_code asn1_get_id(asn1buf *buf, asn1_class *asn1class,
- asn1_construction *construction,
- asn1_tagnum *tagnum)
-{
- asn1_error_code retval;
- asn1_tagnum tn=0;
- asn1_octet o;
+ if (buf == NULL || buf->base == NULL ||
+ buf->bound - buf->next + 1 <= 0) {
+ t->tagnum = ASN1_TAGNUM_CEILING; /* emphatically not an EOC tag */
+ t->asn1class = UNIVERSAL;
+ t->construction = PRIMITIVE;
+ t->length = 0;
+ t->indef = 0;
+ return 0;
+ }
+ {
+ /* asn1_get_id(buf, t) */
+ asn1_tagnum tn=0;
+ asn1_octet o;
#define ASN1_CLASS_MASK 0xC0
#define ASN1_CONSTRUCTION_MASK 0x20
#define ASN1_TAG_NUMBER_MASK 0x1F
- retval = asn1buf_remove_octet(buf,&o);
- if(retval) return retval;
+ retval = asn1buf_remove_octet(buf,&o);
+ if (retval)
+ return retval;
- if(asn1class != NULL)
- *asn1class = (asn1_class)(o&ASN1_CLASS_MASK);
- if(construction != NULL)
- *construction = (asn1_construction)(o&ASN1_CONSTRUCTION_MASK);
- if((o&ASN1_TAG_NUMBER_MASK) != ASN1_TAG_NUMBER_MASK){
- /* low-tag-number form */
- if(tagnum != NULL) *tagnum = (asn1_tagnum)(o&ASN1_TAG_NUMBER_MASK);
- }else{
- /* high-tag-number form */
- do{
- retval = asn1buf_remove_octet(buf,&o);
- if(retval) return retval;
- tn = (tn<<7) + (asn1_tagnum)(o&0x7F);
- }while(tn&0x80);
- if(tagnum != NULL) *tagnum = tn;
- }
- return 0;
-}
+ t->asn1class = (asn1_class)(o&ASN1_CLASS_MASK);
+ t->construction = (asn1_construction)(o&ASN1_CONSTRUCTION_MASK);
+ if ((o&ASN1_TAG_NUMBER_MASK) != ASN1_TAG_NUMBER_MASK){
+ /* low-tag-number form */
+ t->tagnum = (asn1_tagnum)(o&ASN1_TAG_NUMBER_MASK);
+ } else {
+ /* high-tag-number form */
+ do {
+ retval = asn1buf_remove_octet(buf,&o);
+ if (retval) return retval;
+ tn = (tn<<7) + (asn1_tagnum)(o&0x7F);
+ }while(tn&0x80);
+ t->tagnum = tn;
+ }
+ }
-asn1_error_code asn1_get_length(asn1buf *buf, unsigned int *retlen, int *indef)
-{
- asn1_error_code retval;
- asn1_octet o;
+ {
+ /* asn1_get_length(buf, t) */
+ asn1_octet o;
- if (indef != NULL)
- *indef = 0;
- retval = asn1buf_remove_octet(buf,&o);
- if(retval) return retval;
- if((o&0x80) == 0){
- if(retlen != NULL) *retlen = (int)(o&0x7F);
- }else{
- int num;
- int len=0;
+ t->indef = 0;
+ retval = asn1buf_remove_octet(buf,&o);
+ if (retval) return retval;
+ if ((o&0x80) == 0) {
+ t->length = (int)(o&0x7F);
+ } else {
+ int num;
+ int len=0;
- for(num = (int)(o&0x7F); num>0; num--){
- retval = asn1buf_remove_octet(buf,&o);
- if(retval) return retval;
- len = (len<<8) + (int)o;
+ for (num = (int)(o&0x7F); num>0; num--) {
+ retval = asn1buf_remove_octet(buf,&o);
+ if(retval) return retval;
+ len = (len<<8) + (int)o;
+ }
+ if (len < 0)
+ return ASN1_OVERRUN;
+ if (!len)
+ t->indef = 1;
+ t->length = len;
+ }
}
- if (len < 0)
- return ASN1_OVERRUN;
- if (indef != NULL && !len)
- *indef = 1;
- if(retlen != NULL) *retlen = len;
- }
- return 0;
+ if (t->indef && t->construction != CONSTRUCTED)
+ return ASN1_MISMATCH_INDEF;
+ return 0;
+}
+
+asn1_error_code asn1_get_sequence(asn1buf *buf, unsigned int *retlen, int *indef)
+{
+ taginfo t;
+ asn1_error_code retval;
+
+ retval = asn1_get_tag_2(buf, &t);
+ if (retval)
+ return retval;
+ if (t.asn1class != UNIVERSAL || t.construction != CONSTRUCTED ||
+ t.tagnum != ASN1_SEQUENCE)
+ return ASN1_BAD_ID;
+ if (retlen)
+ *retlen = t.length;
+ if (indef)
+ *indef = t.indef;
+ return 0;
}
#include "krbasn1.h"
#include "asn1buf.h"
+typedef struct {
+ asn1_class asn1class;
+ asn1_construction construction;
+ asn1_tagnum tagnum;
+ unsigned int length;
+ int indef;
+} taginfo;
+
+asn1_error_code asn1_get_tag_2 (asn1buf *buf, taginfo *tinfo);
+
+#if 0
asn1_error_code asn1_get_tag_indef
(asn1buf *buf,
asn1_class *Class,
asn1_construction *construction,
asn1_tagnum *tagnum,
unsigned int *retlen, int *indef);
+
asn1_error_code asn1_get_tag
(asn1buf *buf,
asn1_class *Class,
If *buf is empty to begin with,
*tagnum is set to ASN1_TAGNUM_CEILING.
Returns ASN1_OVERRUN if *buf is exhausted during the parse. */
+#endif
asn1_error_code asn1_get_sequence
(asn1buf *buf, unsigned int *retlen, int *indef);
doesn't have a sequence ID. If retlen != NULL, the
associated length is returned in *retlen. */
-/****************************************************************/
-/* Private Procedures */
-
-asn1_error_code asn1_get_id
- (asn1buf *buf,
- asn1_class *Class,
- asn1_construction *construction,
- asn1_tagnum *tagnum);
-/* requires *buf is allocated
- effects Decodes the group of identifier octets at *buf's
- current position. If class != NULL, returns the class
- in *Class. Similarly, the construction and tag number
- are returned in *construction and *tagnum, respectively.
- Returns ASN1_OVERRUN if *buf is exhausted. */
-
-asn1_error_code asn1_get_length
- (asn1buf *buf, unsigned int *retlen, int *indef);
-/* requires *buf is allocated
- effects Decodes the group of length octets at *buf's
- current position. If retlen != NULL, the
- length is returned in *retlen.
- Returns ASN1_OVERRUN if *buf is exhausted. */
-
#endif
#define unused_var(x) if (0) { x = 0; x = x - x; }
/* This is used for prefetch of next tag in sequence. */
-#define next_tag() \
- retval = asn1_get_tag_indef(&subbuf, &asn1class, &construction, \
- &tagnum, &taglen, &indef); \
- if (retval) return retval;
+#define next_tag() \
+{ taginfo t2; \
+ retval = asn1_get_tag_2(&subbuf, &t2); \
+ if (retval) return retval; \
+ /* Copy out to match previous functionality, until better integrated. */ \
+ asn1class = t2.asn1class; \
+ construction = t2.construction; \
+ tagnum = t2.tagnum; \
+ taglen = t2.length; \
+ indef = t2.indef; \
+}
/* Force check for EOC tag. */
-#define get_eoc() \
- retval = asn1_get_tag_indef(&subbuf, &asn1class, &construction, \
- &tagnum, &taglen, &indef); \
- if (retval) return retval; \
- if (asn1class != UNIVERSAL || tagnum || indef) \
- return ASN1_MISSING_EOC
+#define get_eoc() \
+ { \
+ taginfo t3; \
+ retval = asn1_get_tag_2(&subbuf, &t3); \
+ if(retval) return retval; \
+ if (t3.asn1class != UNIVERSAL || t3.tagnum || t3.indef) \
+ return ASN1_MISSING_EOC; \
+ /* Copy out to match previous functionality, until better integrated. */ \
+ asn1class = t3.asn1class; \
+ construction = t3.construction; \
+ tagnum = t3.tagnum; \
+ taglen = t3.length; \
+ indef = t3.indef; \
+ }
#define alloc_field(var, type) \
var = (type*)calloc(1, sizeof(type)); \
if ((var) == NULL) return ENOMEM
/* Fetch an expected APPLICATION class tag and verify. */
-#define apptag(tagexpect) \
- retval = asn1_get_tag(buf, &asn1class, &construction, &tagnum, &applen); \
- if (retval) return retval; \
- if (asn1class != APPLICATION || construction != CONSTRUCTED || \
- tagnum != (tagexpect)) return ASN1_BAD_ID
+#define apptag(tagexpect) \
+ { \
+ taginfo t1; \
+ retval = asn1_get_tag_2(buf, &t1); \
+ if (retval) return retval; \
+ if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED || \
+ t1.tagnum != (tagexpect)) return ASN1_BAD_ID; \
+ /* Copy out to match previous functionality, until better integrated. */ \
+ asn1class = t1.asn1class; \
+ construction = t1.construction; \
+ tagnum = t1.tagnum; \
+ applen = t1.length; \
+ }
/**** normal fields ****/
* Attempts to fetch an EOC tag, if any, and to sync over trailing
* garbage, if any.
*/
-#define end_sequence_of(buf) \
- retval = asn1_get_tag_indef(&seqbuf, &asn1class, &construction, \
- &tagnum, &taglen, &indef); \
- if (retval) return retval; \
- retval = asn1buf_sync(buf, &seqbuf, asn1class, tagnum, \
- length, indef, seqofindef); \
+#define end_sequence_of(buf) \
+ { \
+ taginfo t4; \
+ retval = asn1_get_tag_2(&seqbuf, &t4); \
+ if (retval) return retval; \
+ /* Copy out to match previous functionality, until better integrated. */ \
+ asn1class = t4.asn1class; \
+ construction = t4.construction; \
+ tagnum = t4.tagnum; \
+ taglen = t4.length; \
+ indef = t4.indef; \
+ } \
+ retval = asn1buf_sync(buf, &seqbuf, asn1class, tagnum, \
+ length, indef, seqofindef); \
if (retval) return retval;
/*
* Like end_sequence_of(), but uses the different (non-shadowing)
* variable names.
*/
-#define end_sequence_of_no_tagvars(buf) \
- retval = asn1_get_tag_indef(&seqbuf, &eseqclass, &eseqconstr, \
- &eseqnum, &eseqlen, &eseqindef); \
- if (retval) return retval; \
- retval = asn1buf_sync(buf, &seqbuf, eseqclass, eseqnum, \
- eseqlen, eseqindef, seqofindef); \
+#define end_sequence_of_no_tagvars(buf) \
+ { \
+ taginfo t5; \
+ retval = asn1_get_tag_2(&seqbuf, &t5); \
+ if (retval) return retval; \
+ /* Copy out to match previous functionality, until better integrated. */ \
+ eseqclass = t5.asn1class; \
+ eseqconstr = t5.construction; \
+ eseqnum = t5.tagnum; \
+ eseqlen = t5.length; \
+ eseqindef = t5.indef; \
+ } \
+ retval = asn1buf_sync(buf, &seqbuf, eseqclass, eseqnum, \
+ eseqlen, eseqindef, seqofindef); \
if (retval) return retval;
#define cleanup() \
asn1_error_code asn1_decode_krb5_flags(asn1buf *buf, krb5_flags *val)
{
- setup();
+ asn1_error_code retval;
asn1_octet unused, o;
+ taginfo t;
int i;
krb5_flags f=0;
- unused_var(taglen);
+ unsigned int length;
- retval = asn1_get_tag(buf,&asn1class,&construction,&tagnum,&length);
- if(retval) return retval;
- if(asn1class != UNIVERSAL || construction != PRIMITIVE ||
- tagnum != ASN1_BITSTRING) return ASN1_BAD_ID;
+ retval = asn1_get_tag_2(buf, &t);
+ if (retval) return retval;
+ if (t.asn1class != UNIVERSAL || t.construction != PRIMITIVE ||
+ t.tagnum != ASN1_BITSTRING)
+ return ASN1_BAD_ID;
+ length = t.length;
retval = asn1buf_remove_octet(buf,&unused); /* # of padding bits */
if(retval) return retval;
end_structure();
val->magic = KV5M_TICKET;
}
- if(!applen) {
- retval = asn1_get_tag(buf,&asn1class,&construction,&tagnum,NULL);
- if (retval) return retval;
+ if (!applen) {
+ taginfo t;
+ retval = asn1_get_tag_2(buf, &t);
+ if (retval) return retval;
}
cleanup();
}
asn1_error_code asn1buf_skiptail(asn1buf *buf, const unsigned int length, const int indef)
{
asn1_error_code retval;
- asn1_class asn1class;
- asn1_construction construction;
- asn1_tagnum tagnum;
- unsigned int taglen;
+ taginfo t;
int nestlevel;
- int tagindef;
nestlevel = 1 + indef;
if (!indef) {
return ASN1_OVERRUN;
}
while (nestlevel > 0) {
- retval = asn1_get_tag_indef(buf, &asn1class, &construction, &tagnum,
- &taglen, &tagindef);
+ retval = asn1_get_tag_2(buf, &t);
if (retval) return retval;
- if (!tagindef) {
- if (taglen <= buf->bound - buf->next + 1)
- buf->next += taglen;
+ if (!t.indef) {
+ if (t.length <= buf->bound - buf->next + 1)
+ buf->next += t.length;
else
return ASN1_OVERRUN;
}
- if (tagindef)
+ if (t.indef)
nestlevel++;
- if (asn1_is_eoc(asn1class, tagnum, tagindef))
+ if (asn1_is_eoc(t.asn1class, t.tagnum, t.indef))
nestlevel--; /* got an EOC encoding */
}
return 0;
/* process encoding header ***************************************/
/* decode tag and check that it == [APPLICATION tagnum] */
-#define check_apptag(tagexpect)\
-retval = asn1_get_tag(&buf,&asn1class,&construction,&tagnum,NULL);\
-if(retval) clean_return(retval);\
-if(asn1class != APPLICATION || construction != CONSTRUCTED) \
- clean_return(ASN1_BAD_ID);\
-if(tagnum != (tagexpect)) clean_return(KRB5_BADMSGTYPE)
+#define check_apptag(tagexpect) \
+{ \
+ taginfo t1; \
+ retval = asn1_get_tag_2(&buf, &t1); \
+ if (retval) clean_return (retval); \
+ if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED) \
+ clean_return(ASN1_BAD_ID); \
+ if (t1.tagnum != (tagexpect)) clean_return(KRB5_BADMSGTYPE); \
+ asn1class = t1.asn1class; \
+ construction = t1.construction; \
+ tagnum = t1.tagnum; \
+}
/* process a structure *******************************************/
/* decode an explicit tag and place the number in tagnum */
-#define next_tag()\
-retval = asn1_get_tag_indef(&subbuf,&asn1class,&construction,&tagnum,NULL,&indef);\
-if(retval) clean_return(retval)
+#define next_tag() \
+{ taginfo t2; \
+ retval = asn1_get_tag_2(&subbuf, &t2); \
+ if(retval) clean_return(retval); \
+ asn1class = t2.asn1class; \
+ construction = t2.construction; \
+ tagnum = t2.tagnum; \
+ indef = t2.indef; \
+}
#define get_eoc() \
-retval = asn1_get_tag_indef(&subbuf,&asn1class,&construction, \
- &tagnum,NULL,&indef); \
-if(retval) return retval; \
-if(asn1class != UNIVERSAL || tagnum || indef) \
- return ASN1_MISSING_EOC
+{ \
+ taginfo t3; \
+ retval = asn1_get_tag_2(&subbuf, &t3); \
+ if (retval) return retval; \
+ if (t3.asn1class != UNIVERSAL || t3.tagnum || t3.indef) \
+ return ASN1_MISSING_EOC; \
+ asn1class = t3.asn1class; \
+ construction = t3.construction; \
+ tagnum = t3.tagnum; \
+ indef = t3.indef; \
+}
/* decode sequence header and initialize tagnum with the first field */
#define begin_structure()\
krb5_error_code decode_krb5_enc_kdc_rep_part(const krb5_data *code, krb5_enc_kdc_rep_part **rep)
{
- setup_no_length();
+ taginfo t4;
+ setup_buf_only();
alloc_field(*rep,krb5_enc_kdc_rep_part);
- retval = asn1_get_tag(&buf,&asn1class,&construction,&tagnum,NULL);
- if(retval) clean_return(retval);
- if(asn1class != APPLICATION || construction != CONSTRUCTED) clean_return(ASN1_BAD_ID);
- if(tagnum == 25) (*rep)->msg_type = KRB5_AS_REP;
- else if(tagnum == 26) (*rep)->msg_type = KRB5_TGS_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;
else clean_return(KRB5_BADMSGTYPE);
retval = asn1_decode_enc_kdc_rep_part(&buf,*rep);