diff --git a/CHANGES b/CHANGES index 786ab5064c4fea90b3b0652fcafc9add2ca88017..7645d6f5f96e7c7ccd80ccdbcf5c371e29dbb2d1 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,18 @@ Changes between 0.9.5a and 0.9.6 [xx XXX 2000] + *) Fix for a nasty bug in ASN1_TYPE handling. ASN1_TYPE is used for + a general "ANY" type, as such it should be able to decode anything + including tagged types. However it didn't check the class so it would + wrongly interpret tagged types in the same way as their universal + counterpart and unknown types were just rejected. Changed so that the + tagged and unknown types are handled in the same way as a SEQUENCE: + that is the encoding is stored intact. There is also a new type + "V_ASN1_OTHER" which is used when the class is not universal, in this + case we have no idea what the actual type is so we just lump them all + together. + [Steve Henson] + *) On VMS, stdout may very well lead to a file that is written to in a record-oriented fashion. That means that every write() will write a separate record, which will be read separately by the diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c index 3620e60e99ada82452fea7bb673311a515ef4e84..cf716027d3b0e56278561aa7318e2441368f44a3 100644 --- a/crypto/asn1/a_type.c +++ b/crypto/asn1/a_type.c @@ -123,6 +123,8 @@ int i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp) break; case V_ASN1_SET: case V_ASN1_SEQUENCE: + case V_ASN1_OTHER: + default: if (a->value.set == NULL) r=0; else @@ -159,6 +161,8 @@ ASN1_TYPE *d2i_ASN1_TYPE(ASN1_TYPE **a, unsigned char **pp, long length) inf=ASN1_get_object(&q,&len,&tag,&xclass,length); if (inf & 0x80) goto err; + /* If not universal tag we've no idea what it is */ + if(xclass != V_ASN1_UNIVERSAL) tag = V_ASN1_OTHER; ASN1_TYPE_component_free(ret); @@ -245,6 +249,8 @@ ASN1_TYPE *d2i_ASN1_TYPE(ASN1_TYPE **a, unsigned char **pp, long length) break; case V_ASN1_SET: case V_ASN1_SEQUENCE: + case V_ASN1_OTHER: + default: /* Sets and sequences are left complete */ if ((ret->value.set=ASN1_STRING_new()) == NULL) goto err; ret->value.set->type=tag; @@ -252,9 +258,6 @@ ASN1_TYPE *d2i_ASN1_TYPE(ASN1_TYPE **a, unsigned char **pp, long length) if (!ASN1_STRING_set(ret->value.set,p,(int)len)) goto err; p+=len; break; - default: - ASN1err(ASN1_F_D2I_ASN1_TYPE,ASN1_R_BAD_TYPE); - goto err; } ret->type=tag; @@ -333,10 +336,9 @@ static void ASN1_TYPE_component_free(ASN1_TYPE *a) case V_ASN1_UNIVERSALSTRING: case V_ASN1_BMPSTRING: case V_ASN1_UTF8STRING: - ASN1_STRING_free((ASN1_STRING *)a->value.ptr); - break; + case V_ASN1_OTHER: default: - /* MEMORY LEAK */ + ASN1_STRING_free((ASN1_STRING *)a->value.ptr); break; } a->type=0; diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index 334637752707c3ec175ca8d615107fc5dc79257a..6f956b1963e13a18f6a34937f1be4ab92fd756ff 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -83,6 +83,7 @@ extern "C" { #define V_ASN1_PRIMATIVE_TAG 0x1f #define V_ASN1_APP_CHOOSE -2 /* let the recipient choose */ +#define V_ASN1_OTHER -3 /* used in ASN1_TYPE */ #define V_ASN1_NEG 0x100 /* negative flag */