diff --git a/lib/asn1/CMS.asn1 b/lib/asn1/CMS.asn1 new file mode 100644 index 000000000..89410aeaa --- /dev/null +++ b/lib/asn1/CMS.asn1 @@ -0,0 +1,141 @@ +-- From RFC 3369 -- +-- $Id$ -- + +CMS DEFINITIONS ::= BEGIN + +IMPORTS CertificateSerialNumber, AlgorithmIdentifier, Name, + Attribute, Certificate, Name, SubjectKeyIdentifier FROM rfc2459 + heim_any, heim_any_set FROM heim; + +id-pkcs7 OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) rsadsi(113549) pkcs(1) pkcs7(7) } + +id-pkcs7-data OBJECT IDENTIFIER ::= { id-pkcs7 1 } +id-pkcs7-signedData OBJECT IDENTIFIER ::= { id-pkcs7 2 } +id-pkcs7-envelopedData OBJECT IDENTIFIER ::= { id-pkcs7 3 } +id-pkcs7-signedAndEnvelopedData OBJECT IDENTIFIER ::= { id-pkcs7 4 } +id-pkcs7-digestedData OBJECT IDENTIFIER ::= { id-pkcs7 5 } +id-pkcs7-encryptedData OBJECT IDENTIFIER ::= { id-pkcs7 6 } + +CMSVersion ::= INTEGER { v0(0), v1(1), v2(2), v3(3), v4(4) } + +DigestAlgorithmIdentifier ::= AlgorithmIdentifier +DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier +SignatureAlgorithmIdentifier ::= AlgorithmIdentifier + +ContentType ::= OBJECT IDENTIFIER + +ContentInfo ::= SEQUENCE { + contentType ContentType, + content [0] EXPLICIT heim_any OPTIONAL -- DEFINED BY contentType +} + +EncapsulatedContentInfo ::= SEQUENCE { + eContentType ContentType, + eContent [0] EXPLICIT OCTET STRING OPTIONAL +} + +CertificateSet ::= heim_any_set -- SET OF +CertificateSetReal ::= SET OF heim_any + +CertificateList ::= Certificate + +CertificateRevocationLists ::= SET OF CertificateList + +IssuerAndSerialNumber ::= SEQUENCE { + issuer Name, + serialNumber CertificateSerialNumber +} + +-- RecipientIdentifier is same as SignerIdentifier, +-- lets glue them togheter and save some bytes and share code for them + +CMSIdentifier ::= CHOICE { + issuerAndSerialNumber IssuerAndSerialNumber, + subjectKeyIdentifier [0] SubjectKeyIdentifier +} + +SignerIdentifier ::= CMSIdentifier +RecipientIdentifier ::= CMSIdentifier + +SignedAttributes ::= SET OF Attribute -- SIZE (1..MAX) +UnsignedAttributes ::= SET OF Attribute -- SIZE (1..MAX) + +SignatureValue ::= OCTET STRING + +SignerInfo ::= SEQUENCE { + version CMSVersion, + sid SignerIdentifier, + digestAlgorithm DigestAlgorithmIdentifier, + signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL, + signatureAlgorithm SignatureAlgorithmIdentifier, + signature SignatureValue, + unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL +} + +SignerInfos ::= SET OF SignerInfo + +SignedData ::= SEQUENCE { + version CMSVersion, + digestAlgorithms DigestAlgorithmIdentifiers, + encapContentInfo EncapsulatedContentInfo, + certificates [0] IMPLICIT CertificateSet OPTIONAL, + crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, + signerInfos SignerInfos +} + +OriginatorInfo ::= SEQUENCE { + certs [0] IMPLICIT CertificateSet OPTIONAL, + crls [1] IMPLICIT CertificateRevocationLists OPTIONAL +} + +KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier +ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + +EncryptedKey ::= OCTET STRING + +KeyTransRecipientInfo ::= SEQUENCE { + version CMSVersion, -- always set to 0 or 2 + rid RecipientIdentifier, + keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + encryptedKey EncryptedKey +} + +RecipientInfo ::= KeyTransRecipientInfo + +RecipientInfos ::= SET OF RecipientInfo + +EncryptedContent ::= OCTET STRING + +EncryptedContentInfo ::= SEQUENCE { + contentType ContentType, + contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, + encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL +} + +UnprotectedAttributes ::= SET OF Attribute -- SIZE (1..MAX) + +CMSEncryptedData ::= SEQUENCE { + version CMSVersion, + encryptedContentInfo EncryptedContentInfo, + unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL +} + +EnvelopedData ::= SEQUENCE { + version CMSVersion, + originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + recipientInfos RecipientInfos, + encryptedContentInfo EncryptedContentInfo, + unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL +} + +-- Data ::= OCTET STRING + +CMSRC2CBCParameter ::= SEQUENCE { + rc2ParameterVersion INTEGER, + iv OCTET STRING -- exactly 8 octets +} + +CMSCBCParameter ::= OCTET STRING + +END diff --git a/lib/asn1/ChangeLog b/lib/asn1/ChangeLog new file mode 100644 index 000000000..e7f392d56 --- /dev/null +++ b/lib/asn1/ChangeLog @@ -0,0 +1,763 @@ +2005-07-12 Love + + * gen_locl.h: rename function filename() to get_filename() to + avoid shadowing + + * lex.l: rename function filename() to get_filename() to avoid + shadowing + + * gen.c: rename function filename() to get_filename() to avoid + shadowing + + * check-der.c: add failure checks for large oid elements + + * check-gen.c: add failure checks for tag (and large tags) + + * der_get.c: Check for integer overflows in tags and oid elements. + +2005-07-10 Assar Westerlund + + * gen_decode.c: Fix decoding of choices to select which branch to + try based on the tag and return an error if that branch fails. + + * check-gen.c: Fix short choice test cases. + +2005-07-09 Assar Westerlund + + * symbol.c: + * parse.y: + * main.c: + * lex.l: + * gen_length.c: + * gen_free.c: + * gen_encode.c: + * gen_decode.c: + * gen_copy.c: + * gen.c: + * extra.c: + * check-gen.c: + * check-der.c: + * check-common.c: + * asn1_print.c: + * asn1_gen.c: + Use emalloc, ecalloc, and estrdup. + Check return value from asprintf. + Make sure that malloc(0) returning NULL is not treated as an + error. + +2005-07-10 Love + + * check-gen.c: test cases for CHOICE, its too liberal right now, + it don't fail hard on failure on after it successfully decoded the + first tag in a choice branch + + * asn1_gen.c: calculate the basename for the output file, + pretty-print tag number + + * test.gen: sample for asn1_gen + + * check-gen.c: check errors in SEQUENCE + + * Makefile.am: build asn1_gen, TESTSeq and new, and class/type/tag + string<->num converter. + + * test.asn1: TESTSeq, for testing SEQUENCE + + * asn1_gen.c: generator for asn1 data + + * asn1_print.c: use class/type/tag string<->num converter. + + * der.c: Add class/type/tag string<->num converter. + + * der.h: Add class/type/tag string<->num converter. + Prototypes/structures for new time bits. + +2005-07-09 Love + + * der_get.c (der_get_unsigned) check for length overflow + (der_get_integer) ditto + (der_get_general_string) ditto + + * der_get.c: check for overruns using SIZE_T_MAX + + * check-der.c: check BIT STRING and OBJECT IDENTIFIER error cases + + * check-common.c (generic_decode_fail): allocate 4K for the over + sized memory test + + * der_get.c (der_get_oid): check for integer overruns and + unterminated oid correctly + + * check-common.h (map_alloc, generic_decode_fail): prototypes + + * check-common.c (map_alloc): make input buffer const + (generic_decode_fail): verify decoding failures + +2005-07-05 Love + + * gen_encode.c: split up the printf for SET OF, also use the + generate name for the symbol in the SET OF, if not, the name might + contain non valid variable name characters (like -) + +2005-07-04 Love + + * Makefile.am: move pkcs12 defines into their own namespace + + * pkcs12.asn1: move pkcs12 defines into their own namespace + + * pkcs9.asn1: add PKCS9-friendlyName with workaround for SET OF + bug + + * heim_asn1.h: reuse heim_octet_string for heim_any types + + * main.c: use optidx, handle the case where name is missing and + use base of filename then + + * asn1-common.h: include ASN1_MALLOC_ENCODE + + * gen_decode.c: use less context so lower indentention level, add + missing {} where needed + +2005-07-02 Love + + * gen_copy.c: Use a global variable to keep track of if the 'goto + fail' was used, and use that to only generate the label if needed. + + * asn1_print.c: do indefinite form loop detection and stop after + 10000 recursive indefinite forms, stops crashing due to running + out of stack + + * asn1_print.c: catch badly formated indefinite length data + (missing EndOfContent tag) add (negative) indent flag to speed up + testing + +2005-07-01 Love + + * canthandle.asn1: Can't handle primitives in CHOICE + + * gen_decode.c: Check if malloc failes + + * gen_copy.c: Make sure to free memory on failure + + * gen_decode.c: Check if malloc failes, rename "reallen" to + tagdatalen since that is what it is. + +2005-05-29 Love + + * prefix Der_class with ASN1_C_ to avoid problems with system + headerfiles that pollute the name space + +2005-05-20 Love + + * pkcs12.asn1: add PKCS12CertBag + + * pkcs9.asn1: add pkcs9 certtype x509 certificate + + * Makefile.am: add pkcs12 certbag and pkcs9 certtype x509 + certificate + + * pkcs12.asn1: split off PKCS12Attributes from SafeBag so it can + be reused + + * Makefile.am: add PKCS12Attributes + +2005-05-10 Love + + * canthandle.asn1: fix tags in example + +2005-05-02 Love + + * pkinit.asn1: Let the Windows nonce be an int32 (signed), if not + it will fail when using Windows PK-INIT. + +2005-05-01 Love + + * Makefile.am: add pkcs12-PBEParams + + * pkcs12.asn1: add pkcs12-PBEParams + + * parse.y: objid_element: exit when the condition fails + +2005-04-26 Love + + * gen_glue.c: 1.8: switch the units variable to a + function. gcc-4.1 needs the size of the structure if its defined + as extern struct units foo_units[] an we don't want to include + in the generate headerfile + +2005-03-20 Love + + * Makefile.am: add the des-ede3-cbc oid that ansi x9.52 uses + + * rfc2459.asn1: add the des-ede3-cbc oid that ansi x9.52 uses + + * Makefile.am: add oids for x509 + + * rfc2459.asn1: add oids now when the compiler can handle them + +2005-03-19 Love + + * Makefile.am: add pkcs9 files + + * pkcs9.asn1: add small number of oids from pkcs9 + +2005-03-14 Love + + * Makefile.am: add a bunch of pkcs1/pkcs2/pkcs3/aes oids + + * rfc2459.asn1: add a bunch of pkcs1/pkcs2/pkcs3/aes oids + +2005-03-10 Love + + * k5.asn1: merge pa-numbers + +2005-03-09 Love + + * Makefile.am: add oid's + + * rfc2459.asn1: add encryption oids + + * CMS.asn1: add signedAndEnvelopedData oid + + * pkcs12.asn1: add pkcs12 oids + + * CMS.asn1: add pkcs7 oids + +2005-03-08 Love + + * gen.c (generate_header_of_codefile): break out the header + section generation + (generate_constant): generate a function that return the oid + inside a heim_oid + + * parse.y: fix the ordering of the oid's + + * parse.y: handle OBJECT IDENTIFIER as value construct + +2005-02-24 Love + + * Preserve content of CHOICE element that is unknown if ellipsis + was used when defining the structure + +2005-02-13 Love + + * parse.y: use ANS1_TAILQ macros + + * *.[ch]: use ASN1_TAILQ macros + + * asn1_queue.h: inline bsd sys/queue.h and rename TAILQ to + ASN1_TAILQ to avoid problems with name polluting headerfiles + +2005-01-19 Love + + * gen.c: pull in + +2005-01-10 Love + + * Add BMPString and UniversalString + + * k5.asn1 (EtypeList): make INTEGER constrained (use krb5int32) + +2005-01-07 Love + + * rfc2459.asn1: add GeneralNames + +2004-11-21 Love + + * gen.c: use unsigned integer for len of SequenceOf/SetOf and + bitstring names + +2004-11-10 Love + + * Makefile.am: switch to krb5int32 and krb5uint32 + + * Unify that three integer types TInteger TUInteger and TBigInteger. + Start to use constrained integers where appropriate. + +2004-10-13 Love + + * CMS.asn1: remove no longer used commented out elements + + * gen_glue.c: make units structures const + +2004-10-12 Love + + * lex.l: handle hex number with [a-fA-F] in them + +2004-10-07 Love + + * gen_free.c: free _save for CHOICE too + + * rfc2459.asn1: use Name and not heim_any + + * gen_decode.c: if malloc for _save failes, goto fail so we free + the structure + + * gen_copy.c: copy _save for CHOICE too + + * gen.c: add _save for CHOICE too + + * CMS.asn1: RecipientIdentifier and SignerIdentifier is the same + name is CMSIdentifier and add glue for that so we can share code + use Name and not heim_any + +2004-10-03 Love + + * Makefile.am: drop AlgorithmIdentifierNonOpt add + {RC2CBC,}CBCParameter here where they belong + + * CMS.asn1: add {RC2CBC,}CBCParameter here where they belong + + * rfc2459.asn1: drop AlgorithmIdentifierNonOpt + + * rfc2459.asn1: stop using AlgorithmIdentifierNonOpt hint that we + really want to use Name and some MS stuff + +2004-09-05 Love + + * asn1_print.c: handle end of content, this is part BER support, + however, OCTET STRING need some tweeking too. + + * der.h: add UT_EndOfContent + + * test.asn1: test asn1 spec file + + * check-gen.c: check larget tags + + * Makefile.am: add test asn1 spec file that we can use for testing + constructs that doesn't exists in already existing spec (like + large tags) + + * der_put.c (der_put_tag): make sure there are space for the head + tag when we are dealing with large tags (>30) + + * check-gen.c: add test for tag length + + * check-common.c: export the map_ functions for OVERRUN/UNDERRUN + detection restore the SIGSEGV handler when test is done + + * check-common.h: export the map_ functions for OVERRUN/UNDERRUN + detection + + * gen_decode.c: check that the tag-length is not longer the length + use forwstr on some more places + + * parse.y: revert part of 1.14.2.21, multiple IMPORT isn't allowed + + * pkinit.asn1: correct usage of IMPORT + + * CMS.asn1: correct usage of IMPORT + + * pkcs8.asn1: pkcs8, encrypting private key + + * pkcs12.asn1: pkcs12, key/crl/certificate file transport PDU + + * Makefile.am: add pkcs8 and pkcs12 + + * der_free.c: reset length when freing primitives + + * CMS.asn1: add EncryptedData + +2004-08-26 Love + + * gen_decode.c (decode_type): if the entry is already optional + when parsing a tag and we allocate the structure, not pass down + optional since that will case the subtype's decode_type also to + allocate an entry. and we'll leak an entry. Bug from Luke Howard + . While here, use calloc. + +2004-04-29 Love + + * k5.asn1: shift the last added etypes one step so rc2 doesn't + stomp on cram-md5 + +2004-04-26 Love + + * k5.asn1: add ETYPE_AESNNN_CBC_NONE + + * CMS.asn1: add CMS symmetrical parameters moved to k5.asn1 + + * k5.asn1: add CMS symmetrical parameters here, more nametypes + enctype rc2-cbc + +2004-04-25 Love + + * gen_decode.c: free data on decode failure + +2004-04-24 Love + + * Makefile.am: add CBCParameter and RC2CBCParameter + + * CMS.asn1: add CBCParameter and RC2CBCParameter + +2004-04-20 Love + + * check-der.c: add simple test for oid's, used to trigger malloc + bugs in you have picky malloc (like valgrind/purify/third) + + * der_get.c (der_get_oid): handle all oid components being smaller + then 127 and allocate one extra element since first byte is split + to to elements. + +2004-04-16 Love + + * canthandle.asn1: one thing handled + + * gen_decode.c: handle OPTIONAL CONS-tag-less elements + + * der_length.c (length_len): since length is no longer the same as + an unsigned, do the length counting here. ("unsigned" is zero + padded when most significate bit is set, length is not) + +2004-04-12 Love + + * canthandle.asn1: document by example what the encoder can't + handle right now + + * Makefile.am: add more stuff needed whem implementing x509 + preserve TBSCertificate + + * rfc2459.asn1: add more stuff needed whem implementing x509 + + * CMS.asn1: move some type to rfc2459.asn1 where they belong (and + import them) + + * gen.c: preserve the raw data when asked too + + * gen_decode.c: preserve the raw data when asked too + + * gen_copy.c: preserve the raw data when asked too + + * gen_free.c: preserve the raw data when asked too + + * gen_locl.h: add preserve_type + + * heim_asn1.h: add heim_any_cmp + + * main.c: add flag --preserve-binary=Symbol1,Symbol2,... that make + the compiler generate stubs to save the raw data, its not used + right now when generating the stat + + * k5.asn1: Windows uses PADATA 15 for the request too + + * extra.c: add heim_any_cmp + + * der_put.c: implement UTCtime correctly + + * der_locl.h: remove #ifdef HAVE_TIMEGM\ntimegm\n#endif here from + der.h so one day der.h can get installed + + * der_length.c: implement UTCtime correctly + + * der_get.c: implement UTCtime correctly, prefix dce_fix with + _heim_fix + + * der_copy.c: make copy_bit_string work again + + * der_cmp.c: add octet_string, integer, bit_string cmp functions + + * der.h: hide away more symbols, add more _cmp functions + +2004-03-06 Love + + * Makefile.am: add more pkix types make k5 use rfc150 bitstrings, + everything else use der bitstrings + + * main.c: as a compile time option, handle no rfc1510 bitstrings + + * gen_locl.h: rfc1510 bitstrings flag + + * gen_length.c: as a compile time option, handle no rfc1510 + bitstrings + + * gen_encode.c: as a compile time option, handle no rfc1510 + bitstrings + + * gen_decode.c: handle no rfc1510 bitstrings + + * check-gen.c: test for bitstrings + + * rfc2459.asn1: add Certificates and KeyUsage + +2004-02-22 Love + + * pkinit.asn1: use Name from PKIX + + * rfc2459.asn1: add more silly string types to DirectoryString + + * gen_encode.c: add checks for data overflow when encoding + TBitString with members encode SET OF correctly by bytewise + sorting the members + + * gen_decode.c: add checks for data overrun when encoding + TBitString with members + + * der_put.c: add _heim_der_set_sort + + * der_cmp.c: rename oid_cmp to heim_oid_cmp + + * der.h: rename oid_cmp to heim_oid_cmp, add _heim_der_set_sort + + * check-gen.c: add check for Name and (commented out) heim_integer + + * check-der.c: test for "der_length.c: Fix len_unsigned for + certain negative integers, it got the length wrong" , from + Panasas, Inc. + + * der_length.c: Fix len_unsigned for certain negative integers, it + got the length wrong, fix from Panasas, Inc. + + rename len_int and len_unsigned to _heim_\& + + * gen_length.c: 1.14: (length_type): TSequenceOf: add up the size + of all the elements, don't use just the size of the last element. + +2004-02-20 Love + + * rfc2459.asn1: include defintion of Name + + * pkinit.asn1: no need for ContentType, its cms internal + + * CMS.asn1: move ContentInfo to CMS + + * pkinit.asn1: update to pk-init-18, move ContentInfo to CMS + + * Makefile.am: align with pk-init-18, move contentinfo to cms + +2004-02-17 Love + + * der_get.c: rewrite previous commit + + * der_get.c (der_get_heim_integer): handle positive integer + starting with 0 + + * der_length.c (der_put_heim_integer): try handle negative + integers better (?) + + * der_put.c (der_put_heim_integer): try handle negative integers + better + + * der_get.c (der_get_heim_integer): dont abort on negative integer just + return ASN1_OVERRUN for now + + * parse.y: add ia5string, and printablestring + + * gen_length.c: add ia5string, and printablestring + + * gen_free.c: add ia5string, and printablestring + + * gen_decode.c: add ia5string, and printablestring + + * gen_copy.c: add ia5string, and printablestring + + * gen.c: add ia5string, printablestring, and utf8string change + implemetation of heim_integer and store the data as bigendian byte + array with a external flag for signedness + + * der_put.c: add ia5string, printablestring, and utf8string change + implemetation of heim_integer and store the data as bigendian byte + array with a external flag for signedness + + * der_length.c: add ia5string, printablestring, and utf8string + change implemetation of heim_integer and store the data as + bigendian byte array with a external flag for signedness + + * der_get.c: add ia5string, printablestring, and utf8string change + implemetation of heim_integer and store the data as bigendian byte + array with a external flag for signedness + + * der_free.c: add ia5string, printablestring, and utf8string + + * der_copy.c: add ia5string, printablestring, and utf8string + + * der.h: add ia5string, printablestring, and utf8string + + * asn1-common.h: add signedness flag to heim_integer, add + ia5string and printablestring + +2004-02-13 Love + + * rfc2459.asn1: use BIGINTEGER where appropriate + + * setchgpw2.asn1: spelling and add op-req again + +2004-02-12 Love + + * Makefile.am: clean up better + +2004-02-11 Love + + * gen_decode.c (decode_type): TTag, don't overshare the reallen + variable + + * Makefile.am: adapt to log file name change + + * gen.c: genereate log file name based on base name + +2003-11-26 Love + + * Makefile.am: += asn1_AlgorithmIdentifierNonOpt.x + + * rfc2459.asn1: add AlgorithmIdentifierNonOpt and use it where + it's needed, make DomainParameters.validationParms heim_any as a + hack. Both are workarounds for the problem with heimdal's asn1 + compiler have with decoing context tagless OPTIONALs. + + * pkinit.asn1: don't import AlgorithmIdentifier + +2003-11-25 Love + + * der_put.c (der_put_bit_string): make it work somewhat better + (should really prune off all trailing zeros) + + * gen_encode.c (encode_type): bit string is not a constructed type + + * der_length.c (length_bit_string): calculate right length for + bitstrings + +2003-11-24 Love + + * der_cmp.c (oid_cmp): compare the whole array, not just + length/sizeof(component) + + * check-common.c: mmap the scratch areas, mprotect before and + after, align data to the edge of the mprotect()ed area to provoke + bugs + + * Makefile.am: add DomainParameters, ValidationParms + + * rfc2459.asn1: add DomainParameters, ValidationParms + + * check-der.c: add free function + + * check-common.h: add free function + + * check-common.c: add free function + + * check-gen.c: check KRB-ERROR + + * asn1_print.c: check end of tag_names loop into APPL class tags + +2003-11-23 Love + + * der_put.c (der_put_generalized_time): check size, not *size + +2003-11-11 Love + + * gen_decode.c (decode_type/TBitString): skip over + skipped-bits-in-last-octet octet + + * gen_glue.c (generate_units): generate units in reverse order to + keep unparse_units happy + +2003-11-08 Love + + * Makefile.am: generate all silly pkinit files + + * pkinit.asn1: make it work again, add strange ms structures + + * k5.asn1: PROV-SRV-LOCATION, PacketCable provisioning server + location, PKT-SP-SEC-I09-030728 + + * asn1-common.h: add bit string + + * der_put.c: add bit string and utctime + + * gen.c: add bit string and utctime + + * gen_copy.c: add bit string and utctime + + * der_copy.c: add bit string + + * gen_decode.c: add utctime and bitstring + + * gen_encode.c: add utctime and bitstring + + * gen_free.c: add utctime and bitstring + + * gen_glue.c: don't generate glue for member-less bit strings + + * der_cmp.c: compare function for oids + + * gen_length.c: add utc time, make bit string work for bits + strings w/o any members + + * der_cmp.c: compare function for oids + + * der.h: update boolean prototypes add utctime and bit_string + + * der_free.c: add free_bit_string + + * der_get.c: add bit string and utctime + + * der_length.c: add bit string and utctime, fix memory leak in + length_generalized_time + + * CMS.asn1: make EncryptedContentInfo.encryptedContent a OCTET + STRING to make the generator do the right thing with IMPLICIT + mumble OPTIONAL, make CertificateSet a heim_any_set + + * extra.c, heim_asn1.h: add any_set, instead of just consuming one + der object, its consumes the rest of the data avaible + + * extra.c, heim_asn1.h: extern implementation of ANY, decoder + needs to have hack removed when generator handles tagless optional + data + + * pkinit.asn1: add KdcDHKeyInfo-Win2k + +2003-11-07 Love Hörnquist Åstrand + + * der_copy.c (copy_oid): copy all components + + * parse.y: parse UTCTime, allow multiple IMPORT + + * symbol.h: add TUTCTime + + * rfc2459.asn1: update + + * x509.asn1: update + + * pkinit.asn1: update + + * CMS.asn1: new file + + * asn1_print.c: print some more lengths, check length before + steping out in the void, parse SET, only go down CONTEXT of type + CONS (not PRIM) + +2003-09-17 Love Hörnquist Åstrand + + * gen_encode.c (TChoice, TSequence): code element in reverse + order... + +2003-09-16 Love Hörnquist Åstrand + + * gen.c: store NULL's as int's for now + + * parse.y: remove dup of type def of UsefulType + +2003-09-11 Love Hörnquist Åstrand + + * gen_decode.c (decode_type): if malloc failes, return ENOMEM + +2003-09-10 Love Hörnquist Åstrand + + * parse.y: kw_UTF8String is a token put tag around the OID + + * asn1_print.c (UT_Integer): when the integer is larger then int + can handle, just print BIG INT and its size + +2003-09-10 Love Hörnquist Åstrand + + * gen_decode.c (decode_type): TTag, try to generate prettier code + in the non optional case, also remember to update length + +2003-01-22 Johan Danielsson + + * gen_decode.c: add flag to decode broken DCE BER encoding + + * gen_locl.h: add flag to decode broken DCE BER encoding + + * main.c: add flag to decode broken DCE BER encoding + diff --git a/lib/asn1/Makefile.am b/lib/asn1/Makefile.am index dee678eb8..1c1168e9f 100644 --- a/lib/asn1/Makefile.am +++ b/lib/asn1/Makefile.am @@ -2,98 +2,329 @@ include $(top_srcdir)/Makefile.am.common -YFLAGS = -d +YFLAGS = -dt lib_LTLIBRARIES = libasn1.la -libasn1_la_LDFLAGS = -version-info 7:0:1 +libasn1_la_LDFLAGS = -version-info 6:1:1 -libasn1_la_LIBADD = $(LIB_com_err) +libasn1_la_LIBADD = @LIB_com_err@ -BUILT_SOURCES = \ - $(gen_files:.x=.c) \ - asn1_err.h \ +BUILT_SOURCES = \ + $(gen_files_rfc2459:.x=.c) \ + $(gen_files_cms:.x=.c) \ + $(gen_files_k5:.x=.c) \ + $(gen_files_pkinit:.x=.c) \ + $(gen_files_pkcs8:.x=.c) \ + $(gen_files_pkcs9:.x=.c) \ + $(gen_files_pkcs12:.x=.c) \ + asn1_err.h \ asn1_err.c -gen_files = \ - asn1_AD_AND_OR.x \ - asn1_AD_IF_RELEVANT.x \ - asn1_AD_KDCIssued.x \ - asn1_AD_MANDATORY_FOR_KDC.x \ - asn1_APOptions.x \ - asn1_AP_REP.x \ - asn1_AP_REQ.x \ - asn1_AS_REP.x \ - asn1_AS_REQ.x \ - asn1_Authenticator.x \ - asn1_AuthorizationData.x \ - asn1_AUTHDATA_TYPE.x \ - asn1_CBCParameter.x \ - asn1_CKSUMTYPE.x \ - asn1_ChangePasswdDataMS.x \ - asn1_Checksum.x \ - asn1_ENCTYPE.x \ - asn1_ETYPE_INFO.x \ - asn1_ETYPE_INFO2.x \ - asn1_ETYPE_INFO2_ENTRY.x \ - asn1_ETYPE_INFO_ENTRY.x \ - asn1_EncAPRepPart.x \ - asn1_EncASRepPart.x \ - asn1_EncKDCRepPart.x \ - asn1_EncKrbCredPart.x \ - asn1_EncKrbPrivPart.x \ - asn1_EncTGSRepPart.x \ - asn1_EncTicketPart.x \ - asn1_EncryptedData.x \ - asn1_EncryptionKey.x \ - asn1_EtypeList.x \ - asn1_HostAddress.x \ - asn1_HostAddresses.x \ - asn1_KDCOptions.x \ - asn1_KDC_REP.x \ - asn1_KDC_REQ.x \ - asn1_KDC_REQ_BODY.x \ - asn1_KRB_CRED.x \ - asn1_KRB_ERROR.x \ - asn1_KRB_PRIV.x \ - asn1_KRB_SAFE.x \ - asn1_KRB_SAFE_BODY.x \ - asn1_KerberosString.x \ - asn1_KerberosTime.x \ - asn1_KrbCredInfo.x \ - asn1_LR_TYPE.x \ - asn1_LastReq.x \ - asn1_MESSAGE_TYPE.x \ - asn1_METHOD_DATA.x \ - asn1_NAME_TYPE.x \ - asn1_PADATA_TYPE.x \ - asn1_PA_DATA.x \ - asn1_PA_ENC_SAM_RESPONSE_ENC.x \ - asn1_PA_ENC_TS_ENC.x \ - asn1_PA_PAC_REQUEST.x \ - asn1_PA_SAM_CHALLENGE_2.x \ - asn1_PA_SAM_CHALLENGE_2_BODY.x \ - asn1_PA_SAM_REDIRECT.x \ - asn1_PA_SAM_RESPONSE_2.x \ - asn1_PA_SAM_TYPE.x \ - asn1_Principal.x \ - asn1_PrincipalName.x \ - asn1_RC2CBCParameter.x \ - asn1_Realm.x \ - asn1_SAMFlags.x \ - asn1_TGS_REP.x \ - asn1_TGS_REQ.x \ - asn1_Ticket.x \ - asn1_TicketFlags.x \ - asn1_TransitedEncoding.x \ - asn1_UNSIGNED.x +gen_files_k5 = \ + asn1_AD_AND_OR.x \ + asn1_AD_IF_RELEVANT.x \ + asn1_AD_KDCIssued.x \ + asn1_AD_MANDATORY_FOR_KDC.x \ + asn1_APOptions.x \ + asn1_AP_REP.x \ + asn1_AP_REQ.x \ + asn1_AS_REP.x \ + asn1_AS_REQ.x \ + asn1_AUTHDATA_TYPE.x \ + asn1_Authenticator.x \ + asn1_AuthorizationData.x \ + asn1_CKSUMTYPE.x \ + asn1_ChangePasswdDataMS.x \ + asn1_Checksum.x \ + asn1_ENCTYPE.x \ + asn1_ETYPE_INFO.x \ + asn1_ETYPE_INFO2.x \ + asn1_ETYPE_INFO2_ENTRY.x \ + asn1_ETYPE_INFO_ENTRY.x \ + asn1_EncAPRepPart.x \ + asn1_EncASRepPart.x \ + asn1_EncKDCRepPart.x \ + asn1_EncKrbCredPart.x \ + asn1_EncKrbPrivPart.x \ + asn1_EncTGSRepPart.x \ + asn1_EncTicketPart.x \ + asn1_EncryptedData.x \ + asn1_EncryptionKey.x \ + asn1_EtypeList.x \ + asn1_HostAddress.x \ + asn1_HostAddresses.x \ + asn1_KDCOptions.x \ + asn1_KDC_REP.x \ + asn1_KDC_REQ.x \ + asn1_KDC_REQ_BODY.x \ + asn1_KRB_CRED.x \ + asn1_KRB_ERROR.x \ + asn1_KRB_PRIV.x \ + asn1_KRB_SAFE.x \ + asn1_KRB_SAFE_BODY.x \ + asn1_krb5int32.x \ + asn1_krb5uint32.x \ + asn1_KerberosString.x \ + asn1_KerberosTime.x \ + asn1_KrbCredInfo.x \ + asn1_LR_TYPE.x \ + asn1_LastReq.x \ + asn1_MESSAGE_TYPE.x \ + asn1_METHOD_DATA.x \ + asn1_NAME_TYPE.x \ + asn1_PADATA_TYPE.x \ + asn1_PA_DATA.x \ + asn1_PA_ENC_SAM_RESPONSE_ENC.x \ + asn1_PA_ENC_TS_ENC.x \ + asn1_PA_SAM_CHALLENGE_2.x \ + asn1_PA_SAM_CHALLENGE_2_BODY.x \ + asn1_PA_SAM_REDIRECT.x \ + asn1_PA_SAM_RESPONSE_2.x \ + asn1_PA_SAM_TYPE.x \ + asn1_PA_PAC_REQUEST.x \ + asn1_PROV_SRV_LOCATION.x \ + asn1_Principal.x \ + asn1_PrincipalName.x \ + asn1_Realm.x \ + asn1_SAMFlags.x \ + asn1_TGS_REP.x \ + asn1_TGS_REQ.x \ + asn1_TYPED_DATA.x \ + asn1_Ticket.x \ + asn1_TicketFlags.x \ + asn1_TransitedEncoding.x \ + asn1_TypedData.x \ + asn1_RC2CBCParameter.x \ + asn1_CBCParameter.x + +gen_files_cms = \ + asn1_id_pkcs7.x \ + asn1_id_pkcs7_data.x \ + asn1_id_pkcs7_signedData.x \ + asn1_id_pkcs7_signedAndEnvelopedData.x \ + asn1_id_pkcs7_envelopedData.x \ + asn1_id_pkcs7_digestedData.x \ + asn1_id_pkcs7_encryptedData.x \ + asn1_CMSCBCParameter.x \ + asn1_CMSEncryptedData.x \ + asn1_CMSRC2CBCParameter.x \ + asn1_CMSVersion.x \ + asn1_CMSIdentifier.x \ + asn1_CertificateList.x \ + asn1_CertificateRevocationLists.x \ + asn1_CertificateSet.x \ + asn1_CertificateSetReal.x \ + asn1_ContentEncryptionAlgorithmIdentifier.x \ + asn1_ContentInfo.x \ + asn1_ContentType.x \ + asn1_DigestAlgorithmIdentifier.x \ + asn1_DigestAlgorithmIdentifiers.x \ + asn1_EncapsulatedContentInfo.x \ + asn1_EncryptedContent.x \ + asn1_EncryptedContentInfo.x \ + asn1_EncryptedKey.x \ + asn1_EnvelopedData.x \ + asn1_IssuerAndSerialNumber.x \ + asn1_KeyEncryptionAlgorithmIdentifier.x \ + asn1_KeyTransRecipientInfo.x \ + asn1_OriginatorInfo.x \ + asn1_RecipientIdentifier.x \ + asn1_RecipientInfo.x \ + asn1_RecipientInfos.x \ + asn1_SignatureAlgorithmIdentifier.x \ + asn1_SignatureValue.x \ + asn1_SignedAttributes.x \ + asn1_SignedData.x \ + asn1_SignerIdentifier.x \ + asn1_SignerInfo.x \ + asn1_SignerInfos.x \ + asn1_UnprotectedAttributes.x \ + asn1_UnsignedAttributes.x + +gen_files_rfc2459 = \ + asn1_Version.x \ + asn1_id_pkcs_1.x \ + asn1_id_pkcs1_rsaEncryption.x \ + asn1_id_pkcs1_md2WithRSAEncryption.x \ + asn1_id_pkcs1_md5WithRSAEncryption.x \ + asn1_id_pkcs1_sha1WithRSAEncryption.x \ + asn1_id_pkcs_2.x \ + asn1_id_pkcs2_md2.x \ + asn1_id_pkcs2_md4.x \ + asn1_id_pkcs2_md5.x \ + asn1_id_pkcs_3.x \ + asn1_id_pkcs3_rc2_cbc.x \ + asn1_id_pkcs3_rc4.x \ + asn1_id_pkcs3_des_ede3_cbc.x \ + asn1_id_rsadsi_encalg.x \ + asn1_id_rsadsi_des_ede3_cbc.x \ + asn1_id_secsig_sha_1.x \ + asn1_id_nit_aes_algs.x \ + asn1_id_aes_128_cbc.x \ + asn1_id_aes_192_cbc.x \ + asn1_id_aes_256_cbc.x \ + asn1_id_dhpublicnumber.x \ + asn1_id_x509_ce.x \ + asn1_AlgorithmIdentifier.x \ + asn1_AttributeType.x \ + asn1_AttributeValue.x \ + asn1_TeletexStringx.x \ + asn1_DirectoryString.x \ + asn1_Attribute.x \ + asn1_AttributeTypeAndValue.x \ + asn1_RelativeDistinguishedName.x \ + asn1_RDNSequence.x \ + asn1_Name.x \ + asn1_CertificateSerialNumber.x \ + asn1_Time.x \ + asn1_Validity.x \ + asn1_UniqueIdentifier.x \ + asn1_SubjectPublicKeyInfo.x \ + asn1_Extension.x \ + asn1_Extensions.x \ + asn1_TBSCertificate.x \ + asn1_Certificate.x \ + asn1_Certificates.x \ + asn1_ValidationParms.x \ + asn1_DomainParameters.x \ + asn1_OtherName.x \ + asn1_GeneralName.x \ + asn1_GeneralNames.x \ + asn1_id_x509_ce_keyUsage.x \ + asn1_KeyUsage.x \ + asn1_id_x509_ce_authorityKeyIdentifier.x \ + asn1_KeyIdentifier.x \ + asn1_AuthorityKeyIdentifier.x \ + asn1_id_x509_ce_subjectKeyIdentifier.x \ + asn1_SubjectKeyIdentifier.x \ + asn1_id_x509_ce_basicConstraints.x \ + asn1_BasicConstraints.x \ + asn1_id_x509_ce_nameConstraints.x \ + asn1_BaseDistance.x \ + asn1_GeneralSubtree.x \ + asn1_GeneralSubtrees.x \ + asn1_NameConstraints.x \ + asn1_id_x509_ce_privateKeyUsagePeriod.x \ + asn1_id_x509_ce_certificatePolicies.x \ + asn1_id_x509_ce_policyMappings.x \ + asn1_id_x509_ce_subjectAltName.x \ + asn1_id_x509_ce_issuerAltName.x \ + asn1_id_x509_ce_subjectDirectoryAttributes.x \ + asn1_id_x509_ce_policyConstraints.x \ + asn1_id_x509_ce_extKeyUsage.x \ + asn1_id_x509_ce_cRLDistributionPoints.x \ + asn1_id_x509_ce_cRLNumber.x \ + asn1_id_x509_ce_deltaCRLIndicator.x \ + asn1_id_x509_ce_issuingDistributionPoint.x \ + asn1_id_x509_ce_cRLReasons.x \ + asn1_id_x509_ce_holdInstructionCode.x \ + asn1_id_x509_ce_invalidityDate.x \ + asn1_id_x509_ce_certificateIssuer.x \ + asn1_id_x509_ce_inhibitAnyPolicy.x \ + asn1_id_x509_ce_freshestCRL.x \ + asn1_DSASigValue.x \ + asn1_DSAPublicKey.x \ + asn1_DSAParams.x \ + asn1_RSAPublicKey.x \ + asn1_DigestInfo.x + + +gen_files_pkinit = \ + asn1_id_pkinit.x \ + asn1_id_pkauthdata.x \ + asn1_id_pkdhkeydata.x \ + asn1_id_pkrkeydata.x \ + asn1_id_pkekuoid.x \ + asn1_id_pkkdcekuoid.x \ + asn1_DHNonce.x \ + asn1_TrustedCA.x \ + asn1_PA_PK_AS_REQ.x \ + asn1_PKAuthenticator.x \ + asn1_AuthPack.x \ + asn1_TD_TRUSTED_CERTIFIERS.x \ + asn1_TD_INVALID_CERTIFICATES.x \ + asn1_KRB5PrincipalName.x \ + asn1_AD_INITIAL_VERIFIED_CAS.x \ + asn1_DHRepInfo.x \ + asn1_PA_PK_AS_REP.x \ + asn1_KDCDHKeyInfo.x \ + asn1_ReplyKeyPack.x \ + asn1_TD_DH_PARAMETERS.x \ + asn1_PKAuthenticator_Win2k.x \ + asn1_AuthPack_Win2k.x \ + asn1_PA_PK_AS_REP_Win2k.x \ + asn1_KDCDHKeyInfo_Win2k.x \ + asn1_TrustedCA_19.x \ + asn1_PA_PK_AS_REQ_19.x \ + asn1_PA_PK_AS_REQ_Win2k.x \ + asn1_PKAuthenticator_19.x \ + asn1_AuthPack_19.x \ + asn1_PA_PK_AS_REP_19.x \ + asn1_ReplyKeyPack_19.x + + +gen_files_pkcs12 = \ + asn1_id_pkcs_12.x \ + asn1_id_pkcs_12PbeIds.x \ + asn1_id_pbeWithSHAAnd128BitRC4.x \ + asn1_id_pbeWithSHAAnd40BitRC4.x \ + asn1_id_pbeWithSHAAnd3_KeyTripleDES_CBC.x \ + asn1_id_pbeWithSHAAnd2_KeyTripleDES_CBC.x \ + asn1_id_pbeWithSHAAnd128BitRC2_CBC.x \ + asn1_id_pbewithSHAAnd40BitRC2_CBC.x \ + asn1_id_pkcs12_bagtypes.x \ + asn1_id_pkcs12_keyBag.x \ + asn1_id_pkcs12_pkcs8ShroudedKeyBag.x \ + asn1_id_pkcs12_certBag.x \ + asn1_id_pkcs12_crlBag.x \ + asn1_id_pkcs12_secretBag.x \ + asn1_id_pkcs12_safeContentsBag.x \ + asn1_PKCS12_MacData.x \ + asn1_PKCS12_PFX.x \ + asn1_PKCS12_AuthenticatedSafe.x \ + asn1_PKCS12_CertBag.x \ + asn1_PKCS12_Attribute.x \ + asn1_PKCS12_Attributes.x \ + asn1_PKCS12_SafeBag.x \ + asn1_PKCS12_SafeContents.x \ + asn1_PKCS12_PBEParams.x + +gen_files_pkcs8 = \ + asn1_PKCS8PrivateKeyAlgorithmIdentifier.x \ + asn1_PKCS8PrivateKey.x \ + asn1_PKCS8PrivateKeyInfo.x \ + asn1_PKCS8Attributes.x \ + asn1_PKCS8EncryptedPrivateKeyInfo.x \ + asn1_PKCS8EncryptedData.x + +gen_files_pkcs9 = \ + asn1_id_pkcs_9.x \ + asn1_id_pkcs_9_at_friendlyName.x \ + asn1_id_pkcs_9_at_localKeyId.x \ + asn1_id_pkcs_9_at_certTypes.x \ + asn1_id_pkcs_9_at_certTypes_x509.x \ + asn1_PKCS9_BMPString.x \ + asn1_PKCS9_friendlyName.x + +gen_files_test = \ + asn1_TESTChoice1.x \ + asn1_TESTChoice2.x \ + asn1_TESTSeq.x \ + asn1_TESTLargeTag.x + +noinst_PROGRAMS = asn1_compile asn1_print asn1_gen -noinst_PROGRAMS = asn1_compile asn1_print check_PROGRAMS = check-der check-gen TESTS = check-der check-gen -check_der_SOURCES = check-der.c check-common.c -check_gen_SOURCES = check-gen.c check-common.c +asn1_gen_SOURCES = asn1_gen.c +asn1_print_SOURCES = asn1_print.c +check_der_SOURCES = check-der.c check-common.c +check_gen_SOURCES = \ + check-gen.c \ + check-common.c \ + $(gen_files_test:.x=.c) asn1_compile_SOURCES = \ gen.c \ @@ -110,12 +341,14 @@ asn1_compile_SOURCES = \ symbol.c libasn1_la_SOURCES = \ + der.c \ der_get.c \ der_put.c \ der_free.c \ der_length.c \ der_copy.c \ der_cmp.c \ + extra.c \ timegm.c \ $(BUILT_SOURCES) @@ -128,22 +361,78 @@ check_der_LDADD = \ check_gen_LDADD = $(check_der_LDADD) asn1_print_LDADD = $(check_der_LDADD) +asn1_gen_LDADD = $(check_der_LDADD) -CLEANFILES = lex.c parse.c parse.h krb5_asn1.h \ +CLEANFILES = lex.c parse.c parse.h \ $(BUILT_SOURCES) \ - $(gen_files) asn1_files asn1_files2 + $(gen_files_rfc2459) \ + $(gen_files_cms) \ + $(gen_files_k5) \ + $(gen_files_pkinit) \ + $(gen_files_pkcs8) \ + $(gen_files_pkcs9) \ + $(gen_files_pkcs12) \ + $(gen_files_test) \ + rfc2459_asn1_files rfc2459_asn1.h \ + cms_asn1_files cms_asn1.h \ + krb5_asn1_files krb5_asn1.h \ + pkinit_asn1_files pkinit_asn1.h \ + pkcs8_asn1_files pkcs8_asn1.h \ + pkcs9_asn1_files pkcs9_asn1.h \ + pkcs12_asn1_files pkcs12_asn1.h \ + test_asn1_files test_asn1.h -include_HEADERS = krb5_asn1.h asn1_err.h der.h + +include_HEADERS = asn1_err.h der.h heim_asn1.h +include_HEADERS += krb5_asn1.h +include_HEADERS += pkinit_asn1.h +include_HEADERS += cms_asn1.h +include_HEADERS += rfc2459_asn1.h +include_HEADERS += pkcs8_asn1.h +include_HEADERS += pkcs9_asn1.h +include_HEADERS += pkcs12_asn1.h $(asn1_compile_OBJECTS): parse.h parse.c -$(gen_files) krb5_asn1.h: asn1_files +$(gen_files_k5) krb5_asn1.h: krb5_asn1_files +$(gen_files_pkinit) pkinit_asn1.h: pkinit_asn1_files +$(gen_files_pkcs8) pkcs8_asn1.h: pkcs8_asn1_files +$(gen_files_pkcs9) pkcs9_asn1.h: pkcs9_asn1_files +$(gen_files_pkcs12) pkcs12_asn1.h: pkcs12_asn1_files +$(gen_files_rfc2459) rfc2459_asn1.h: rfc2459_asn1_files +$(gen_files_cms) cms_asn1.h: cms_asn1_files +$(gen_files_test) test_asn1.h: test_asn1_files -asn1_files: asn1_compile$(EXEEXT) $(srcdir)/k5.asn1 - ./asn1_compile$(EXEEXT) $(srcdir)/k5.asn1 krb5_asn1 +rfc2459_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc2459.asn1 + ./asn1_compile$(EXEEXT) --preserve-binary=TBSCertificate --preserve-binary=Name $(srcdir)/rfc2459.asn1 rfc2459_asn1 || (rm -f rfc2459_asn1_files ; exit 1) + +cms_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/CMS.asn1 + ./asn1_compile$(EXEEXT) $(srcdir)/CMS.asn1 cms_asn1 || (rm -f cms_asn1_files ; exit 1) + +krb5_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/k5.asn1 + ./asn1_compile$(EXEEXT) --encode-rfc1510-bit-string $(srcdir)/k5.asn1 krb5_asn1 || (rm -f krb5_asn1_files ; exit 1) + +pkinit_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1 + ./asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1 pkinit_asn1 || (rm -f pkinit_asn1_files ; exit 1) + +pkcs8_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs8.asn1 + ./asn1_compile$(EXEEXT) $(srcdir)/pkcs8.asn1 pkcs8_asn1 || (rm -f pkcs8_asn1_files ; exit 1) + +pkcs9_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs9.asn1 + ./asn1_compile$(EXEEXT) $(srcdir)/pkcs9.asn1 pkcs9_asn1 || (rm -f pkcs9_asn1_files ; exit 1) + +pkcs12_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs12.asn1 + ./asn1_compile$(EXEEXT) $(srcdir)/pkcs12.asn1 pkcs12_asn1 || (rm -f pkcs12_asn1_files ; exit 1) + +test_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1 + ./asn1_compile$(EXEEXT) $(srcdir)/test.asn1 test_asn1 || (rm -f test_asn1_files ; exit 1) $(libasn1_la_OBJECTS): krb5_asn1.h asn1_err.h +$(check_gen_OBJECTS): test_asn1.h + $(asn1_print_OBJECTS): krb5_asn1.h +parse.h: parse.c + EXTRA_DIST = asn1_err.et diff --git a/lib/asn1/asn1-common.h b/lib/asn1/asn1-common.h index 6f08c49fe..c77c5aedf 100644 --- a/lib/asn1/asn1-common.h +++ b/lib/asn1/asn1-common.h @@ -6,6 +6,12 @@ #ifndef __asn1_common_definitions__ #define __asn1_common_definitions__ +typedef struct heim_integer { + size_t length; + void *data; + int negative; +} heim_integer; + typedef struct heim_octet_string { size_t length; void *data; @@ -13,10 +19,44 @@ typedef struct heim_octet_string { typedef char *heim_general_string; typedef char *heim_utf8_string; +typedef char *heim_printable_string; +typedef char *heim_ia5_string; + +typedef struct heim_bmp_string { + size_t length; + uint16_t *data; +} heim_bmp_string; + +typedef struct heim_universal_string { + size_t length; + uint32_t *data; +} heim_universal_string; + typedef struct heim_oid { size_t length; unsigned *components; } heim_oid; +typedef struct heim_bit_string { + size_t length; + void *data; +} heim_bit_string; + +#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \ + do { \ + (BL) = length_##T((S)); \ + (B) = malloc((BL)); \ + if((B) == NULL) { \ + (R) = ENOMEM; \ + } else { \ + (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \ + (S), (L)); \ + if((R) != 0) { \ + free((B)); \ + (B) = NULL; \ + } \ + } \ + } while (0) + #endif diff --git a/lib/asn1/asn1_gen.c b/lib/asn1/asn1_gen.c new file mode 100644 index 000000000..e184e28a8 --- /dev/null +++ b/lib/asn1/asn1_gen.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "der_locl.h" +#include +#include +#include +#include +#include +#include +#include + +RCSID("$Id$"); + +static int +doit(const char *fn) +{ + char buf[2048]; + char *fnout; + const char *bname; + unsigned long line = 0; + FILE *f, *fout; + size_t offset = 0; + + f = fopen(fn, "r"); + if (f == NULL) + err(1, "fopen"); + + bname = strrchr(fn, '/'); + if (bname) + bname++; + else + bname = fn; + + asprintf(&fnout, "%s.out", bname); + if (fnout == NULL) + errx(1, "malloc"); + + fout = fopen(fnout, "w"); + if (fout == NULL) + err(1, "fopen: output file"); + + while (fgets(buf, sizeof(buf), f) != NULL) { + char *ptr, *class, *type, *tag, *length, *data, *foo; + int ret, l, c, ty, ta; + unsigned char p[6], *pdata; + size_t sz; + + line++; + + buf[strcspn(buf, "\r\n")] = '\0'; + if (buf[0] == '#' || buf[0] == '\0') + continue; + + ptr = buf; + while (isspace((unsigned char)*ptr)) + ptr++; + + class = strtok_r(ptr, " \t\n", &foo); + if (class == NULL) errx(1, "class missing one line %lu", line); + type = strtok_r(NULL, " \t\n", &foo); + if (type == NULL) errx(1, "type missing one line %lu", line); + tag = strtok_r(NULL, " \t\n", &foo); + if (tag == NULL) errx(1, "tag missing one line %lu", line); + length = strtok_r(NULL, " \t\n", &foo); + if (length == NULL) errx(1, "length missing one line %lu", line); + data = strtok_r(NULL, " \t\n", &foo); + + c = der_get_class_num(class); + if (c == -1) errx(1, "no valid class on line %lu", line); + ty = der_get_type_num(type); + if (ty == -1) errx(1, "no valid type on line %lu", line); + ta = der_get_tag_num(tag); + if (ta == -1) + ta = atoi(tag); + + l = atoi(length); + + printf("line: %3lu offset: %3lu class: %d type: %d " + "tag: %3d length: %3d %s\n", + line, (unsigned long)offset, c, ty, ta, l, + data ? "" : ""); + + ret = der_put_length_and_tag(p + sizeof(p) - 1, sizeof(p), + l, + c, + ty, + ta, + &sz); + if (ret) + errx(1, "der_put_length_and_tag: %d", ret); + + if (fwrite(p + sizeof(p) - sz , sz, 1, fout) != 1) + err(1, "fwrite length/tag failed"); + offset += sz; + + if (data) { + size_t datalen; + + datalen = strlen(data) / 2; + pdata = emalloc(sz); + + if (hex_decode(data, pdata, datalen) != datalen) + errx(1, "failed to decode data"); + + if (fwrite(pdata, datalen, 1, fout) != 1) + err(1, "fwrite data failed"); + offset += datalen; + + free(pdata); + } + } + printf("line: eof offset: %lu\n", (unsigned long)offset); + + fclose(fout); + fclose(f); + return 0; +} + + +static int version_flag; +static int help_flag; +struct getargs args[] = { + { "version", 0, arg_flag, &version_flag }, + { "help", 0, arg_flag, &help_flag } +}; +int num_args = sizeof(args) / sizeof(args[0]); + +static void +usage(int code) +{ + arg_printusage(args, num_args, NULL, "parse-file"); + exit(code); +} + +int +main(int argc, char **argv) +{ + int optind = 0; + + setprogname (argv[0]); + + if(getarg(args, num_args, argc, argv, &optind)) + usage(1); + if(help_flag) + usage(0); + if(version_flag) { + print_version(NULL); + exit(0); + } + argv += optind; + argc -= optind; + if (argc != 1) + usage (1); + + return doit (argv[0]); +} diff --git a/lib/asn1/asn1_print.c b/lib/asn1/asn1_print.c index e65d56c88..cdfee813d 100644 --- a/lib/asn1/asn1_print.c +++ b/lib/asn1/asn1_print.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -37,55 +37,20 @@ #include #include #include +#include RCSID("$Id$"); -const char *class_names[] = { - "UNIV", /* 0 */ - "APPL", /* 1 */ - "CONTEXT", /* 2 */ - "PRIVATE" /* 3 */ -}; +static int indent_flag = 1; -const char *type_names[] = { - "PRIM", /* 0 */ - "CONS" /* 1 */ -}; +static unsigned long indefinite_form_loop; +static unsigned long indefinite_form_loop_max = 10000; -const char *tag_names[] = { - NULL, /* 0 */ - NULL, /* 1 */ - "Integer", /* 2 */ - "BitString", /* 3 */ - "OctetString", /* 4 */ - "Null", /* 5 */ - "ObjectID", /* 6 */ - NULL, /* 7 */ - NULL, /* 8 */ - NULL, /* 9 */ - "Enumerated", /* 10 */ - NULL, /* 11 */ - NULL, /* 12 */ - NULL, /* 13 */ - NULL, /* 14 */ - NULL, /* 15 */ - "Sequence", /* 16 */ - "Set", /* 17 */ - NULL, /* 18 */ - "PrintableString", /* 19 */ - NULL, /* 20 */ - NULL, /* 21 */ - "IA5String", /* 22 */ - "UTCTime", /* 23 */ - "GeneralizedTime", /* 24 */ - NULL, /* 25 */ - "VisibleString", /* 26 */ - "GeneralString" /* 27 */ -}; - -static int +static size_t loop (unsigned char *buf, size_t len, int indent) { + unsigned char *start_buf = buf; + while (len > 0) { int ret; Der_class class; @@ -93,7 +58,9 @@ loop (unsigned char *buf, size_t len, int indent) int tag; size_t sz; size_t length; - int i; + size_t loop_length = 0; + int end_tag = 0; + const char *tagname; ret = der_get_tag (buf, len, &class, &type, &tag, &sz); if (ret) @@ -103,62 +70,99 @@ loop (unsigned char *buf, size_t len, int indent) (unsigned)sz, (unsigned)len); buf += sz; len -= sz; - for (i = 0; i < indent; ++i) - printf (" "); - printf ("%s %s ", class_names[class], type_names[type]); - if (tag_names[tag]) - printf ("%s = ", tag_names[tag]); + if (indent_flag) { + int i; + for (i = 0; i < indent; ++i) + printf (" "); + } + printf ("%s %s ", der_get_class_name(class), der_get_type_name(type)); + tagname = der_get_tag_name(tag); + if (class == ASN1_C_UNIV && tagname != NULL) + printf ("%s = ", tagname); else printf ("tag %d = ", tag); ret = der_get_length (buf, len, &length, &sz); if (ret) errx (1, "der_get_tag: %s", error_message (ret)); + if (sz > len) + errx (1, "unreasonable tag length (%u) > %u", + (unsigned)sz, (unsigned)len); buf += sz; len -= sz; - - if (class == ASN1_C_CONTEXT) { - printf ("[%d]\n", tag); - loop (buf, length, indent); + if (length == ASN1_INDEFINITE) { + if ((class == ASN1_C_UNIV && type == PRIM && tag == UT_OctetString) || + (class == ASN1_C_CONTEXT && type == CONS) || + (class == ASN1_C_UNIV && type == CONS && tag == UT_Sequence) || + (class == ASN1_C_UNIV && type == CONS && tag == UT_Set)) { + printf("*INDEFINITE FORM*"); + } else { + fflush(stdout); + errx(1, "indef form used on unsupported object"); + } + end_tag = 1; + if (indefinite_form_loop > indefinite_form_loop_max) + errx(1, "indefinite form used recursively more then %lu " + "times, aborting", indefinite_form_loop_max); + indefinite_form_loop++; + length = len; + } else if (length > len) { + printf("\n"); + fflush(stdout); + errx (1, "unreasonable inner length (%u) > %u", + (unsigned)length, (unsigned)len); + } + if (class == ASN1_C_CONTEXT || class == ASN1_C_APPL) { + printf ("%d bytes [%d]\n", length, tag); + if (type == CONS) + loop_length = loop (buf, length, indent + 2); } else if (class == ASN1_C_UNIV) { switch (tag) { + case UT_EndOfContent: + printf (" INDEFINITE length was %lu\n", + (unsigned long)(buf - start_buf)); + break; + case UT_Set : case UT_Sequence : - printf ("{\n"); - loop (buf, length, indent + 2); - for (i = 0; i < indent; ++i) - printf (" "); - printf ("}\n"); + printf ("%lu bytes {\n", (unsigned long)length); + loop_length = loop (buf, length, indent + 2); + if (indent_flag) { + int i; + for (i = 0; i < indent; ++i) + printf (" "); + printf ("}\n"); + } else + printf ("} indent = %d\n", indent / 2); break; case UT_Integer : { int val; - ret = der_get_int (buf, length, &val, NULL); - if (ret) - errx (1, "der_get_int: %s", error_message (ret)); - printf ("integer %d\n", val); + if (length <= sizeof(val)) { + ret = der_get_integer (buf, length, &val, NULL); + if (ret) + errx (1, "der_get_integer: %s", error_message (ret)); + printf ("integer %d\n", val); + } else { + printf ("BIG NUM integer: length %d\n", length); + } break; } case UT_OctetString : { heim_octet_string str; + int i; unsigned char *uc; ret = der_get_octet_string (buf, length, &str, NULL); if (ret) errx (1, "der_get_octet_string: %s", error_message (ret)); - printf ("(length %lu)%s", (unsigned long)str.length, - str.length > 0 ? ", " : ""); + printf ("(length %lu), ", (unsigned long)length); uc = (unsigned char *)str.data; - length = str.length; - if (length > 16) - length = 16; - for (i = 0; i < length; ++i) + for (i = 0; i < min(16,length); ++i) printf ("%02x", uc[i]); printf ("\n"); free (str.data); break; } case UT_GeneralizedTime : - case UT_IA5String: - case UT_UTF8String : case UT_GeneralString : { heim_general_string str; @@ -172,6 +176,7 @@ loop (unsigned char *buf, size_t len, int indent) } case UT_OID: { heim_oid o; + int i; ret = der_get_oid(buf, length, &o, NULL); if (ret) @@ -185,9 +190,9 @@ loop (unsigned char *buf, size_t len, int indent) break; } case UT_Enumerated: { - unsigned num; + int num; - ret = der_get_int (buf, length, &num, NULL); + ret = der_get_integer (buf, length, &num, NULL); if (ret) errx (1, "der_get_enum: %s", error_message (ret)); @@ -199,6 +204,17 @@ loop (unsigned char *buf, size_t len, int indent) break; } } + if (end_tag) { + if (loop_length == 0) + errx(1, "zero length INDEFINITE data ? indent = %d\n", + indent / 2); + if (loop_length < length) + length = loop_length; + if (indefinite_form_loop == 0) + errx(1, "internal error in indefinite form loop detection"); + indefinite_form_loop--; + } else if (loop_length) + errx(1, "internal error for INDEFINITE form"); buf += length; len -= length; } @@ -219,21 +235,20 @@ doit (const char *filename) if (fstat (fd, &sb) < 0) err (1, "stat %s", filename); len = sb.st_size; - buf = malloc (len); - if (buf == NULL) - err (1, "malloc %u", (unsigned)len); + buf = emalloc (len); if (read (fd, buf, len) != len) errx (1, "read failed"); close (fd); ret = loop (buf, len, 0); free (buf); - return ret; + return 0; } static int version_flag; static int help_flag; struct getargs args[] = { + { "indent", 0, arg_negative_flag, &indent_flag }, { "version", 0, arg_flag, &version_flag }, { "help", 0, arg_flag, &help_flag } }; @@ -249,11 +264,11 @@ usage(int code) int main(int argc, char **argv) { - int optidx = 0; + int optind = 0; setprogname (argv[0]); initialize_asn1_error_table (); - if(getarg(args, num_args, argc, argv, &optidx)) + if(getarg(args, num_args, argc, argv, &optind)) usage(1); if(help_flag) usage(0); @@ -261,8 +276,8 @@ main(int argc, char **argv) print_version(NULL); exit(0); } - argv += optidx; - argc -= optidx; + argv += optind; + argc -= optind; if (argc != 1) usage (1); return doit (argv[0]); diff --git a/lib/asn1/asn1_queue.h b/lib/asn1/asn1_queue.h new file mode 100644 index 000000000..73eb50f8b --- /dev/null +++ b/lib/asn1/asn1_queue.h @@ -0,0 +1,167 @@ +/* $NetBSD: queue.h,v 1.38 2004/04/18 14:12:05 lukem Exp $ */ +/* $Id$ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _ASN1_QUEUE_H_ +#define _ASN1_QUEUE_H_ + +/* + * Tail queue definitions. + */ +#define ASN1_TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define ASN1_TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } +#define ASN1_TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * Tail queue functions. + */ +#if defined(_KERNEL) && defined(QUEUEDEBUG) +#define QUEUEDEBUG_ASN1_TAILQ_INSERT_HEAD(head, elm, field) \ + if ((head)->tqh_first && \ + (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \ + panic("ASN1_TAILQ_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__); +#define QUEUEDEBUG_ASN1_TAILQ_INSERT_TAIL(head, elm, field) \ + if (*(head)->tqh_last != NULL) \ + panic("ASN1_TAILQ_INSERT_TAIL %p %s:%d", (head), __FILE__, __LINE__); +#define QUEUEDEBUG_ASN1_TAILQ_OP(elm, field) \ + if ((elm)->field.tqe_next && \ + (elm)->field.tqe_next->field.tqe_prev != \ + &(elm)->field.tqe_next) \ + panic("ASN1_TAILQ_* forw %p %s:%d", (elm), __FILE__, __LINE__);\ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("ASN1_TAILQ_* back %p %s:%d", (elm), __FILE__, __LINE__); +#define QUEUEDEBUG_ASN1_TAILQ_PREREMOVE(head, elm, field) \ + if ((elm)->field.tqe_next == NULL && \ + (head)->tqh_last != &(elm)->field.tqe_next) \ + panic("ASN1_TAILQ_PREREMOVE head %p elm %p %s:%d", \ + (head), (elm), __FILE__, __LINE__); +#define QUEUEDEBUG_ASN1_TAILQ_POSTREMOVE(elm, field) \ + (elm)->field.tqe_next = (void *)1L; \ + (elm)->field.tqe_prev = (void *)1L; +#else +#define QUEUEDEBUG_ASN1_TAILQ_INSERT_HEAD(head, elm, field) +#define QUEUEDEBUG_ASN1_TAILQ_INSERT_TAIL(head, elm, field) +#define QUEUEDEBUG_ASN1_TAILQ_OP(elm, field) +#define QUEUEDEBUG_ASN1_TAILQ_PREREMOVE(head, elm, field) +#define QUEUEDEBUG_ASN1_TAILQ_POSTREMOVE(elm, field) +#endif + +#define ASN1_TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define ASN1_TAILQ_INSERT_HEAD(head, elm, field) do { \ + QUEUEDEBUG_ASN1_TAILQ_INSERT_HEAD((head), (elm), field) \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define ASN1_TAILQ_INSERT_TAIL(head, elm, field) do { \ + QUEUEDEBUG_ASN1_TAILQ_INSERT_TAIL((head), (elm), field) \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define ASN1_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QUEUEDEBUG_ASN1_TAILQ_OP((listelm), field) \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define ASN1_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QUEUEDEBUG_ASN1_TAILQ_OP((listelm), field) \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define ASN1_TAILQ_REMOVE(head, elm, field) do { \ + QUEUEDEBUG_ASN1_TAILQ_PREREMOVE((head), (elm), field) \ + QUEUEDEBUG_ASN1_TAILQ_OP((elm), field) \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + QUEUEDEBUG_ASN1_TAILQ_POSTREMOVE((elm), field); \ +} while (/*CONSTCOND*/0) + +#define ASN1_TAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->tqh_first); \ + (var); \ + (var) = ((var)->field.tqe_next)) + +#define ASN1_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ + (var); \ + (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) + +/* + * Tail queue access methods. + */ +#define ASN1_TAILQ_EMPTY(head) ((head)->tqh_first == NULL) +#define ASN1_TAILQ_FIRST(head) ((head)->tqh_first) +#define ASN1_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define ASN1_TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +#define ASN1_TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + + +#endif /* !_ASN1_QUEUE_H_ */ diff --git a/lib/asn1/canthandle.asn1 b/lib/asn1/canthandle.asn1 new file mode 100644 index 000000000..abb83de2f --- /dev/null +++ b/lib/asn1/canthandle.asn1 @@ -0,0 +1,30 @@ +-- $Id$ -- + +CANTHANDLE DEFINITIONS ::= BEGIN + +-- Don't code the tag [0] as a constructed tag for foo.kaka1, +-- it should be PRIM (and no type field) +-- Workaround is to use heim_any and decode type + +Kaka ::= SEQUENCE { + kaka3 [0] INTEGER +} + +Foo ::= SEQUENCE { + kaka1 [0] IMPLICIT INTEGER OPTIONAL, + kaka2 [1] IMPLICIT Kaka OPTIONAL +} + +-- Don't code kaka if its 1 +-- Workaround is to use OPTIONAL and check for in the encoder stubs + +Bar ::= SEQUENCE { + kaka [0] INTEGER DEFAULT 1 +} + +-- Can't handle primitives in SET OF +-- Workaround is to define a type that is only an integer and use that + +Baz ::= SET OF INTEGER + +END diff --git a/lib/asn1/check-common.c b/lib/asn1/check-common.c index 8864fe532..fddfacaaa 100644 --- a/lib/asn1/check-common.c +++ b/lib/asn1/check-common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan + * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -34,6 +34,9 @@ #ifdef HAVE_CONFIG_H #include #endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif #include #include #include @@ -43,6 +46,107 @@ RCSID("$Id$"); +struct map_page { + void *start; + size_t size; + void *data_start; + size_t data_size; + enum map_type type; +}; + +/* #undef HAVE_MMAP */ + +void * +map_alloc(enum map_type type, const void *buf, + size_t size, struct map_page **map) +{ +#ifndef HAVE_MMAP + unsigned char *p; + + *map = ecalloc(1, sizeof(**map)); + + p = emalloc(size + 2); + (*map)->type = type; + (*map)->start = p; + (*map)->size = size + 2; + p[0] = 0xff; + p[(*map)->size] = 0xff; + (*map)->data_start = p + 1; +#else + unsigned char *p; + int flags, ret, fd; + size_t pagesize = getpagesize(); + + *map = ecalloc(1, sizeof(**map)); + + (*map)->type = type; + +#ifdef MAP_ANON + flags = MAP_ANON; + fd = -1; +#else + flags = 0; + fd = open ("/dev/zero", O_RDONLY); + if(fd < 0) + err (1, "open /dev/zero"); +#endif + flags |= MAP_PRIVATE; + + (*map)->size = size + pagesize - (size % pagesize) + pagesize * 2; + + p = (char *)mmap(0, (*map)->size, PROT_READ | PROT_WRITE, + flags, fd, 0); + if (p == (unsigned char *)MAP_FAILED) + err (1, "mmap"); + + (*map)->start = p; + + ret = mprotect (p, pagesize, 0); + if (ret < 0) + err (1, "mprotect"); + + ret = mprotect (p + (*map)->size - pagesize, pagesize, 0); + if (ret < 0) + err (1, "mprotect"); + + switch (type) { + case OVERRUN: + (*map)->data_start = p + (*map)->size - pagesize - size; + break; + case UNDERRUN: + (*map)->data_start = p + pagesize; + break; + default: + abort(); + } +#endif + (*map)->data_size = size; + if (buf) + memcpy((*map)->data_start, buf, size); + return (*map)->data_start; +} + +void +map_free(struct map_page *map, const char *test_name, const char *map_name) +{ +#ifndef HAVE_MMAP + unsigned char *p = map->start; + + if (p[0] != 0xff) + errx(1, "%s: %s underrun %x\n", test_name, map_name, p[0]); + if (p[map->size] != 0xff) + errx(1, "%s: %s overrun %x\n", test_name, map_name, p[map->size - 1]); + free(map->start); +#else + int ret; + + ret = munmap (map->start, map->size); + if (ret < 0) + err (1, "munmap"); +#endif + free(map); +} + static void print_bytes (unsigned const char *buf, size_t len) { @@ -52,6 +156,31 @@ print_bytes (unsigned const char *buf, size_t len) printf ("%02x ", buf[i]); } +#ifndef MAP_FAILED +#define MAP_FAILED (-1) +#endif + +static char *current_test = ""; +static char *current_state = ""; + +static RETSIGTYPE +segv_handler(int sig) +{ + int fd; + char msg[] = "SIGSEGV i current test: "; + + fd = open("/dev/stdout", O_WRONLY, 0600); + if (fd >= 0) { + write(fd, msg, sizeof(msg)); + write(fd, current_test, strlen(current_test)); + write(fd, " ", 1); + write(fd, current_state, strlen(current_state)); + write(fd, "\n", 1); + close(fd); + } + _exit(1); +} + int generic_test (const struct test_case *tests, unsigned ntests, @@ -59,67 +188,181 @@ generic_test (const struct test_case *tests, int (*encode)(unsigned char *, size_t, void *, size_t *), int (*length)(void *), int (*decode)(unsigned char *, size_t, void *, size_t *), + int (*free_data)(void *), int (*cmp)(void *a, void *b)) { - unsigned char buf[4711]; + unsigned char *buf, *buf2; int i; int failures = 0; - void *val = malloc (data_size); + void *data; + struct map_page *data_map, *buf_map, *buf2_map; - if (data_size != 0 && val == NULL) - err (1, "malloc"); + struct sigaction sa, osa; for (i = 0; i < ntests; ++i) { int ret; - size_t sz, consumed_sz, length_sz; - unsigned char *beg; + size_t sz, consumed_sz, length_sz, buf_sz; - ret = (*encode) (buf + sizeof(buf) - 1, sizeof(buf), + current_test = tests[i].name; + + current_state = "init"; + + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; +#ifdef SA_RESETHAND + sa.sa_flags |= SA_RESETHAND; +#endif + sa.sa_handler = segv_handler; + sigaction (SIGSEGV, &sa, &osa); + + data = map_alloc(OVERRUN, NULL, data_size, &data_map); + + buf_sz = tests[i].byte_len; + buf = map_alloc(UNDERRUN, NULL, buf_sz, &buf_map); + + current_state = "encode"; + ret = (*encode) (buf + buf_sz - 1, buf_sz, tests[i].val, &sz); - beg = buf + sizeof(buf) - sz; if (ret != 0) { - printf ("encoding of %s failed\n", tests[i].name); + printf ("encoding of %s failed %d\n", tests[i].name, ret); ++failures; + continue; } if (sz != tests[i].byte_len) { printf ("encoding of %s has wrong len (%lu != %lu)\n", tests[i].name, (unsigned long)sz, (unsigned long)tests[i].byte_len); ++failures; + continue; } + current_state = "length"; length_sz = (*length) (tests[i].val); if (sz != length_sz) { printf ("length for %s is bad (%lu != %lu)\n", tests[i].name, (unsigned long)length_sz, (unsigned long)sz); ++failures; + continue; } - if (memcmp (beg, tests[i].bytes, tests[i].byte_len) != 0) { + current_state = "memcmp"; + if (memcmp (buf, tests[i].bytes, tests[i].byte_len) != 0) { printf ("encoding of %s has bad bytes:\n" "correct: ", tests[i].name); print_bytes (tests[i].bytes, tests[i].byte_len); printf ("\nactual: "); - print_bytes (beg, sz); + print_bytes (buf, sz); printf ("\n"); ++failures; + continue; } - ret = (*decode) (beg, sz, val, &consumed_sz); + + buf2 = map_alloc(OVERRUN, buf, sz, &buf2_map); + + current_state = "decode"; + ret = (*decode) (buf2, sz, data, &consumed_sz); if (ret != 0) { - printf ("decoding of %s failed\n", tests[i].name); + printf ("decoding of %s failed %d\n", tests[i].name, ret); ++failures; + continue; } if (sz != consumed_sz) { printf ("different length decoding %s (%ld != %ld)\n", tests[i].name, (unsigned long)sz, (unsigned long)consumed_sz); ++failures; + continue; } - if ((*cmp)(val, tests[i].val) != 0) { + current_state = "cmp"; + if ((*cmp)(data, tests[i].val) != 0) { printf ("%s: comparison failed\n", tests[i].name); ++failures; + continue; } + current_state = "free"; + if (free_data) + (*free_data)(data); + + current_state = "free"; + map_free(buf_map, tests[i].name, "encode"); + map_free(buf2_map, tests[i].name, "decode"); + map_free(data_map, tests[i].name, "data"); + + sigaction (SIGSEGV, &osa, NULL); } - free (val); + current_state = "done"; + return failures; +} + +/* + * check for failures + * + * a test size (byte_len) of -1 means that the test tries to trigger a + * integer overflow (and later a malloc of to little memory), just + * allocate some memory and hope that is enough for that test. + */ + +int +generic_decode_fail (const struct test_case *tests, + unsigned ntests, + size_t data_size, + int (*decode)(unsigned char *, size_t, void *, size_t *)) +{ + unsigned char *buf; + int i; + int failures = 0; + void *data; + struct map_page *data_map, *buf_map; + + struct sigaction sa, osa; + + for (i = 0; i < ntests; ++i) { + int ret; + size_t sz; + const void *bytes; + + current_test = tests[i].name; + + current_state = "init"; + + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; +#ifdef SA_RESETHAND + sa.sa_flags |= SA_RESETHAND; +#endif + sa.sa_handler = segv_handler; + sigaction (SIGSEGV, &sa, &osa); + + data = map_alloc(OVERRUN, NULL, data_size, &data_map); + + if (tests[i].byte_len != -1) { + sz = tests[i].byte_len; + bytes = tests[i].bytes; + } else { + sz = 4096; + bytes = NULL; + } + + buf = map_alloc(OVERRUN, bytes, sz, &buf_map); + + if (tests[i].byte_len == -1) + memset(buf, 0, sz); + + current_state = "decode"; + ret = (*decode) (buf, tests[i].byte_len, data, &sz); + if (ret == 0) { + printf ("sucessfully decoded %s\n", tests[i].name); + ++failures; + continue; + } + + current_state = "free"; + if (buf) + map_free(buf_map, tests[i].name, "encode"); + map_free(data_map, tests[i].name, "data"); + + sigaction (SIGSEGV, &osa, NULL); + } + current_state = "done"; return failures; } diff --git a/lib/asn1/check-common.h b/lib/asn1/check-common.h index 52d59cb4f..8b772b3d0 100644 --- a/lib/asn1/check-common.h +++ b/lib/asn1/check-common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan + * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -41,6 +41,7 @@ struct test_case { typedef int (*generic_encode)(unsigned char *, size_t, void *, size_t *); typedef int (*generic_length)(void *); typedef int (*generic_decode)(unsigned char *, size_t, void *, size_t *); +typedef int (*generic_free)(void *); int generic_test (const struct test_case *tests, @@ -49,5 +50,21 @@ generic_test (const struct test_case *tests, int (*encode)(unsigned char *, size_t, void *, size_t *), int (*length)(void *), int (*decode)(unsigned char *, size_t, void *, size_t *), + int (*free_data)(void *), int (*cmp)(void *a, void *b)); +int +generic_decode_fail(const struct test_case *tests, + unsigned ntests, + size_t data_size, + int (*decode)(unsigned char *, size_t, void *, size_t *)); + + +struct map_page; + +enum map_type { OVERRUN, UNDERRUN }; + +struct map_page; + +void * map_alloc(enum map_type, const void *, size_t, struct map_page **); +void map_free(struct map_page *, const char *, const char *); diff --git a/lib/asn1/check-der.c b/lib/asn1/check-der.c index 8e825a422..562169ad7 100644 --- a/lib/asn1/check-der.c +++ b/lib/asn1/check-der.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan + * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -56,17 +56,17 @@ static int test_integer (void) { struct test_case tests[] = { - {NULL, 3, "\x02\x01\x00"}, - {NULL, 3, "\x02\x01\x7f"}, - {NULL, 4, "\x02\x02\x00\x80"}, - {NULL, 4, "\x02\x02\x01\x00"}, - {NULL, 3, "\x02\x01\x80"}, - {NULL, 4, "\x02\x02\xff\x7f"}, - {NULL, 3, "\x02\x01\xff"}, - {NULL, 4, "\x02\x02\xff\x01"}, - {NULL, 4, "\x02\x02\x00\xff"}, - {NULL, 6, "\x02\x04\x80\x00\x00\x00"}, - {NULL, 6, "\x02\x04\x7f\xff\xff\xff"} + {NULL, 1, "\x00"}, + {NULL, 1, "\x7f"}, + {NULL, 2, "\x00\x80"}, + {NULL, 2, "\x01\x00"}, + {NULL, 1, "\x80"}, + {NULL, 2, "\xff\x7f"}, + {NULL, 1, "\xff"}, + {NULL, 2, "\xff\x01"}, + {NULL, 2, "\x00\xff"}, + {NULL, 4, "\x80\x00\x00\x00"}, + {NULL, 4, "\x7f\xff\xff\xff"} }; int values[] = {0, 127, 128, 256, -128, -129, -1, -255, 255, @@ -77,21 +77,23 @@ test_integer (void) for (i = 0; i < ntests; ++i) { tests[i].val = &values[i]; asprintf (&tests[i].name, "integer %d", values[i]); + if (tests[i].name == NULL) + errx(1, "malloc"); } return generic_test (tests, ntests, sizeof(int), - (generic_encode)encode_integer, + (generic_encode)der_put_integer, (generic_length) length_integer, - (generic_decode)decode_integer, + (generic_decode)der_get_integer, + (generic_free)NULL, cmp_integer); } static int test_one_int(int val) { - int ret, dval; + int len, ret, len_len, dval; unsigned char *buf; - size_t len_len, len; len = _heim_len_int(val); @@ -101,25 +103,25 @@ test_one_int(int val) buf[len + 1] = '\xff'; memset(buf + 1, 0, len); - ret = der_put_int(buf + 1 + len - 1, len, val, &len_len); + ret = der_put_integer(buf + 1 + len - 1, len, &val, &len_len); if (ret) { printf("integer %d encode failed %d\n", val, ret); return 1; } if (len != len_len) { - printf("integer %d encode fail with %d len %lu, result len %lu\n", - val, ret, (unsigned long)len, (unsigned long)len_len); + printf("integer %d encode fail with %d len %d, result len %d\n", + val, ret, len, len_len); return 1; } - ret = der_get_int(buf + 1, len, &dval, &len_len); + ret = der_get_integer(buf + 1, len, &dval, &len_len); if (ret) { printf("integer %d decode failed %d\n", val, ret); return 1; } if (len != len_len) { - printf("integer %d decoded diffrent len %lu != %lu", - val, (unsigned long)len, (unsigned long)len_len); + printf("integer %d decoded diffrent len %d != %d", + val, len, len_len); return 1; } if (val != dval) { @@ -174,14 +176,14 @@ static int test_unsigned (void) { struct test_case tests[] = { - {NULL, 3, "\x02\x01\x00"}, - {NULL, 3, "\x02\x01\x7f"}, - {NULL, 4, "\x02\x02\x00\x80"}, - {NULL, 4, "\x02\x02\x01\x00"}, - {NULL, 4, "\x02\x02\x02\x00"}, - {NULL, 5, "\x02\x03\x00\x80\x00"}, - {NULL, 7, "\x02\x05\x00\x80\x00\x00\x00"}, - {NULL, 6, "\x02\x04\x7f\xff\xff\xff"} + {NULL, 1, "\x00"}, + {NULL, 1, "\x7f"}, + {NULL, 2, "\x00\x80"}, + {NULL, 2, "\x01\x00"}, + {NULL, 2, "\x02\x00"}, + {NULL, 3, "\x00\x80\x00"}, + {NULL, 5, "\x00\x80\x00\x00\x00"}, + {NULL, 4, "\x7f\xff\xff\xff"} }; unsigned int values[] = {0, 127, 128, 256, 512, 32768, @@ -192,12 +194,15 @@ test_unsigned (void) for (i = 0; i < ntests; ++i) { tests[i].val = &values[i]; asprintf (&tests[i].name, "unsigned %u", values[i]); + if (tests[i].name == NULL) + errx(1, "malloc"); } return generic_test (tests, ntests, sizeof(int), - (generic_encode)encode_unsigned, - (generic_length) length_unsigned, - (generic_decode)decode_unsigned, + (generic_encode)der_put_unsigned, + (generic_length)length_unsigned, + (generic_decode)der_get_unsigned, + (generic_free)NULL, cmp_unsigned); } @@ -219,20 +224,63 @@ test_octet_string (void) heim_octet_string s1 = {8, "\x01\x23\x45\x67\x89\xab\xcd\xef"}; struct test_case tests[] = { - {NULL, 10, "\x04\x08\x01\x23\x45\x67\x89\xab\xcd\xef"} + {NULL, 8, "\x01\x23\x45\x67\x89\xab\xcd\xef"} }; int ntests = sizeof(tests) / sizeof(*tests); tests[0].val = &s1; asprintf (&tests[0].name, "a octet string"); + if (tests[0].name == NULL) + errx(1, "malloc"); return generic_test (tests, ntests, sizeof(heim_octet_string), - (generic_encode)encode_octet_string, + (generic_encode)der_put_octet_string, (generic_length)length_octet_string, - (generic_decode)decode_octet_string, + (generic_decode)der_get_octet_string, + (generic_free)free_octet_string, cmp_octet_string); } +static int +cmp_bmp_string (void *a, void *b) +{ + heim_bmp_string *oa = (heim_bmp_string *)a; + heim_bmp_string *ob = (heim_bmp_string *)b; + + return heim_bmp_string_cmp(oa, ob); +} + +static int +test_bmp_string (void) +{ + uint16_t d1[] = { 32 }; + heim_bmp_string s1 = { 1, d1 }; + uint16_t d2[] = { 32, 32 }; + heim_bmp_string s2 = { 2, d2 }; + + struct test_case tests[] = { + {NULL, 2, "\x00\x20"}, + {NULL, 4, "\x00\x20\x00\x20"} + }; + int ntests = sizeof(tests) / sizeof(*tests); + + tests[0].val = &s1; + asprintf (&tests[0].name, "a bmp string"); + if (tests[0].name == NULL) + errx(1, "malloc"); + tests[1].val = &s2; + asprintf (&tests[1].name, "second bmp string"); + if (tests[1].name == NULL) + errx(1, "malloc"); + + return generic_test (tests, ntests, sizeof(heim_bmp_string), + (generic_encode)der_put_bmp_string, + (generic_length)length_bmp_string, + (generic_decode)der_get_bmp_string, + (generic_free)free_bmp_string, + cmp_bmp_string); +} + static int cmp_general_string (void *a, void *b) { @@ -248,17 +296,20 @@ test_general_string (void) unsigned char *s1 = "Test User 1"; struct test_case tests[] = { - {NULL, 13, "\x1b\x0b\x54\x65\x73\x74\x20\x55\x73\x65\x72\x20\x31"} + {NULL, 11, "\x54\x65\x73\x74\x20\x55\x73\x65\x72\x20\x31"} }; int ntests = sizeof(tests) / sizeof(*tests); tests[0].val = &s1; asprintf (&tests[0].name, "the string \"%s\"", s1); + if (tests[0].name == NULL) + errx(1, "malloc"); return generic_test (tests, ntests, sizeof(unsigned char *), - (generic_encode)encode_general_string, + (generic_encode)der_put_general_string, (generic_length)length_general_string, - (generic_decode)decode_general_string, + (generic_decode)der_get_general_string, + (generic_free)free_general_string, cmp_general_string); } @@ -275,8 +326,8 @@ static int test_generalized_time (void) { struct test_case tests[] = { - {NULL, 17, "\x18\x0f""19700101000000Z"}, - {NULL, 17, "\x18\x0f""19851106210627Z"} + {NULL, 15, "19700101000000Z"}, + {NULL, 15, "19851106210627Z"} }; time_t values[] = {0, 500159187}; int i; @@ -285,15 +336,211 @@ test_generalized_time (void) for (i = 0; i < ntests; ++i) { tests[i].val = &values[i]; asprintf (&tests[i].name, "time %d", (int)values[i]); + if (tests[i].name == NULL) + errx(1, "malloc"); } return generic_test (tests, ntests, sizeof(time_t), - (generic_encode)encode_generalized_time, + (generic_encode)der_put_generalized_time, (generic_length)length_generalized_time, - (generic_decode)decode_generalized_time, + (generic_decode)der_get_generalized_time, + (generic_free)NULL, cmp_generalized_time); } +static int +test_cmp_oid (void *a, void *b) +{ + return heim_oid_cmp((heim_oid *)a, (heim_oid *)b); +} + +static int +test_oid (void) +{ + struct test_case tests[] = { + {NULL, 2, "\x29\x01"}, + {NULL, 1, "\x29"}, + {NULL, 2, "\xff\x01"}, + {NULL, 1, "\xff"} + }; + unsigned oid_comp1[] = { 1, 1, 1 }; + unsigned oid_comp2[] = { 1, 1 }; + unsigned oid_comp3[] = { 6, 15, 1 }; + unsigned oid_comp4[] = { 6, 15 }; + heim_oid values[] = { + { 3, oid_comp1 }, + { 2, oid_comp2 }, + { 3, oid_comp3 }, + { 2, oid_comp4 } + }; + int i; + int ntests = sizeof(tests) / sizeof(*tests); + + for (i = 0; i < ntests; ++i) { + tests[i].val = &values[i]; + asprintf (&tests[i].name, "oid %d", i); + if (tests[i].name == NULL) + errx(1, "malloc"); + } + + return generic_test (tests, ntests, sizeof(heim_oid), + (generic_encode)der_put_oid, + (generic_length)length_oid, + (generic_decode)der_get_oid, + (generic_free)free_oid, + test_cmp_oid); +} + +static int +check_fail_unsigned(void) +{ + struct test_case tests[] = { + {NULL, sizeof(unsigned) + 1, + "\x01\x01\x01\x01\x01\x01\x01\x01\x01", "data overrun" } + }; + int ntests = sizeof(tests) / sizeof(*tests); + + return generic_decode_fail(tests, ntests, sizeof(unsigned), + (generic_decode)der_get_unsigned); +} + +static int +check_fail_integer(void) +{ + struct test_case tests[] = { + {NULL, sizeof(int) + 1, + "\x01\x01\x01\x01\x01\x01\x01\x01\x01", "data overrun" } + }; + int ntests = sizeof(tests) / sizeof(*tests); + + return generic_decode_fail(tests, ntests, sizeof(int), + (generic_decode)der_get_integer); +} + +static int +check_fail_length(void) +{ + struct test_case tests[] = { + {NULL, 0, "", "empty input data"}, + {NULL, 1, "\x82", "internal length overrun" } + }; + int ntests = sizeof(tests) / sizeof(*tests); + + return generic_decode_fail(tests, ntests, sizeof(size_t), + (generic_decode)der_get_length); +} + +static int +check_fail_boolean(void) +{ + struct test_case tests[] = { + {NULL, 0, "", "empty input data"} + }; + int ntests = sizeof(tests) / sizeof(*tests); + + return generic_decode_fail(tests, ntests, sizeof(int), + (generic_decode)der_get_boolean); +} + +static int +check_fail_general_string(void) +{ + struct test_case tests[] = { + {NULL, -1, "", "over sized buffer"} + }; + int ntests = sizeof(tests) / sizeof(*tests); + + return generic_decode_fail(tests, ntests, sizeof(heim_general_string), + (generic_decode)der_get_general_string); +} + +static int +check_fail_bmp_string(void) +{ + struct test_case tests[] = { + {NULL, 1, "\x00", "odd length bmpstring"}, + {NULL, -1, "\x00", "over sized data"} + }; + int ntests = sizeof(tests) / sizeof(*tests); + + return generic_decode_fail(tests, ntests, sizeof(heim_bmp_string), + (generic_decode)der_get_bmp_string); +} + +static int +check_fail_universal_string(void) +{ + struct test_case tests[] = { + {NULL, 1, "\x00", "x & 3 == 1 universal string"}, + {NULL, 2, "\x00\x00", "x & 3 == 2 universal string"}, + {NULL, 3, "\x00\x00\x00", "x & 3 == 3 universal string"}, + {NULL, 5, "\x00\x00\x00\x00\x00", "x & 3 == 1 universal string"}, + {NULL, 6, "\x00\x00\x00\x00\x00\x00", "x & 3 == 2 universal string"}, + {NULL, 7, "\x00\x00\x00\x00\x00\x00\x00", "x & 3 == 3 universal string"}, + {NULL, -1, "\x00", "over sized data"} + }; + int ntests = sizeof(tests) / sizeof(*tests); + + return generic_decode_fail(tests, ntests, sizeof(heim_universal_string), + (generic_decode)der_get_universal_string); +} + +static int +check_fail_heim_integer(void) +{ + struct test_case tests[] = { + {NULL, -1, "\x00", "over sized data"} + }; + int ntests = sizeof(tests) / sizeof(*tests); + + return generic_decode_fail(tests, ntests, sizeof(heim_integer), + (generic_decode)der_get_heim_integer); +} + +static int +check_fail_generalized_time(void) +{ + struct test_case tests[] = { + {NULL, 1, "\x00", "no time"}, + {NULL, -1, "\x00", "over sized data"} + }; + int ntests = sizeof(tests) / sizeof(*tests); + + return generic_decode_fail(tests, ntests, sizeof(time_t), + (generic_decode)der_get_generalized_time); +} + +static int +check_fail_oid(void) +{ + struct test_case tests[] = { + {NULL, 0, "", "empty input data"}, + {NULL, 2, "\x00\x80", "last byte continuation" }, + {NULL, 11, "\x00\x81\x80\x80\x80\x80\x80\x80\x80\x80\x00", + "oid element overflow" }, + {NULL, -1, "", "over sized buffer" } + }; + int ntests = sizeof(tests) / sizeof(*tests); + + return generic_decode_fail(tests, ntests, sizeof(heim_oid), + (generic_decode)der_get_oid); +} + +static int +check_fail_bitstring(void) +{ + struct test_case tests[] = { + {NULL, 0, "", "empty input data"}, + {NULL, 1, "\x08", "larger then 8 bits trailer"}, + {NULL, 1, "\x01", "to few bytes for bits"}, + {NULL, -1, "", "length to short"} + }; + int ntests = sizeof(tests) / sizeof(*tests); + + return generic_decode_fail(tests, ntests, sizeof(heim_bit_string), + (generic_decode)der_get_bit_string); +} + int main(int argc, char **argv) { @@ -303,8 +550,22 @@ main(int argc, char **argv) ret += test_integer_more(); ret += test_unsigned (); ret += test_octet_string (); + ret += test_bmp_string (); ret += test_general_string (); ret += test_generalized_time (); + ret += test_oid (); + ret += check_fail_unsigned(); + ret += check_fail_integer(); + ret += check_fail_length(); + ret += check_fail_boolean(); + ret += check_fail_general_string(); + ret += check_fail_bmp_string(); + ret += check_fail_universal_string(); + ret += check_fail_heim_integer(); + ret += check_fail_generalized_time(); + ret += check_fail_oid(); + ret += check_fail_bitstring(); + return ret; } diff --git a/lib/asn1/check-gen.c b/lib/asn1/check-gen.c index 83ec0cfb9..ae4167299 100644 --- a/lib/asn1/check-gen.c +++ b/lib/asn1/check-gen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -43,16 +43,26 @@ #include #include #include +#include +#include +#include #include "check-common.h" RCSID("$Id$"); -static char *lha_princ[] = { "lha" }; +static char *lha_principal[] = { "lha" }; static char *lharoot_princ[] = { "lha", "root" }; static char *datan_princ[] = { "host", "nutcracker.e.kth.se" }; +static char *nada_tgt_principal[] = { "krbtgt", "NADA.KTH.SE" }; +#define IF_OPT_COMPARE(ac,bc,e) \ + if (((ac)->e == NULL && (bc)->e != NULL) || (((ac)->e != NULL && (bc)->e == NULL))) return 1; if ((ab)->e) +#define COMPARE_OPT_STRING(ac,bc,e) \ + do { if (strcmp(*(ac)->e, *(bc)->e) != 0) return 1; } while(0) +#define COMPARE_OPT_OCTECT_STRING(ac,bc,e) \ + do { if ((ac)->e->length != (bc)->e->length || memcmp((ac)->e->data, (bc)->e->data, (ac)->e->length) != 0) return 1; } while(0) #define COMPARE_STRING(ac,bc,e) \ do { if (strcmp((ac)->e, (bc)->e) != 0) return 1; } while(0) #define COMPARE_INTEGER(ac,bc,e) \ @@ -101,7 +111,7 @@ test_principal (void) Principal values[] = { - { { KRB5_NT_PRINCIPAL, { 1, lha_princ } }, "SU.SE" }, + { { KRB5_NT_PRINCIPAL, { 1, lha_principal } }, "SU.SE" }, { { KRB5_NT_PRINCIPAL, { 2, lharoot_princ } }, "SU.SE" }, { { KRB5_NT_SRV_HST, { 2, datan_princ } }, "E.KTH.SE" } }; @@ -117,6 +127,7 @@ test_principal (void) (generic_encode)encode_Principal, (generic_length)length_Principal, (generic_decode)decode_Principal, + (generic_free)free_Principal, cmp_principal); } @@ -161,7 +172,7 @@ test_authenticator (void) }; Authenticator values[] = { - { 5, "E.KTH.SE", { KRB5_NT_PRINCIPAL, { 1, lha_princ } }, + { 5, "E.KTH.SE", { KRB5_NT_PRINCIPAL, { 1, lha_principal } }, NULL, 10, 99, NULL, NULL, NULL }, { 5, "SU.SE", { KRB5_NT_PRINCIPAL, { 2, lharoot_princ } }, NULL, 292, 999, NULL, NULL, NULL } @@ -178,111 +189,496 @@ test_authenticator (void) (generic_encode)encode_Authenticator, (generic_length)length_Authenticator, (generic_decode)decode_Authenticator, + (generic_free)free_Authenticator, cmp_authenticator); } static int -cmp_AuthorizationData (void *a, void *b) +cmp_KRB_ERROR (void *a, void *b) { - AuthorizationData *aa = a; - AuthorizationData *ab = b; + KRB_ERROR *aa = a; + KRB_ERROR *ab = b; + int i; - COMPARE_INTEGER(aa,ab,len); + COMPARE_INTEGER(aa,ab,pvno); + COMPARE_INTEGER(aa,ab,msg_type); + + IF_OPT_COMPARE(aa,ab,ctime) { + COMPARE_INTEGER(aa,ab,ctime); + } + IF_OPT_COMPARE(aa,ab,cusec) { + COMPARE_INTEGER(aa,ab,cusec); + } + COMPARE_INTEGER(aa,ab,stime); + COMPARE_INTEGER(aa,ab,susec); + COMPARE_INTEGER(aa,ab,error_code); + + IF_OPT_COMPARE(aa,ab,crealm) { + COMPARE_OPT_STRING(aa,ab,crealm); + } +#if 0 + IF_OPT_COMPARE(aa,ab,cname) { + COMPARE_OPT_STRING(aa,ab,cname); + } +#endif + COMPARE_STRING(aa,ab,realm); + + COMPARE_INTEGER(aa,ab,sname.name_string.len); + for (i = 0; i < aa->sname.name_string.len; i++) + COMPARE_STRING(aa,ab,sname.name_string.val[i]); + + IF_OPT_COMPARE(aa,ab,e_text) { + COMPARE_OPT_STRING(aa,ab,e_text); + } + IF_OPT_COMPARE(aa,ab,e_data) { + // COMPARE_OPT_OCTECT_STRING(aa,ab,e_data); + } return 0; } -static char static_buf512[512]; - static int -test_AuthorizationData (void) +test_krb_error (void) { struct test_case tests[] = { - { NULL, 14, + { NULL, 127, (unsigned char*) - "\x30\x0c\x30\x0a\xa0\x03\x02\x01\x01\xa1\x03\x04\x01\x00" + "\x7e\x7d\x30\x7b\xa0\x03\x02\x01\x05\xa1\x03\x02\x01\x1e\xa4\x11" + "\x18\x0f\x32\x30\x30\x33\x31\x31\x32\x34\x30\x30\x31\x31\x31\x39" + "\x5a\xa5\x05\x02\x03\x04\xed\xa5\xa6\x03\x02\x01\x1f\xa7\x0d\x1b" + "\x0b\x4e\x41\x44\x41\x2e\x4b\x54\x48\x2e\x53\x45\xa8\x10\x30\x0e" + "\xa0\x03\x02\x01\x01\xa1\x07\x30\x05\x1b\x03\x6c\x68\x61\xa9\x0d" + "\x1b\x0b\x4e\x41\x44\x41\x2e\x4b\x54\x48\x2e\x53\x45\xaa\x20\x30" + "\x1e\xa0\x03\x02\x01\x01\xa1\x17\x30\x15\x1b\x06\x6b\x72\x62\x74" + "\x67\x74\x1b\x0b\x4e\x41\x44\x41\x2e\x4b\x54\x48\x2e\x53\x45", + "KRB-ERROR Test 1" + } + }; + int ntests = sizeof(tests) / sizeof(*tests); + KRB_ERROR e1; + PrincipalName lhaprincipalname = { 1, { 1, lha_principal } }; + PrincipalName tgtprincipalname = { 1, { 2, nada_tgt_principal } }; + char *realm = "NADA.KTH.SE"; + + e1.pvno = 5; + e1.msg_type = 30; + e1.ctime = NULL; + e1.cusec = NULL; + e1.stime = 1069632679; + e1.susec = 322981; + e1.error_code = 31; + e1.crealm = &realm; + e1.cname = &lhaprincipalname; + e1.realm = "NADA.KTH.SE"; + e1.sname = tgtprincipalname; + e1.e_text = NULL; + e1.e_data = NULL; + + tests[0].val = &e1; + + return generic_test (tests, ntests, sizeof(KRB_ERROR), + (generic_encode)encode_KRB_ERROR, + (generic_length)length_KRB_ERROR, + (generic_decode)decode_KRB_ERROR, + (generic_free)free_KRB_ERROR, + cmp_KRB_ERROR); +} + +static int +cmp_Name (void *a, void *b) +{ + /* XXX */ + return 0; +} + +static int +test_Name (void) +{ + struct test_case tests[] = { + { NULL, 35, + (unsigned char*) + "\x30\x21\x31\x1f\x30\x0b\x06\x03\x55\x04\x03\x13\x04\x4c\x6f\x76" + "\x65\x30\x10\x06\x03\x55\x04\x07\x13\x09\x53\x54\x4f\x43\x4b\x48" + "\x4f\x4c\x4d", + "Name CN=Love+L=STOCKHOLM" }, - { NULL, 142, + { NULL, 35, (unsigned char*) - "\x30\x81\x8b\x30\x81\x88\xa0\x03\x02\x01\x01\xa1\x81\x80\x04\x7e" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - }, - { NULL, 132, - (unsigned char*) - "\x30\x81\x81\x30\x73\xa0\x03\x02\x01\x01\xa1\x6c\x04\x6a\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x30\x0a\xa0\x03\x02\x01\x01\xa1" - "\x03\x04\x01\x00" - }, - { NULL, 134, - (unsigned char*) - "\x30\x81\x83\x30\x74\xa0\x03\x02\x01\x01\xa1\x6d\x04\x6b\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x0b\xa0\x03\x02\x01\x01" - "\xa1\x04\x04\x02\x00\x00" + "\x30\x21\x31\x1f\x30\x0b\x06\x03\x55\x04\x03\x13\x04\x4c\x6f\x76" + "\x65\x30\x10\x06\x03\x55\x04\x07\x13\x09\x53\x54\x4f\x43\x4b\x48" + "\x4f\x4c\x4d", + "Name L=STOCKHOLM+CN=Love" } }; - AuthorizationData values[] = { - { 1, NULL }, - { 1, NULL }, - { 2, NULL }, - { 2, NULL } + int ntests = sizeof(tests) / sizeof(*tests); + Name n1, n2; + RelativeDistinguishedName rdn1[1]; + RelativeDistinguishedName rdn2[1]; + AttributeTypeAndValue atv1[2]; + AttributeTypeAndValue atv2[2]; + unsigned cmp_CN[] = { 2, 5, 4, 3 }; + unsigned cmp_L[] = { 2, 5, 4, 7 }; + + /* n1 */ + n1.element = choice_Name_rdnSequence; + n1.u.rdnSequence.val = rdn1; + n1.u.rdnSequence.len = sizeof(rdn1)/sizeof(rdn1[0]); + rdn1[0].val = atv1; + rdn1[0].len = sizeof(atv1)/sizeof(atv1[0]); + + atv1[0].type.length = sizeof(cmp_CN)/sizeof(cmp_CN[0]); + atv1[0].type.components = cmp_CN; + atv1[0].value.element = choice_DirectoryString_printableString; + atv1[0].value.u.printableString = "Love"; + + atv1[1].type.length = sizeof(cmp_L)/sizeof(cmp_L[0]); + atv1[1].type.components = cmp_L; + atv1[1].value.element = choice_DirectoryString_printableString; + atv1[1].value.u.printableString = "STOCKHOLM"; + + /* n2 */ + n2.element = choice_Name_rdnSequence; + n2.u.rdnSequence.val = rdn2; + n2.u.rdnSequence.len = sizeof(rdn2)/sizeof(rdn2[0]); + rdn2[0].val = atv2; + rdn2[0].len = sizeof(atv2)/sizeof(atv2[0]); + + atv2[0].type.length = sizeof(cmp_L)/sizeof(cmp_L[0]); + atv2[0].type.components = cmp_L; + atv2[0].value.element = choice_DirectoryString_printableString; + atv2[0].value.u.printableString = "STOCKHOLM"; + + atv2[1].type.length = sizeof(cmp_CN)/sizeof(cmp_CN[0]); + atv2[1].type.components = cmp_CN; + atv2[1].value.element = choice_DirectoryString_printableString; + atv2[1].value.u.printableString = "Love"; + + /* */ + tests[0].val = &n1; + tests[1].val = &n2; + + return generic_test (tests, ntests, sizeof(Name), + (generic_encode)encode_Name, + (generic_length)length_Name, + (generic_decode)decode_Name, + (generic_free)free_Name, + cmp_Name); +} + + +#if 0 + +#include + +static int +check_heim_integer(void) +{ + heim_integer h; + BIGNUM *bn = BN_new(); + unsigned char buf[10]; + unsigned char buf2[10]; + size_t len = sizeof(buf), size; + size_t len2 = sizeof(buf), size2; + int i, ret; + + memset(buf, 0, sizeof(buf)); + memset(buf2, 0, sizeof(buf2)); + + i = -123123; + + BN_zero(bn); + if (i < 0) + BN_sub_word(bn, -i); + else + BN_add_word(bn, i); + + h.negative = bn->neg; + h.length = BN_num_bytes(bn); + h.data = emalloc(h.length); + BN_bn2bin(bn, h.data); + + printf("length = %d\n", h.length); + + ret = der_put_heim_integer(buf + len - 1, len, &h, &size); + if (ret) + errx(1, "der_put_heim_integer: %d", ret); + + ret = der_put_integer(buf2 + len - 1, len2, &i, &size2); + if (ret) + errx(1, "der_put_heim_integer: %d", ret); + + if (size != size2) + errx(1, "size %lu != size2 %lu", + (unsigned long)size, (unsigned long)size2); + + if (memcmp(buf + len - 1 - size, + buf2 + len - 1 - size, + size) != 0) + errx(1, "data not the same"); + + return 0; +} +#endif + +static int +cmp_KeyUsage (void *a, void *b) +{ + KeyUsage *aa = a; + KeyUsage *ab = b; + + return KeyUsage2int(*aa) != KeyUsage2int(*ab); +} + +static int +test_bit_string (void) +{ + struct test_case tests[] = { + { NULL, 4, + "\x03\x02\x07\x80", + "bitstring 1" + } + }; + + int ntests = sizeof(tests) / sizeof(*tests); + KeyUsage ku1; + + memset(&ku1, 0, sizeof(ku1)); + ku1.digitalSignature = 1; + + tests[0].val = &ku1; + + return generic_test (tests, ntests, sizeof(KeyUsage), + (generic_encode)encode_KeyUsage, + (generic_length)length_KeyUsage, + (generic_decode)decode_KeyUsage, + (generic_free)free_KeyUsage, + cmp_KeyUsage); +} + +static int +cmp_TESTLargeTag (void *a, void *b) +{ + TESTLargeTag *aa = a; + TESTLargeTag *ab = b; + + COMPARE_INTEGER(aa,ab,foo); + return 0; +} + +static int +test_large_tag (void) +{ + struct test_case tests[] = { + { NULL, 8, "\x30\x06\xbf\x7f\x03\x02\x01\x01", "large tag 1" } + }; + + int ntests = sizeof(tests) / sizeof(*tests); + TESTLargeTag lt1; + + memset(<1, 0, sizeof(lt1)); + lt1.foo = 1; + + tests[0].val = <1; + + return generic_test (tests, ntests, sizeof(TESTLargeTag), + (generic_encode)encode_TESTLargeTag, + (generic_length)length_TESTLargeTag, + (generic_decode)decode_TESTLargeTag, + (generic_free)free_TESTLargeTag, + cmp_TESTLargeTag); +} + +struct test_data { + int ok; + size_t len; + size_t expected_len; + void *data; +}; + +static int +check_tag_length(void) +{ + struct test_data td[] = { + { 1, 3, 3, "\x02\x01\x00"}, + { 1, 3, 3, "\x02\x01\x7f"}, + { 1, 4, 4, "\x02\x02\x00\x80"}, + { 1, 4, 4, "\x02\x02\x01\x00"}, + { 1, 4, 4, "\x02\x02\x02\x00"}, + { 0, 3, 0, "\x02\x02\x00"}, + { 0, 3, 0, "\x02\x7f\x7f"}, + { 0, 4, 0, "\x02\x03\x00\x80"}, + { 0, 4, 0, "\x02\x7f\x01\x00"}, + { 0, 5, 0, "\x02\xff\x7f\x02\x00"} + }; + size_t sz; + krb5uint32 values[] = {0, 127, 128, 256, 512, + 0, 127, 128, 256, 512 }; + krb5uint32 u; + int i, ret, failed = 0; + void *buf; + + for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) { + struct map_page *page; + + buf = map_alloc(OVERRUN, td[i].data, td[i].len, &page); + + ret = decode_krb5uint32(buf, td[i].len, &u, &sz); + if (ret) { + if (td[i].ok) { + printf("failed with tag len test %d\n", i); + failed = 1; + } + } else { + if (td[i].ok == 0) { + printf("failed with success for tag len test %d\n", i); + failed = 1; + } + if (td[i].expected_len != sz) { + printf("wrong expected size for tag test %d\n", i); + failed = 1; + } + if (values[i] != u) { + printf("wrong value for tag test %d\n", i); + failed = 1; + } + } + map_free(page, "test", "decode"); + } + return failed; +} + +static int +cmp_TESTChoice (void *a, void *b) +{ + return 0; +} + +static int +test_choice (void) +{ + struct test_case tests[] = { + { NULL, 5, "\xa1\x03\x02\x01\x01", "large choice 1" }, + { NULL, 5, "\xa2\x03\x02\x01\x02", "large choice 2" } + }; + + int ret = 0, ntests = sizeof(tests) / sizeof(*tests); + TESTChoice1 c1; + TESTChoice1 c2_1; + TESTChoice2 c2_2; + + memset(&c1, 0, sizeof(c1)); + c1.element = choice_TESTChoice1_i1; + c1.u.i1 = 1; + tests[0].val = &c1; + + memset(&c2_1, 0, sizeof(c2_1)); + c2_1.element = choice_TESTChoice1_i2; + c2_1.u.i2 = 2; + tests[1].val = &c2_1; + + ret += generic_test (tests, ntests, sizeof(TESTChoice1), + (generic_encode)encode_TESTChoice1, + (generic_length)length_TESTChoice1, + (generic_decode)decode_TESTChoice1, + (generic_free)free_TESTChoice1, + cmp_TESTChoice); + + memset(&c2_2, 0, sizeof(c2_2)); + c2_2.element = choice_TESTChoice2_asn1_ellipsis; + c2_2.u.asn1_ellipsis.data = "\xa2\x03\x02\x01\x02"; + c2_2.u.asn1_ellipsis.length = 5; + tests[1].val = &c2_2; + + ret += generic_test (tests, ntests, sizeof(TESTChoice2), + (generic_encode)encode_TESTChoice2, + (generic_length)length_TESTChoice2, + (generic_decode)decode_TESTChoice2, + (generic_free)free_TESTChoice2, + cmp_TESTChoice); + + return ret; +} + +static int +check_fail_largetag(void) +{ + struct test_case tests[] = { + {NULL, 14, "\x30\x0c\xbf\x87\xff\xff\xff\xff\xff\x7f\x03\x02\x01\x01", + "tag overflow"}, + {NULL, 0, "", "empty buffer"}, + {NULL, 7, "\x30\x05\xa1\x03\x02\x02\x01", + "one too short" }, + {NULL, 7, "\x30\x04\xa1\x03\x02\x02\x01" + "two too short" }, + {NULL, 7, "\x30\x03\xa1\x03\x02\x02\x01", + "three too short" }, + {NULL, 7, "\x30\x02\xa1\x03\x02\x02\x01", + "four too short" }, + {NULL, 7, "\x30\x01\xa1\x03\x02\x02\x01", + "five too short" }, + {NULL, 7, "\x30\x00\xa1\x03\x02\x02\x01", + "six too short" }, + {NULL, 7, "\x30\x05\xa1\x04\x02\x02\x01", + "inner one too long" }, + {NULL, 7, "\x30\x00\xa1\x02\x02\x02\x01", + "inner one too short" }, + {NULL, 8, "\x30\x05\xbf\x7f\x03\x02\x02\x01", + "inner one too short"}, + {NULL, 8, "\x30\x06\xbf\x64\x03\x02\x01\x01", + "wrong tag"}, + {NULL, 10, "\x30\x08\xbf\x9a\x9b\x38\x03\x02\x01\x01", + "still wrong tag"}, + {NULL, -1, NULL, "overlarger buffer"} }; - int i; int ntests = sizeof(tests) / sizeof(*tests); - for (i = 0; i < ntests; ++i) { - tests[i].val = &values[i]; - asprintf (&tests[i].name, "AuthorizationData %d", i); - values[i].val = emalloc(values[i].len * sizeof(values[i].val[0])); - } - values[0].val[0].ad_type = 1; - values[0].val[0].ad_data.length = 1; - values[0].val[0].ad_data.data = static_buf512; + return generic_decode_fail(tests, ntests, sizeof(TESTLargeTag), + (generic_decode)decode_TESTLargeTag); +} - values[1].val[0].ad_type = 1; - values[1].val[0].ad_data.length = 126; - values[1].val[0].ad_data.data = static_buf512; - values[2].val[0].ad_type = 1; - values[2].val[0].ad_data.length = 106; - values[2].val[0].ad_data.data = static_buf512; +static int +check_fail_sequence(void) +{ + struct test_case tests[] = { + {NULL, 0, "", "empty buffer"}, + {NULL, 24, + "\x30\x16\xa0\x03\x02\x01\x01\xa1\x08\x30\x06\xbf\x7f\x03\x02\x01\x01" + "\x02\x01\x01\xa2\x03\x02\x01\x01" + "missing one byte from the end, internal length ok"}, + {NULL, 25, + "\x30\x18\xa0\x03\x02\x01\x01\xa1\x08\x30\x06\xbf\x7f\x03\x02\x01\x01" + "\x02\x01\x01\xa2\x03\x02\x01\x01", + "inner length one byte too long"}, + {NULL, 24, + "\x30\x17\xa0\x03\x02\x01\x01\xa1\x08\x30\x06\xbf\x7f\x03\x02\x01" + "\x01\x02\x01\x01\xa2\x03\x02\x01\x01", + "correct buffer but missing one to short"}, + {NULL, -1, NULL, "overlarger buffer"} + }; + int ntests = sizeof(tests) / sizeof(*tests); - values[2].val[1].ad_type = 1; - values[2].val[1].ad_data.length = 1; - values[2].val[1].ad_data.data = static_buf512; + return generic_decode_fail(tests, ntests, sizeof(TESTSeq), + (generic_decode)decode_TESTSeq); +} - values[3].val[0].ad_type = 1; - values[3].val[0].ad_data.length = 107; - values[3].val[0].ad_data.data = static_buf512; +static int +check_fail_choice(void) +{ + struct test_case tests[] = { + {NULL, 6, + "\xa1\x02\x02\x01\x01", + "one too short"}, + {NULL, 6, + "\xa1\x03\x02\x02\x01", + "one too short inner"}, + {NULL, -1, NULL, "overlarger buffer"} + }; + int ntests = sizeof(tests) / sizeof(*tests); - values[3].val[1].ad_type = 1; - values[3].val[1].ad_data.length = 2; - values[3].val[1].ad_data.data = static_buf512; - - return generic_test (tests, ntests, sizeof(AuthorizationData), - (generic_encode)encode_AuthorizationData, - (generic_length)length_AuthorizationData, - (generic_decode)decode_AuthorizationData, - cmp_AuthorizationData); + return generic_decode_fail(tests, ntests, sizeof(TESTChoice1), + (generic_decode)decode_TESTChoice1); } int @@ -292,7 +688,20 @@ main(int argc, char **argv) ret += test_principal (); ret += test_authenticator(); - ret += test_AuthorizationData(); + ret += test_krb_error(); + ret += test_Name(); +#if 0 + ret += check_heim_integer(); +#endif + ret += test_bit_string(); + + ret += check_tag_length(); + ret += test_large_tag(); + ret += test_choice(); + + ret += check_fail_largetag(); + ret += check_fail_sequence(); + ret += check_fail_choice(); return ret; } diff --git a/lib/asn1/der.c b/lib/asn1/der.c new file mode 100644 index 000000000..159d358fc --- /dev/null +++ b/lib/asn1/der.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "der_locl.h" +#include +#include +#include +#include +#include + +RCSID("$Id$"); + + +static const char *class_names[] = { + "UNIV", /* 0 */ + "APPL", /* 1 */ + "CONTEXT", /* 2 */ + "PRIVATE" /* 3 */ +}; + +static const char *type_names[] = { + "PRIM", /* 0 */ + "CONS" /* 1 */ +}; + +static const char *tag_names[] = { + "EndOfContent", /* 0 */ + "Boolean", /* 1 */ + "Integer", /* 2 */ + "BitString", /* 3 */ + "OctetString", /* 4 */ + "Null", /* 5 */ + "ObjectID", /* 6 */ + NULL, /* 7 */ + NULL, /* 8 */ + NULL, /* 9 */ + "Enumerated", /* 10 */ + NULL, /* 11 */ + NULL, /* 12 */ + NULL, /* 13 */ + NULL, /* 14 */ + NULL, /* 15 */ + "Sequence", /* 16 */ + "Set", /* 17 */ + NULL, /* 18 */ + "PrintableString", /* 19 */ + NULL, /* 20 */ + NULL, /* 21 */ + "IA5String", /* 22 */ + "UTCTime", /* 23 */ + "GeneralizedTime", /* 24 */ + NULL, /* 25 */ + "VisibleString", /* 26 */ + "GeneralString", /* 27 */ + NULL, /* 28 */ + NULL, /* 29 */ + "BMPString" /* 30 */ +}; + +static int +get_type(const char *name, const char *list[], unsigned len) +{ + unsigned i; + for (i = 0; i < len; i++) + if (list[i] && strcasecmp(list[i], name) == 0) + return i; + return -1; +} + +#define SIZEOF_ARRAY(a) (sizeof((a))/sizeof((a)[0])) + +const char * +der_get_class_name(unsigned num) +{ + if (num >= SIZEOF_ARRAY(class_names)) + return NULL; + return class_names[num]; +} + +int +der_get_class_num(const char *name) +{ + return get_type(name, class_names, SIZEOF_ARRAY(class_names)); +} + +const char * +der_get_type_name(unsigned num) +{ + if (num >= SIZEOF_ARRAY(type_names)) + return NULL; + return type_names[num]; +} + +int +der_get_type_num(const char *name) +{ + return get_type(name, type_names, SIZEOF_ARRAY(type_names)); +} + +const char * +der_get_tag_name(unsigned num) +{ + if (num >= SIZEOF_ARRAY(tag_names)) + return NULL; + return tag_names[num]; +} + +int +der_get_tag_num(const char *name) +{ + return get_type(name, tag_names, SIZEOF_ARRAY(tag_names)); +} diff --git a/lib/asn1/der.h b/lib/asn1/der.h index 05b08e3f4..eaecaa49d 100644 --- a/lib/asn1/der.h +++ b/lib/asn1/der.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -36,145 +36,208 @@ #ifndef __DER_H__ #define __DER_H__ -#include - typedef enum { ASN1_C_UNIV = 0, ASN1_C_APPL = 1, - ASN1_C_CONTEXT = 2 , + ASN1_C_CONTEXT = 2, ASN1_C_PRIVATE = 3 } Der_class; typedef enum {PRIM = 0, CONS = 1} Der_type; +#define MAKE_TAG(CLASS, TYPE, TAG) (((CLASS) << 6) | ((TYPE) << 5) | (TAG)) + /* Universal tags */ enum { - UT_Boolean = 1, - UT_Integer = 2, - UT_BitString = 3, - UT_OctetString = 4, - UT_Null = 5, - UT_OID = 6, - UT_Enumerated = 10, - UT_UTF8String = 12, - UT_Sequence = 16, - UT_Set = 17, - UT_PrintableString = 19, - UT_IA5String = 22, - UT_UTCTime = 23, - UT_GeneralizedTime = 24, - UT_VisibleString = 26, - UT_GeneralString = 27 + UT_EndOfContent = 0, + UT_Boolean = 1, + UT_Integer = 2, + UT_BitString = 3, + UT_OctetString = 4, + UT_Null = 5, + UT_OID = 6, + UT_Enumerated = 10, + UT_UTF8String = 12, + UT_Sequence = 16, + UT_Set = 17, + UT_PrintableString = 19, + UT_IA5String = 22, + UT_UTCTime = 23, + UT_GeneralizedTime = 24, + UT_VisibleString = 26, + UT_GeneralString = 27, + /* unsupported types */ + UT_ObjectDescriptor = 7, + UT_External = 8, + UT_Real = 9, + UT_EmbeddedPDV = 11, + UT_RelativeOID = 13, + UT_NumericString = 18, + UT_TeletexString = 20, + UT_VideotexString = 21, + UT_GraphicString = 25, + UT_UniversalString = 25, + UT_BMPString = 30, }; #define ASN1_INDEFINITE 0xdce0deed -#ifndef HAVE_TIMEGM -time_t timegm (struct tm *); -#endif +typedef struct asn1_der_time_t { + time_t dt_sec; + unsigned long dt_nsec; +} asn1_der_time_t; -int time2generalizedtime (time_t t, heim_octet_string *s); +typedef struct asn1_ber_time_t { + time_t bt_sec; + unsigned bt_nsec; + int bt_zone; +} asn1_ber_time_t; -int der_get_int (const unsigned char *p, size_t len, int *ret, size_t *size); +int der_get_unsigned (const unsigned char *p, size_t len, + unsigned *ret, size_t *size); +int der_get_integer (const unsigned char *p, size_t len, + int *ret, size_t *size); +int der_get_heim_integer (const unsigned char *p, size_t len, + heim_integer *ret, size_t *size); +int der_get_boolean(const unsigned char *p, size_t len, + int *data, size_t *size); int der_get_length (const unsigned char *p, size_t len, size_t *val, size_t *size); -int der_get_boolean (const unsigned char *p, size_t len, - int *data, size_t *size); int der_get_general_string (const unsigned char *p, size_t len, heim_general_string *str, size_t *size); +int der_get_utf8string (const unsigned char *p, size_t len, + heim_utf8_string *str, size_t *size); +int der_get_universal_string (const unsigned char *p, size_t len, + heim_universal_string *str, size_t *size); +int der_get_bmp_string (const unsigned char *p, size_t len, + heim_bmp_string *str, size_t *size); +int der_get_printable_string (const unsigned char *p, size_t len, + heim_printable_string *str, size_t *size); +int der_get_ia5_string (const unsigned char *p, size_t len, + heim_ia5_string *str, size_t *size); int der_get_octet_string (const unsigned char *p, size_t len, heim_octet_string *data, size_t *size); +int der_get_generalized_time (const unsigned char *p, size_t len, + time_t *data, size_t *size); +int der_get_generalized_time_der (const unsigned char *p, size_t len, + asn1_der_time_t *data, size_t *size); +int der_get_generalized_time_ber (const unsigned char *p, size_t len, + asn1_ber_time_t *data, size_t *size); +int der_get_utctime (const unsigned char *p, size_t len, + time_t *data, size_t *size); int der_get_oid (const unsigned char *p, size_t len, heim_oid *data, size_t *size); +int der_get_bit_string (const unsigned char *p, size_t len, + heim_bit_string *data, size_t *size); int der_get_tag (const unsigned char *p, size_t len, Der_class *class, Der_type *type, - int *tag, size_t *size); + unsigned int *tag, size_t *size); int der_match_tag (const unsigned char *p, size_t len, Der_class class, Der_type type, - int tag, size_t *size); + unsigned int tag, size_t *size); int der_match_tag_and_length (const unsigned char *p, size_t len, - Der_class class, Der_type type, int tag, + Der_class class, Der_type type, unsigned int tag, size_t *length_ret, size_t *size); -int decode_boolean (const unsigned char*, size_t, int*, size_t*); -int decode_integer (const unsigned char*, size_t, int*, size_t*); -int decode_unsigned (const unsigned char*, size_t, unsigned*, size_t*); -int decode_enumerated (const unsigned char*, size_t, unsigned*, size_t*); -int decode_general_string (const unsigned char*, size_t, - heim_general_string*, size_t*); -int decode_oid (const unsigned char *p, size_t len, - heim_oid *k, size_t *size); -int decode_octet_string (const unsigned char*, size_t, - heim_octet_string*, size_t*); -int decode_generalized_time (const unsigned char*, size_t, time_t*, size_t*); -int decode_nulltype (const unsigned char*, size_t, size_t*); -int decode_utf8string (const unsigned char*, size_t, - heim_utf8_string*, size_t*); +int der_put_unsigned (unsigned char *p, size_t len, const unsigned *val, size_t*); +int der_put_integer (unsigned char *p, size_t len, const int *val, size_t*); +int der_put_heim_integer (unsigned char *p, size_t len, + const heim_integer *val, size_t*); +int der_put_boolean (unsigned char *p, size_t len, const int *val, size_t*); -int der_put_int (unsigned char *p, size_t len, int val, size_t*); int der_put_length (unsigned char *p, size_t len, size_t val, size_t*); -int der_put_boolean (unsigned char *p, size_t len, const int *data, size_t*); int der_put_general_string (unsigned char *p, size_t len, const heim_general_string *str, size_t*); +int der_put_utf8string (unsigned char *p, size_t len, + const heim_utf8_string *str, size_t*); +int der_put_universal_string (unsigned char *p, size_t len, + const heim_universal_string *str, size_t*); +int der_put_bmp_string (unsigned char *p, size_t len, + const heim_bmp_string *str, size_t*); +int der_put_printable_string (unsigned char *p, size_t len, + const heim_printable_string *str, size_t*); +int der_put_ia5_string (unsigned char *p, size_t len, + const heim_ia5_string *str, size_t*); int der_put_octet_string (unsigned char *p, size_t len, const heim_octet_string *data, size_t*); +int der_put_generalized_time (unsigned char *p, size_t len, + const time_t *data, size_t *size); +int der_put_utctime (unsigned char *p, size_t len, + const time_t *data, size_t *size); int der_put_oid (unsigned char *p, size_t len, const heim_oid *data, size_t *size); +int der_put_bit_string (unsigned char *p, size_t len, + const heim_bit_string *data, size_t *size); int der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, - int tag, size_t*); + unsigned int tag, size_t*); int der_put_length_and_tag (unsigned char*, size_t, size_t, - Der_class, Der_type, int, size_t*); - -int encode_boolean (unsigned char *p, size_t len, - const int *data, size_t*); -int encode_integer (unsigned char *p, size_t len, - const int *data, size_t*); -int encode_unsigned (unsigned char *p, size_t len, - const unsigned *data, size_t*); -int encode_enumerated (unsigned char *p, size_t len, - const unsigned *data, size_t*); -int encode_general_string (unsigned char *p, size_t len, - const heim_general_string *data, size_t*); -int encode_octet_string (unsigned char *p, size_t len, - const heim_octet_string *k, size_t*); -int encode_oid (unsigned char *p, size_t len, - const heim_oid *k, size_t*); -int encode_generalized_time (unsigned char *p, size_t len, - const time_t *t, size_t*); -int encode_nulltype (unsigned char*, size_t, size_t*); -int encode_utf8string (unsigned char*, size_t, - const heim_utf8_string*, size_t*); + Der_class, Der_type, unsigned int, size_t*); void free_integer (int *num); +void free_heim_integer (heim_integer *num); +void free_octet_string (heim_octet_string *k); void free_general_string (heim_general_string *str); void free_octet_string (heim_octet_string *k); void free_oid (heim_oid *k); +void free_bit_string (heim_bit_string *k); void free_generalized_time (time_t *t); +void free_utctime (time_t *t); void free_utf8string (heim_utf8_string*); +void free_printable_string (heim_printable_string*); +void free_ia5_string (heim_ia5_string*); +void free_universal_string (heim_universal_string*); +void free_bmp_string (heim_bmp_string*); size_t length_len (size_t len); -size_t length_boolean (const int *data); size_t length_integer (const int *data); +size_t length_heim_integer (const heim_integer *data); size_t length_unsigned (const unsigned *data); size_t length_enumerated (const unsigned *data); size_t length_general_string (const heim_general_string *data); size_t length_octet_string (const heim_octet_string *k); size_t length_oid (const heim_oid *k); +size_t length_bit_string (const heim_bit_string *k); size_t length_generalized_time (const time_t *t); -size_t length_nulltype (void); +size_t length_utctime (const time_t *t); size_t length_utf8string (const heim_utf8_string*); +size_t length_printable_string (const heim_printable_string*); +size_t length_ia5_string (const heim_ia5_string*); +size_t length_bmp_string (const heim_bmp_string*); +size_t length_universal_string (const heim_universal_string*); +size_t length_boolean (const int*); +int copy_heim_integer (const heim_integer *, heim_integer *); int copy_general_string (const heim_general_string *, heim_general_string *); int copy_octet_string (const heim_octet_string *, heim_octet_string *); int copy_oid (const heim_oid *from, heim_oid *to); -int copy_nulltype (void *, void *); +int copy_bit_string (const heim_bit_string *from, heim_bit_string *to); int copy_utf8string (const heim_utf8_string*, heim_utf8_string*); +int copy_printable_string (const heim_printable_string*,heim_printable_string*); +int copy_ia5_string (const heim_ia5_string*,heim_ia5_string*); +int copy_universal_string(const heim_universal_string*,heim_universal_string*); +int copy_bmp_string (const heim_bmp_string*,heim_bmp_string*); int heim_oid_cmp(const heim_oid *, const heim_oid *); int heim_octet_string_cmp(const heim_octet_string *,const heim_octet_string *); +int heim_bit_string_cmp(const heim_bit_string *, const heim_bit_string *); +int heim_integer_cmp(const heim_integer *, const heim_integer *); +int heim_bmp_string_cmp(const heim_bmp_string *, const heim_bmp_string *); +int heim_universal_string_cmp(const heim_universal_string *, + const heim_universal_string *); -int fix_dce(size_t reallen, size_t *len); +int der_parse_oid(const char *, heim_oid *); + +int _heim_fix_dce(size_t reallen, size_t *len); +int _heim_der_set_sort(const void *, const void *); +int _heim_time2generalizedtime (time_t, heim_octet_string *, int); + +const char * der_get_class_name(unsigned); +int der_get_class_num(const char *); +const char * der_get_type_name(unsigned); +int der_get_type_num(const char *); +const char * der_get_tag_name(unsigned); +int der_get_tag_num(const char *); #endif /* __DER_H__ */ diff --git a/lib/asn1/der_cmp.c b/lib/asn1/der_cmp.c index b91610db3..0a9c4ea76 100644 --- a/lib/asn1/der_cmp.c +++ b/lib/asn1/der_cmp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 2003-2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,8 +33,6 @@ #include "der_locl.h" -RCSID("$Id$"); - int heim_oid_cmp(const heim_oid *p, const heim_oid *q) { @@ -52,3 +50,48 @@ heim_octet_string_cmp(const heim_octet_string *p, const heim_octet_string *q) return p->length - q->length; return memcmp(p->data, q->data, p->length); } + +int +heim_bit_string_cmp(const heim_bit_string *p, const heim_bit_string *q) +{ + int i, r1, r2; + if (p->length != q->length) + return p->length - q->length; + i = memcmp(p->data, q->data, p->length / 8); + if (i) + return i; + i = p->length / 8; + r1 = ((unsigned char *)p->data)[i]; + r2 = ((unsigned char *)q->data)[i]; + i = 8 - p->length % 8; + r1 = r1 >> i; + r2 = r2 >> i; + return r1 - r2; +} + +int +heim_integer_cmp(const heim_integer *p, const heim_integer *q) +{ + if (p->length != q->length) + return p->length - q->length; + if (p->negative != q->negative) + return p->negative - q->negative; + return memcmp(p->data, q->data, p->length); +} + +int +heim_bmp_string_cmp(const heim_bmp_string *p, const heim_bmp_string *q) +{ + if (p->length != q->length) + return p->length - q->length; + return memcmp(p->data, q->data, q->length * sizeof(q->data[0])); +} + +int +heim_universal_string_cmp(const heim_universal_string *p, + const heim_universal_string *q) +{ + if (p->length != q->length) + return p->length - q->length; + return memcmp(p->data, q->data, q->length * sizeof(q->data[0])); +} diff --git a/lib/asn1/der_copy.c b/lib/asn1/der_copy.c index 622e97872..cbd9ac689 100644 --- a/lib/asn1/der_copy.c +++ b/lib/asn1/der_copy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -44,6 +44,49 @@ copy_general_string (const heim_general_string *from, heim_general_string *to) return 0; } +int +copy_utf8string (const heim_utf8_string *from, heim_utf8_string *to) +{ + return copy_general_string(from, to); +} + +int +copy_printable_string (const heim_printable_string *from, + heim_printable_string *to) +{ + return copy_general_string(from, to); +} + +int +copy_ia5_string (const heim_printable_string *from, + heim_printable_string *to) +{ + return copy_general_string(from, to); +} + +int +copy_bmp_string (const heim_bmp_string *from, heim_bmp_string *to) +{ + to->length = from->length; + to->data = malloc(to->length * sizeof(to->data[0])); + if(to->length != 0 && to->data == NULL) + return ENOMEM; + memcpy(to->data, from->data, to->length * sizeof(to->data[0])); + return 0; +} + +int +copy_universal_string (const heim_universal_string *from, + heim_universal_string *to) +{ + to->length = from->length; + to->data = malloc(to->length * sizeof(to->data[0])); + if(to->length != 0 && to->data == NULL) + return ENOMEM; + memcpy(to->data, from->data, to->length * sizeof(to->data[0])); + return 0; +} + int copy_octet_string (const heim_octet_string *from, heim_octet_string *to) { @@ -55,6 +98,17 @@ copy_octet_string (const heim_octet_string *from, heim_octet_string *to) return 0; } +int +copy_heim_integer (const heim_integer *from, heim_integer *to) +{ + to->length = from->length; + to->data = malloc(to->length); + if(to->length != 0 && to->data == NULL) + return ENOMEM; + memcpy(to->data, from->data, to->length); + return 0; +} + int copy_oid (const heim_oid *from, heim_oid *to) { @@ -66,3 +120,17 @@ copy_oid (const heim_oid *from, heim_oid *to) to->length * sizeof(*to->components)); return 0; } + +int +copy_bit_string (const heim_bit_string *from, heim_bit_string *to) +{ + size_t len; + + len = (from->length + 7) / 8; + to->length = from->length; + to->data = malloc(len); + if(len != 0 && to->data == NULL) + return ENOMEM; + memcpy(to->data, from->data, len); + return 0; +} diff --git a/lib/asn1/der_free.c b/lib/asn1/der_free.c index 0c1f96de9..7c303763b 100644 --- a/lib/asn1/der_free.c +++ b/lib/asn1/der_free.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -42,11 +42,56 @@ free_general_string (heim_general_string *str) *str = NULL; } +void +free_utf8string (heim_utf8_string *str) +{ + free(*str); + *str = NULL; +} + +void +free_printable_string (heim_printable_string *str) +{ + free(*str); + *str = NULL; +} + +void +free_ia5_string (heim_ia5_string *str) +{ + free_general_string(str); +} + +void +free_bmp_string (heim_bmp_string *k) +{ + free(k->data); + k->data = NULL; + k->length = 0; +} + +void +free_universal_string (heim_universal_string *k) +{ + free(k->data); + k->data = NULL; + k->length = 0; +} + void free_octet_string (heim_octet_string *k) { free(k->data); k->data = NULL; + k->length = 0; +} + +void +free_heim_integer (heim_integer *k) +{ + free(k->data); + k->data = NULL; + k->length = 0; } void @@ -54,4 +99,13 @@ free_oid (heim_oid *k) { free(k->components); k->components = NULL; + k->length = 0; +} + +void +free_bit_string (heim_bit_string *k) +{ + free(k->data); + k->data = NULL; + k->length = 0; } diff --git a/lib/asn1/der_get.c b/lib/asn1/der_get.c index 1c33f8265..b2a36b1ed 100644 --- a/lib/asn1/der_get.c +++ b/lib/asn1/der_get.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -45,13 +45,18 @@ RCSID("$Id$"); * Either 0 or an error code is returned. */ -static int +int der_get_unsigned (const unsigned char *p, size_t len, unsigned *ret, size_t *size) { unsigned val = 0; size_t oldlen = len; + if (len == sizeof(unsigned) + 1 && p[0] == 0) + ; + else if (len > sizeof(unsigned)) + return ASN1_OVERRUN; + while (len--) val = val * 256 + *p++; *ret = val; @@ -60,12 +65,15 @@ der_get_unsigned (const unsigned char *p, size_t len, } int -der_get_int (const unsigned char *p, size_t len, - int *ret, size_t *size) +der_get_integer (const unsigned char *p, size_t len, + int *ret, size_t *size) { int val = 0; size_t oldlen = len; + if (len > sizeof(int)) + return ASN1_OVERRUN; + if (len > 0) { val = (signed char)*p++; while (--len) @@ -76,19 +84,6 @@ der_get_int (const unsigned char *p, size_t len, return 0; } -int -der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size) -{ - if(len < 1) - return ASN1_OVERRUN; - if(*p != 0) - *data = 1; - else - *data = 0; - *size = 1; - return 0; -} - int der_get_length (const unsigned char *p, size_t len, size_t *val, size_t *size) @@ -123,12 +118,28 @@ der_get_length (const unsigned char *p, size_t len, return 0; } +int +der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size) +{ + if(len < 1) + return ASN1_OVERRUN; + if(*p != 0) + *data = 1; + else + *data = 0; + *size = 1; + return 0; +} + int der_get_general_string (const unsigned char *p, size_t len, heim_general_string *str, size_t *size) { char *s; + if (len > SIZE_T_MAX - 1) + return ASN1_BAD_LENGTH; + s = malloc (len + 1); if (s == NULL) return ENOMEM; @@ -139,6 +150,70 @@ der_get_general_string (const unsigned char *p, size_t len, return 0; } +int +der_get_utf8string (const unsigned char *p, size_t len, + heim_utf8_string *str, size_t *size) +{ + return der_get_general_string(p, len, str, size); +} + +int +der_get_printable_string (const unsigned char *p, size_t len, + heim_printable_string *str, size_t *size) +{ + return der_get_general_string(p, len, str, size); +} + +int +der_get_ia5_string (const unsigned char *p, size_t len, + heim_ia5_string *str, size_t *size) +{ + return der_get_general_string(p, len, str, size); +} + +int +der_get_bmp_string (const unsigned char *p, size_t len, + heim_bmp_string *data, size_t *size) +{ + size_t i; + + if (len & 1) + return ASN1_BAD_FORMAT; + data->length = len / 2; + data->data = malloc(data->length * sizeof(data->data[0])); + if (data->data == NULL && data->length != 0) + return ENOMEM; + + for (i = 0; i < data->length; i++) { + data->data[i] = (p[0] << 8) | p[1]; + p += 2; + } + if (size) *size = len; + + return 0; +} + +int +der_get_universal_string (const unsigned char *p, size_t len, + heim_universal_string *data, size_t *size) +{ + size_t i; + + if (len & 3) + return ASN1_BAD_FORMAT; + data->length = len / 4; + data->data = malloc(data->length * sizeof(data->data[0])); + if (data->data == NULL && data->length != 0) + return ENOMEM; + + for (i = 0; i < data->length; i++) { + data->data[i] = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + p += 4; + } + if (size) *size = len; + return 0; +} + int der_get_octet_string (const unsigned char *p, size_t len, heim_octet_string *data, size_t *size) @@ -152,6 +227,108 @@ der_get_octet_string (const unsigned char *p, size_t len, return 0; } +int +der_get_heim_integer (const unsigned char *p, size_t len, + heim_integer *data, size_t *size) +{ + data->length = 0; + data->negative = 0; + data->data = NULL; + + if (len == 0) { + if (size) + *size = 0; + return 0; + } + if (p[0] & 0x80) { + data->negative = 1; + + return ASN1_OVERRUN; + } else { + data->negative = 0; + data->length = len; + + if (p[0] == 0 && data->length != 1) { + p++; + data->length--; + } + data->data = malloc(data->length); + if (data->data == NULL) { + data->length = 0; + return ENOMEM; + } + memcpy(data->data, p, data->length); + } + if (size) + *size = len; + return 0; +} + +static int +generalizedtime2time (const char *s, time_t *t) +{ + struct tm tm; + + memset(&tm, 0, sizeof(tm)); + if (sscanf (s, "%04d%02d%02d%02d%02d%02dZ", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, + &tm.tm_min, &tm.tm_sec) != 6) { + if (sscanf (s, "%02d%02d%02d%02d%02d%02dZ", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, + &tm.tm_min, &tm.tm_sec) != 6) + return ASN1_BAD_TIMEFORMAT; + if (tm.tm_year < 50) + tm.tm_year += 2000; + else + tm.tm_year += 1900; + } + tm.tm_year -= 1900; + tm.tm_mon -= 1; + *t = timegm (&tm); + return 0; +} + +static int +der_get_time (const unsigned char *p, size_t len, + time_t *data, size_t *size) +{ + heim_octet_string k; + char *times; + size_t ret = 0; + size_t l; + int e; + + e = der_get_octet_string (p, len, &k, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + times = realloc(k.data, k.length + 1); + if (times == NULL){ + free(k.data); + return ENOMEM; + } + times[k.length] = 0; + e = generalizedtime2time(times, data); + free (times); + if(size) *size = ret; + return e; +} + +int +der_get_generalized_time (const unsigned char *p, size_t len, + time_t *data, size_t *size) +{ + return der_get_time(p, len, data, size); +} + +int +der_get_utctime (const unsigned char *p, size_t len, + time_t *data, size_t *size) +{ + return der_get_time(p, len, data, size); +} + int der_get_oid (const unsigned char *p, size_t len, heim_oid *data, size_t *size) @@ -162,6 +339,9 @@ der_get_oid (const unsigned char *p, size_t len, if (len < 1) return ASN1_OVERRUN; + if (len > SIZE_T_MAX - 1) + return ASN1_BAD_LENGTH; + data->components = malloc((len + 1) * sizeof(*data->components)); if (data->components == NULL) return ENOMEM; @@ -170,15 +350,21 @@ der_get_oid (const unsigned char *p, size_t len, --len; ++p; for (n = 2; len > 0; ++n) { - unsigned u = 0; - + unsigned u = 0, u1; + do { --len; - u = u * 128 + (*p++ % 128); + u1 = u * 128 + (*p++ % 128); + /* check that we don't overflow the element */ + if (u1 < u) { + free_oid(data); + return ASN1_OVERRUN; + } + u = u1; } while (len > 0 && p[-1] & 0x80); data->components[n] = u; } - if (len > 0 && p[-1] & 0x80) { + if (n > 2 && p[-1] & 0x80) { free_oid (data); return ASN1_OVERRUN; } @@ -191,21 +377,39 @@ der_get_oid (const unsigned char *p, size_t len, int der_get_tag (const unsigned char *p, size_t len, Der_class *class, Der_type *type, - int *tag, size_t *size) + unsigned int *tag, size_t *size) { + size_t ret = 0; if (len < 1) return ASN1_OVERRUN; *class = (Der_class)(((*p) >> 6) & 0x03); *type = (Der_type)(((*p) >> 5) & 0x01); - *tag = (*p) & 0x1F; - if(size) *size = 1; + *tag = (*p) & 0x1f; + p++; len--; ret++; + if(*tag == 0x1f) { + unsigned int continuation; + unsigned int tag1; + *tag = 0; + do { + if(len < 1) + return ASN1_OVERRUN; + continuation = *p & 128; + tag1 = *tag * 128 + (*p % 128); + /* check that we don't overflow the tag */ + if (tag1 < *tag) + return ASN1_OVERFLOW; + *tag = tag1; + p++; len--; ret++; + } while(continuation); + } + if(size) *size = ret; return 0; } int der_match_tag (const unsigned char *p, size_t len, Der_class class, Der_type type, - int tag, size_t *size) + unsigned int tag, size_t *size) { size_t l; Der_class thisclass; @@ -227,7 +431,7 @@ der_match_tag (const unsigned char *p, size_t len, int der_match_tag_and_length (const unsigned char *p, size_t len, - Der_class class, Der_type type, int tag, + Der_class class, Der_type type, unsigned int tag, size_t *length_ret, size_t *size) { size_t l, ret = 0; @@ -238,7 +442,6 @@ der_match_tag_and_length (const unsigned char *p, size_t len, p += l; len -= l; ret += l; - e = der_get_length (p, len, length_ret, &l); if (e) return e; p += l; @@ -248,281 +451,21 @@ der_match_tag_and_length (const unsigned char *p, size_t len, return 0; } -int -decode_boolean (const unsigned char *p, size_t len, - int *num, size_t *size) -{ - size_t ret = 0; - size_t l, reallen; - int e; - - e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Boolean, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - - e = der_get_length (p, len, &reallen, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if (reallen > len) - return ASN1_OVERRUN; - - e = der_get_boolean (p, reallen, num, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if(size) *size = ret; - return 0; -} +/* + * Old versions of DCE was based on a very early beta of the MIT code, + * which used MAVROS for ASN.1 encoding. MAVROS had the interesting + * feature that it encoded data in the forward direction, which has + * it's problems, since you have no idea how long the data will be + * until after you're done. MAVROS solved this by reserving one byte + * for length, and later, if the actual length was longer, it reverted + * to indefinite, BER style, lengths. The version of MAVROS used by + * the DCE people could apparently generate correct X.509 DER encodings, and + * did this by making space for the length after encoding, but + * unfortunately this feature wasn't used with Kerberos. + */ int -decode_integer (const unsigned char *p, size_t len, - int *num, size_t *size) -{ - size_t ret = 0; - size_t l, reallen; - int e; - - e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Integer, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - - e = der_get_length (p, len, &reallen, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if (reallen > len) - return ASN1_OVERRUN; - - e = der_get_int (p, reallen, num, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if(size) *size = ret; - return 0; -} - -int -decode_unsigned (const unsigned char *p, size_t len, - unsigned *num, size_t *size) -{ - size_t ret = 0; - size_t l, reallen; - int e; - - e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Integer, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - - e = der_get_length (p, len, &reallen, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if (reallen > len) - return ASN1_OVERRUN; - - e = der_get_unsigned (p, reallen, num, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if(size) *size = ret; - return 0; -} - -int -decode_enumerated (const unsigned char *p, size_t len, - unsigned *num, size_t *size) -{ - size_t ret = 0; - size_t l, reallen; - int e; - - e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Enumerated, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - - e = der_get_length (p, len, &reallen, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if (reallen > len) - return ASN1_OVERRUN; - - e = der_get_int (p, reallen, num, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if(size) *size = ret; - return 0; -} - -int -decode_general_string (const unsigned char *p, size_t len, - heim_general_string *str, size_t *size) -{ - size_t ret = 0; - size_t l, reallen; - int e; - - e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_GeneralString, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - - e = der_get_length (p, len, &reallen, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if (len < reallen) - return ASN1_OVERRUN; - - e = der_get_general_string (p, reallen, str, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if(size) *size = ret; - return 0; -} - -int -decode_octet_string (const unsigned char *p, size_t len, - heim_octet_string *k, size_t *size) -{ - size_t ret = 0; - size_t l, reallen; - int e; - - e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_OctetString, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - - e = der_get_length (p, len, &reallen, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if (len < reallen) - return ASN1_OVERRUN; - - e = der_get_octet_string (p, reallen, k, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if(size) *size = ret; - return 0; -} - -int -decode_oid (const unsigned char *p, size_t len, - heim_oid *k, size_t *size) -{ - size_t ret = 0; - size_t l, reallen; - int e; - - e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_OID, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - - e = der_get_length (p, len, &reallen, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if (len < reallen) - return ASN1_OVERRUN; - - e = der_get_oid (p, reallen, k, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if(size) *size = ret; - return 0; -} - -static void -generalizedtime2time (const char *s, time_t *t) -{ - struct tm tm; - - memset(&tm, 0, sizeof(tm)); - sscanf (s, "%04d%02d%02d%02d%02d%02dZ", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, - &tm.tm_min, &tm.tm_sec); - tm.tm_year -= 1900; - tm.tm_mon -= 1; - *t = timegm (&tm); -} - -int -decode_generalized_time (const unsigned char *p, size_t len, - time_t *t, size_t *size) -{ - heim_octet_string k; - char *times; - size_t ret = 0; - size_t l, reallen; - int e; - - e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_GeneralizedTime, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - - e = der_get_length (p, len, &reallen, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - if (len < reallen) - return ASN1_OVERRUN; - - e = der_get_octet_string (p, reallen, &k, &l); - if (e) return e; - p += l; - len -= l; - ret += l; - times = realloc(k.data, k.length + 1); - if (times == NULL){ - free(k.data); - return ENOMEM; - } - times[k.length] = 0; - generalizedtime2time (times, t); - free (times); - if(size) *size = ret; - return 0; -} - - -int -fix_dce(size_t reallen, size_t *len) +_heim_fix_dce(size_t reallen, size_t *len) { if(reallen == ASN1_INDEFINITE) return 1; @@ -531,3 +474,25 @@ fix_dce(size_t reallen, size_t *len) *len = reallen; return 0; } + +int +der_get_bit_string (const unsigned char *p, size_t len, + heim_bit_string *data, size_t *size) +{ + if (len < 1) + return ASN1_OVERRUN; + if (p[0] > 7) + return ASN1_BAD_FORMAT; + if (len - 1 == 0 && p[0] != 0) + return ASN1_BAD_FORMAT; + if (len - 1 > SIZE_T_MAX / 8) + return ASN1_OVERRUN; + data->length = (len - 1) * 8; + data->data = malloc(len - 1); + if (data->data == NULL && (len - 1) != 0) + return ENOMEM; + memcpy (data->data, p + 1, len - 1); + data->length -= p[0]; + if(size) *size = len; + return 0; +} diff --git a/lib/asn1/der_length.c b/lib/asn1/der_length.c index 1166a7984..1db3b4fc8 100644 --- a/lib/asn1/der_length.c +++ b/lib/asn1/der_length.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -39,11 +39,17 @@ size_t _heim_len_unsigned (unsigned val) { size_t ret = 0; - + int last_val_gt_128; + do { ++ret; + last_val_gt_128 = (val >= 128); val /= 256; } while (val); + + if(last_val_gt_128) + ret++; + return ret; } @@ -83,12 +89,10 @@ len_oid (const heim_oid *oid) for (n = 2; n < oid->length; ++n) { unsigned u = oid->components[n]; - ++ret; - u /= 128; - while (u > 0) { + do { ++ret; u /= 128; - } + } while(u > 0); } return ret; } @@ -98,68 +102,91 @@ length_len (size_t len) { if (len < 128) return 1; - else - return _heim_len_unsigned (len) + 1; -} - -size_t -length_boolean (const int *data) -{ - return 1 + length_len(1) + 1; + else { + int ret = 0; + do { + ++ret; + len /= 256; + } while (len); + return ret + 1; + } } size_t length_integer (const int *data) { - size_t len = _heim_len_int (*data); - - return 1 + length_len(len) + len; + return _heim_len_int (*data); } size_t length_unsigned (const unsigned *data) { - unsigned val = *data; - size_t len = 0; - - while (val > 255) { - ++len; - val /= 256; - } - len++; - if (val >= 128) - len++; - return 1 + length_len(len) + len; + return _heim_len_unsigned(*data); } size_t length_enumerated (const unsigned *data) { - size_t len = _heim_len_int (*data); - - return 1 + length_len(len) + len; + return _heim_len_int (*data); } size_t length_general_string (const heim_general_string *data) { - char *str = *data; - size_t len = strlen(str); - return 1 + length_len(len) + len; + return strlen(*data); +} + +size_t +length_utf8string (const heim_utf8_string *data) +{ + return strlen(*data); +} + +size_t +length_printable_string (const heim_printable_string *data) +{ + return strlen(*data); +} + +size_t +length_ia5_string (const heim_ia5_string *data) +{ + return strlen(*data); +} + +size_t +length_bmp_string (const heim_bmp_string *data) +{ + return data->length * 2; +} + +size_t +length_universal_string (const heim_universal_string *data) +{ + return data->length * 4; } size_t length_octet_string (const heim_octet_string *k) { - return 1 + length_len(k->length) + k->length; + return k->length; +} + +size_t +length_heim_integer (const heim_integer *k) +{ + if (k->length == 0) + return 1; + if (k->negative) + return k->length + ((((unsigned char *)k->data)[0] & 0x80) ? 0 : 1); + else + return k->length + ((((unsigned char *)k->data)[0] & 0x80) ? 1 : 0); } size_t length_oid (const heim_oid *k) { - size_t len = len_oid (k); - - return 1 + length_len(len) + len; + return len_oid (k); } size_t @@ -168,8 +195,32 @@ length_generalized_time (const time_t *t) heim_octet_string k; size_t ret; - time2generalizedtime (*t, &k); - ret = 1 + length_len(k.length) + k.length; - free (k.data); + _heim_time2generalizedtime (*t, &k, 1); + ret = k.length; + free(k.data); return ret; } + +size_t +length_utctime (const time_t *t) +{ + heim_octet_string k; + size_t ret; + + _heim_time2generalizedtime (*t, &k, 0); + ret = k.length; + free(k.data); + return ret; +} + +size_t +length_boolean (const int *k) +{ + return 1; +} + +size_t +length_bit_string (const heim_bit_string *k) +{ + return (k->length + 7) / 8 + 1; +} diff --git a/lib/asn1/der_locl.h b/lib/asn1/der_locl.h index d65d06890..4b67803da 100644 --- a/lib/asn1/der_locl.h +++ b/lib/asn1/der_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2002, 2004 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -53,6 +53,10 @@ #include #include +#ifndef HAVE_TIMEGM +time_t timegm (struct tm *); +#endif + size_t _heim_len_unsigned (unsigned); size_t _heim_len_int (int); diff --git a/lib/asn1/der_put.c b/lib/asn1/der_put.c index 56469e3c2..16af8f161 100644 --- a/lib/asn1/der_put.c +++ b/lib/asn1/der_put.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -43,10 +43,11 @@ RCSID("$Id$"); * The return value is 0 or an error. */ -static int -der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size) +int +der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size) { unsigned char *base = p; + unsigned val = *v; if (val) { while (len > 0 && val) { @@ -57,6 +58,11 @@ der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size) if (val != 0) return ASN1_OVERFLOW; else { + if(p[1] >= 128) { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = 0; + } *size = base - p; return 0; } @@ -70,9 +76,10 @@ der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size) } int -der_put_int (unsigned char *p, size_t len, int val, size_t *size) +der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size) { unsigned char *base = p; + int val = *v; if(val >= 0) { do { @@ -114,22 +121,26 @@ der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) { if (len < 1) return ASN1_OVERFLOW; + if (val < 128) { *p = val; *size = 1; - return 0; } else { - size_t l; - int e; + size_t l = 0; - e = der_put_unsigned (p, len - 1, val, &l); - if (e) - return e; - p -= l; + while(val > 0) { + if(len < 2) + return ASN1_OVERFLOW; + *p-- = val % 256; + val /= 256; + len--; + l++; + } *p = 0x80 | l; - *size = l + 1; - return 0; + if(size) + *size = l + 1; } + return 0; } int @@ -160,6 +171,65 @@ der_put_general_string (unsigned char *p, size_t len, return 0; } +int +der_put_utf8string (unsigned char *p, size_t len, + const heim_utf8_string *str, size_t *size) +{ + return der_put_general_string(p, len, str, size); +} + +int +der_put_printable_string (unsigned char *p, size_t len, + const heim_printable_string *str, size_t *size) +{ + return der_put_general_string(p, len, str, size); +} + +int +der_put_ia5_string (unsigned char *p, size_t len, + const heim_ia5_string *str, size_t *size) +{ + return der_put_general_string(p, len, str, size); +} + +int +der_put_bmp_string (unsigned char *p, size_t len, + const heim_bmp_string *data, size_t *size) +{ + size_t i; + if (len / 2 < data->length) + return ASN1_OVERFLOW; + p -= data->length * 2; + len -= data->length * 2; + for (i = 0; i < data->length; i++) { + p[1] = (data->data[i] >> 8) & 0xff; + p[2] = data->data[i] & 0xff; + p += 2; + } + if (size) *size = data->length * 2; + return 0; +} + +int +der_put_universal_string (unsigned char *p, size_t len, + const heim_universal_string *data, size_t *size) +{ + size_t i; + if (len / 4 < data->length) + return ASN1_OVERFLOW; + p -= data->length * 4; + len -= data->length * 4; + for (i = 0; i < data->length; i++) { + p[1] = (data->data[i] >> 24) & 0xff; + p[2] = (data->data[i] >> 16) & 0xff; + p[3] = (data->data[i] >> 8) & 0xff; + p[4] = data->data[i] & 0xff; + p += 4; + } + if (size) *size = data->length * 4; + return 0; +} + int der_put_octet_string (unsigned char *p, size_t len, const heim_octet_string *data, size_t *size) @@ -173,6 +243,98 @@ der_put_octet_string (unsigned char *p, size_t len, return 0; } +int +der_put_heim_integer (unsigned char *p, size_t len, + const heim_integer *data, size_t *size) +{ + unsigned char *buf = data->data; + int hibitset = 0; + + if (data->length == 0) { + if (len < 1) + return ASN1_OVERFLOW; + *p-- = 0; + if (size) + *size = 1; + return 0; + } + if (len < data->length) + return ASN1_OVERFLOW; + + len -= data->length; + + if (data->negative) { + int i, carry; + for (i = data->length - 1, carry = 1; i >= 0; i--) { + *p = buf[i] ^ 0xff; + if (carry) + carry = !++*p; + p--; + } + if (p[1] < 128) { + if (len < 1) + return ASN1_OVERFLOW; + *p-- = 0xff; + len--; + hibitset = 1; + } + } else { + p -= data->length; + memcpy(p + 1, buf, data->length); + + if (p[1] >= 128) { + if (len < 1) + return ASN1_OVERFLOW; + p[0] = 0; + len--; + hibitset = 1; + } + } + if (size) + *size = data->length + hibitset; + return 0; +} + +int +der_put_generalized_time (unsigned char *p, size_t len, + const time_t *data, size_t *size) +{ + heim_octet_string k; + size_t l; + int e; + + e = _heim_time2generalizedtime (*data, &k, 1); + if (e) + return e; + e = der_put_octet_string(p, len, &k, &l); + free(k.data); + if(e) + return e; + if(size) + *size = l; + return 0; +} + +int +der_put_utctime (unsigned char *p, size_t len, + const time_t *data, size_t *size) +{ + heim_octet_string k; + size_t l; + int e; + + e = _heim_time2generalizedtime (*data, &k, 0); + if (e) + return e; + e = der_put_octet_string(p, len, &k, &l); + free(k.data); + if(e) + return e; + if(size) + *size = l; + return 0; +} + int der_put_oid (unsigned char *p, size_t len, const heim_oid *data, size_t *size) @@ -205,18 +367,39 @@ der_put_oid (unsigned char *p, size_t len, int der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, - int tag, size_t *size) + unsigned int tag, size_t *size) { - if (len < 1) - return ASN1_OVERFLOW; - *p = (class << 6) | (type << 5) | tag; /* XXX */ - *size = 1; + if (tag <= 30) { + if (len < 1) + return ASN1_OVERFLOW; + *p = MAKE_TAG(class, type, tag); + *size = 1; + } else { + size_t ret = 0; + unsigned int continuation = 0; + + do { + if (len < 1) + return ASN1_OVERFLOW; + *p-- = tag % 128 | continuation; + len--; + ret++; + tag /= 128; + continuation = 0x80; + } while(tag > 0); + if (len < 1) + return ASN1_OVERFLOW; + *p-- = MAKE_TAG(class, type, 0x1f); + ret++; + *size = ret; + } return 0; } int der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, - Der_class class, Der_type type, int tag, size_t *size) + Der_class class, Der_type type, + unsigned int tag, size_t *size) { size_t ret = 0; size_t l; @@ -239,229 +422,55 @@ der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, } int -encode_boolean (unsigned char *p, size_t len, const int *data, - size_t *size) -{ - size_t ret = 0; - size_t l; - int e; - - e = der_put_boolean (p, len, data, &l); - if(e) - return e; - p -= l; - len -= l; - ret += l; - e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Boolean, &l); - if (e) - return e; - p -= l; - len -= l; - ret += l; - *size = ret; - return 0; -} - -int -encode_integer (unsigned char *p, size_t len, const int *data, size_t *size) -{ - int num = *data; - size_t ret = 0; - size_t l; - int e; - - e = der_put_int (p, len, num, &l); - if(e) - return e; - p -= l; - len -= l; - ret += l; - e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Integer, &l); - if (e) - return e; - p -= l; - len -= l; - ret += l; - *size = ret; - return 0; -} - -int -encode_unsigned (unsigned char *p, size_t len, const unsigned *data, - size_t *size) -{ - unsigned num = *data; - size_t ret = 0; - size_t l; - int e; - - e = der_put_unsigned (p, len, num, &l); - if(e) - return e; - p -= l; - len -= l; - ret += l; - /* if first octet has msb set, we need to pad with a zero byte */ - if(p[1] >= 128) { - if(len == 0) - return ASN1_OVERFLOW; - *p-- = 0; - len--; - ret++; - l++; - } - e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Integer, &l); - if (e) - return e; - p -= l; - len -= l; - ret += l; - *size = ret; - return 0; -} - -int -encode_enumerated (unsigned char *p, size_t len, const unsigned *data, - size_t *size) -{ - unsigned num = *data; - size_t ret = 0; - size_t l; - int e; - - e = der_put_int (p, len, num, &l); - if(e) - return e; - p -= l; - len -= l; - ret += l; - e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Enumerated, &l); - if (e) - return e; - p -= l; - len -= l; - ret += l; - *size = ret; - return 0; -} - -int -encode_general_string (unsigned char *p, size_t len, - const heim_general_string *data, size_t *size) -{ - size_t ret = 0; - size_t l; - int e; - - e = der_put_general_string (p, len, data, &l); - if (e) - return e; - p -= l; - len -= l; - ret += l; - e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_GeneralString, &l); - if (e) - return e; - p -= l; - len -= l; - ret += l; - *size = ret; - return 0; -} - -int -encode_octet_string (unsigned char *p, size_t len, - const heim_octet_string *k, size_t *size) -{ - size_t ret = 0; - size_t l; - int e; - - e = der_put_octet_string (p, len, k, &l); - if (e) - return e; - p -= l; - len -= l; - ret += l; - e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_OctetString, &l); - if (e) - return e; - p -= l; - len -= l; - ret += l; - *size = ret; - return 0; -} - -int -encode_oid(unsigned char *p, size_t len, - const heim_oid *k, size_t *size) -{ - size_t ret = 0; - size_t l; - int e; - - e = der_put_oid (p, len, k, &l); - if (e) - return e; - p -= l; - len -= l; - ret += l; - e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_OID, &l); - if (e) - return e; - p -= l; - len -= l; - ret += l; - *size = ret; - return 0; -} - -int -time2generalizedtime (time_t t, heim_octet_string *s) +_heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep) { struct tm *tm; - size_t len; - - len = 15; + const size_t len = gtimep ? 15 : 13; s->data = malloc(len + 1); if (s->data == NULL) return ENOMEM; s->length = len; tm = gmtime (&t); - snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); + if (gtimep) + snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + else + snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ", + tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + return 0; } int -encode_generalized_time (unsigned char *p, size_t len, - const time_t *t, size_t *size) +der_put_bit_string (unsigned char *p, size_t len, + const heim_bit_string *data, size_t *size) { - size_t ret = 0; - size_t l; - heim_octet_string k; - int e; - - e = time2generalizedtime (*t, &k); - if (e) - return e; - e = der_put_octet_string (p, len, &k, &l); - free (k.data); - if (e) - return e; - p -= l; - len -= l; - ret += l; - e = der_put_length_and_tag (p, len, k.length, ASN1_C_UNIV, PRIM, - UT_GeneralizedTime, &l); - if (e) - return e; - p -= l; - len -= l; - ret += l; - *size = ret; + size_t data_size = (data->length + 7) / 8; + if (len < data_size + 1) + return ASN1_OVERFLOW; + p -= data_size + 1; + len -= data_size + 1; + memcpy (p+2, data->data, data_size); + if (data->length && (data->length % 8) != 0) + p[1] = 8 - (data->length % 8); + else + p[1] = 0; + *size = data_size + 1; return 0; } + +int +_heim_der_set_sort(const void *a1, const void *a2) +{ + const struct heim_octet_string *s1 = a1, *s2 = a2; + int ret; + + ret = memcmp(s1->data, s2->data, + s1->length < s2->length ? s1->length : s2->length); + if(ret) + return ret; + return s1->length - s2->length; +} diff --git a/lib/asn1/extra.c b/lib/asn1/extra.c index 76e864ec4..e325eb263 100644 --- a/lib/asn1/extra.c +++ b/lib/asn1/extra.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Kungliga Tekniska Högskolan + * Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -103,7 +103,7 @@ int copy_heim_any(const heim_any *from, heim_any *to) { to->data = malloc(from->length); - if (to->data == NULL) + if (to->data == NULL && from->length != 0) return ENOMEM; memcpy(to->data, from->data, from->length); to->length = from->length; @@ -124,7 +124,7 @@ decode_heim_any_set(const unsigned char *p, size_t len, { memset(data, 0, sizeof(*data)); data->data = malloc(len); - if (data->data == NULL) + if (data->data == NULL && len != 0) return ENOMEM; data->length = len; memcpy(data->data, p, len); @@ -149,3 +149,11 @@ copy_heim_any_set(const heim_any_set *from, heim_any_set *to) { return copy_heim_any(from, to); } + +int +heim_any_cmp(const heim_any_set *p, const heim_any_set *q) +{ + if (p->length != q->length) + return p->length - q->length; + return memcmp(p->data, q->data, p->length); +} diff --git a/lib/asn1/gen.c b/lib/asn1/gen.c index 4812ba3d2..826b0e9ca 100644 --- a/lib/asn1/gen.c +++ b/lib/asn1/gen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -41,7 +41,7 @@ FILE *headerfile, *codefile, *logfile; static const char *orig_filename; static char *header; -static char *headerbase; +static char *headerbase = STEM; /* * list of all IMPORTs @@ -70,29 +70,20 @@ get_filename (void) return orig_filename; } -static int unique_number; - -void -unique_reset(void) -{ - unique_number = 0; -} - -int -unique_get_next(void) -{ - return unique_number++; -} - void init_generate (const char *filename, const char *base) { + char *fn; + orig_filename = filename; - if(base) + if (base != NULL) { asprintf(&headerbase, "%s", base); - else - headerbase = strdup(STEM); + if (headerbase == NULL) + errx(1, "malloc"); + } asprintf(&header, "%s.h", headerbase); + if (header == NULL) + errx(1, "malloc"); headerfile = fopen (header, "w"); if (headerfile == NULL) err (1, "open %s", header); @@ -112,6 +103,12 @@ init_generate (const char *filename, const char *base) fprintf (headerfile, "#ifndef __asn1_common_definitions__\n" "#define __asn1_common_definitions__\n\n"); + fprintf (headerfile, + "typedef struct heim_integer {\n" + " size_t length;\n" + " void *data;\n" + " int negative;\n" + "} heim_integer;\n\n"); fprintf (headerfile, "typedef struct heim_octet_string {\n" " size_t length;\n" @@ -123,11 +120,32 @@ init_generate (const char *filename, const char *base) fprintf (headerfile, "typedef char *heim_utf8_string;\n\n" ); + fprintf (headerfile, + "typedef char *heim_printable_string;\n\n" + ); + fprintf (headerfile, + "typedef char *heim_ia5_string;\n\n" + ); + fprintf (headerfile, + "typedef struct heim_bmp_string {\n" + " size_t length;\n" + " uint16_t *data;\n" + "} heim_bmp_string;\n\n"); + fprintf (headerfile, + "typedef struct heim_universal_string {\n" + " size_t length;\n" + " uint32_t *data;\n" + "} heim_universal_string;\n\n"); fprintf (headerfile, "typedef struct heim_oid {\n" " size_t length;\n" " unsigned *components;\n" "} heim_oid;\n\n"); + fprintf (headerfile, + "typedef struct heim_bit_string {\n" + " size_t length;\n" + " void *data;\n" + "} heim_bit_string;\n\n"); fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n" " do { \\\n" " (BL) = length_##T((S)); \\\n" @@ -145,9 +163,12 @@ init_generate (const char *filename, const char *base) " } while (0)\n\n", headerfile); fprintf (headerfile, "#endif\n\n"); - logfile = fopen(STEM "_files", "w"); + asprintf(&fn, "%s_files", base); + if (fn == NULL) + errx(1, "malloc"); + logfile = fopen(fn, "w"); if (logfile == NULL) - err (1, "open " STEM "_files"); + err (1, "open %s", fn); } void @@ -161,310 +182,59 @@ close_generate (void) } void -generate_constant (const Symbol *s) +gen_assign_defval(const char *var, struct value *val) { - fprintf (headerfile, "enum { %s = %d };\n\n", - s->gen_name, s->constant); -} - -static void -space(int level) -{ - while(level-- > 0) - fprintf(headerfile, " "); -} - -static void -define_asn1 (int level, Type *t) -{ - switch (t->type) { - case TType: - space(level); - fprintf (headerfile, "%s", t->symbol->name); + switch(val->type) { + case stringvalue: + fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue); break; - case TInteger: - space(level); - fprintf (headerfile, "INTEGER"); + case integervalue: + fprintf(codefile, "%s = %d;\n", var, val->u.integervalue); break; - case TUInteger: - space(level); - fprintf (headerfile, "UNSIGNED INTEGER"); - break; - case TOctetString: - space(level); - fprintf (headerfile, "OCTET STRING"); - break; - case TOID : - space(level); - fprintf(headerfile, "OBJECT IDENTIFIER"); - break; - case TBitString: { - Member *m; - int tag = -1; - - space(level); - fprintf (headerfile, "BIT STRING {\n"); - for (m = t->members; m && m->val != tag; m = m->next) { - if (tag == -1) - tag = m->val; - space(level + 1); - fprintf (headerfile, "%s(%d)%s\n", m->name, m->val, - m->next->val == tag?"":","); - - } - space(level); - fprintf (headerfile, "}"); - break; - } - case TEnumerated : { - Member *m; - int tag = -1; - - space(level); - fprintf (headerfile, "ENUMERATED {\n"); - for (m = t->members; m && m->val != tag; m = m->next) { - if (tag == -1) - tag = m->val; - space(level + 1); - fprintf (headerfile, "%s(%d)%s\n", m->name, m->val, - m->next->val == tag?"":","); - - } - space(level); - fprintf (headerfile, "}"); - break; - } - case TSequence: { - Member *m; - int tag; - int max_width = 0; - - space(level); - fprintf (headerfile, "SEQUENCE {\n"); - for (m = t->members, tag = -1; m && m->val != tag; m = m->next) { - if (tag == -1) - tag = m->val; - if(strlen(m->name) + (m->val > 9) > max_width) - max_width = strlen(m->name) + (m->val > 9); - } - max_width += 3 + 2; - if(max_width < 16) max_width = 16; - for (m = t->members, tag = -1 ; m && m->val != tag; m = m->next) { - int width; - if (tag == -1) - tag = m->val; - space(level + 1); - fprintf(headerfile, "%s[%d]", m->name, m->val); - width = max_width - strlen(m->name) - 3 - (m->val > 9) - 2; - fprintf(headerfile, "%*s", width, ""); - define_asn1(level + 1, m->type); - if(m->optional) - fprintf(headerfile, " OPTIONAL"); - if(m->next->val != tag) - fprintf (headerfile, ","); - fprintf (headerfile, "\n"); - } - space(level); - fprintf (headerfile, "}"); - break; - } - case TSequenceOf: { - space(level); - fprintf (headerfile, "SEQUENCE OF "); - define_asn1 (0, t->subtype); - break; - } - case TGeneralizedTime: - space(level); - fprintf (headerfile, "GeneralizedTime"); - break; - case TGeneralString: - space(level); - fprintf (headerfile, "GeneralString"); - break; - case TApplication: - fprintf (headerfile, "[APPLICATION %d] ", t->application); - define_asn1 (level, t->subtype); - break; - case TBoolean: - space(level); - fprintf (headerfile, "BOOLEAN"); - break; - case TUTF8String: - space(level); - fprintf (headerfile, "UTF8String"); - break; - case TNull: - space(level); - fprintf (headerfile, "NULL"); + case booleanvalue: + if(val->u.booleanvalue) + fprintf(codefile, "%s = TRUE;\n", var); + else + fprintf(codefile, "%s = FALSE;\n", var); break; default: - abort (); + abort(); } } -static void -define_type (int level, const char *name, Type *t, int typedefp) -{ - switch (t->type) { - case TType: - space(level); - fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name); - break; - case TInteger: - space(level); - if(t->members == NULL) { - fprintf (headerfile, "int %s;\n", name); - } else { - Member *m; - int tag = -1; - fprintf (headerfile, "enum %s {\n", typedefp ? name : ""); - for (m = t->members; m && m->val != tag; m = m->next) { - if(tag == -1) - tag = m->val; - space (level + 1); - fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val, - m->next->val == tag ? "" : ","); - } - fprintf (headerfile, "} %s;\n", name); - } - break; - case TUInteger: - space(level); - fprintf (headerfile, "unsigned int %s;\n", name); - break; - case TOctetString: - space(level); - fprintf (headerfile, "heim_octet_string %s;\n", name); - break; - case TOID : - space(level); - fprintf (headerfile, "heim_oid %s;\n", name); - break; - case TBitString: { - Member *m; - Type i; - int tag = -1; - - i.type = TUInteger; - space(level); - fprintf (headerfile, "struct %s {\n", typedefp ? name : ""); - for (m = t->members; m && m->val != tag; m = m->next) { - char *n; - - asprintf (&n, "%s:1", m->gen_name); - define_type (level + 1, n, &i, FALSE); - free (n); - if (tag == -1) - tag = m->val; - } - space(level); - fprintf (headerfile, "} %s;\n\n", name); - break; - } - case TEnumerated: { - Member *m; - int tag = -1; - - space(level); - fprintf (headerfile, "enum %s {\n", typedefp ? name : ""); - for (m = t->members; m && m->val != tag; m = m->next) { - if (tag == -1) - tag = m->val; - space(level + 1); - fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val, - m->next->val == tag ? "" : ","); - } - space(level); - fprintf (headerfile, "} %s;\n\n", name); - break; - } - case TSequence: { - Member *m; - int tag = -1; - - space(level); - fprintf (headerfile, "struct %s {\n", typedefp ? name : ""); - for (m = t->members; m && m->val != tag; m = m->next) { - if (m->optional) { - char *n; - - asprintf (&n, "*%s", m->gen_name); - define_type (level + 1, n, m->type, FALSE); - free (n); - } else - define_type (level + 1, m->gen_name, m->type, FALSE); - if (tag == -1) - tag = m->val; - } - space(level); - fprintf (headerfile, "} %s;\n", name); - break; - } - case TSequenceOf: { - Type i; - - i.type = TUInteger; - i.application = 0; - - space(level); - fprintf (headerfile, "struct %s {\n", typedefp ? name : ""); - define_type (level + 1, "len", &i, FALSE); - define_type (level + 1, "*val", t->subtype, FALSE); - space(level); - fprintf (headerfile, "} %s;\n", name); - break; - } - case TGeneralizedTime: - space(level); - fprintf (headerfile, "time_t %s;\n", name); - break; - case TGeneralString: - space(level); - fprintf (headerfile, "heim_general_string %s;\n", name); - break; - case TUTF8String: - space(level); - fprintf (headerfile, "heim_utf8_string %s;\n", name); - break; - case TBoolean: - space(level); - fprintf (headerfile, "int %s;\n", name); - break; - case TNull: - space(level); - fprintf (headerfile, "NULL %s;\n", name); - break; - case TApplication: - define_type (level, name, t->subtype, FALSE); - break; - default: - abort (); - } -} - -static void -generate_type_header (const Symbol *s) -{ - fprintf (headerfile, "/*\n"); - fprintf (headerfile, "%s ::= ", s->name); - define_asn1 (0, s->type); - fprintf (headerfile, "\n*/\n\n"); - - fprintf (headerfile, "typedef "); - define_type (0, s->gen_name, s->type, TRUE); - - fprintf (headerfile, "\n"); -} - - void -generate_type (const Symbol *s) +gen_compare_defval(const char *var, struct value *val) +{ + switch(val->type) { + case stringvalue: + fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue); + break; + case integervalue: + fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue); + break; + case booleanvalue: + if(val->u.booleanvalue) + fprintf(codefile, "if(!%s)\n", var); + else + fprintf(codefile, "if(%s)\n", var); + break; + default: + abort(); + } +} + +static void +generate_header_of_codefile(const char *name) { struct import *i; char *filename; - asprintf (&filename, "%s_%s.x", STEM, s->gen_name); + if (codefile != NULL) + abort(); + + asprintf (&filename, "%s_%s.x", STEM, name); + if (filename == NULL) + errx(1, "malloc"); codefile = fopen (filename, "w"); if (codefile == NULL) err (1, "fopen %s", filename); @@ -477,7 +247,8 @@ generate_type (const Symbol *s) "#include \n" "#include \n" "#include \n" - "#include \n", + "#include \n" + "#include \n", orig_filename); for (i = imports; i != NULL; i = i->next) @@ -492,19 +263,522 @@ generate_type (const Symbol *s) "#include \n" "#include \n\n"); - if (s->stype == Stype && s->type->type == TChoice) { - fprintf(codefile, - "/* CHOICE */\n" - "int asn1_%s_dummy_holder = 1;\n", s->gen_name); - } else { - generate_type_header (s); - generate_type_encode (s); - generate_type_decode (s); - generate_type_free (s); - generate_type_length (s); - generate_type_copy (s); - generate_glue (s); - } - fprintf(headerfile, "\n\n"); - fclose(codefile); +} + +static void +close_codefile(void) +{ + if (codefile == NULL) + abort(); + + fclose(codefile); + codefile = NULL; +} + + +void +generate_constant (const Symbol *s) +{ + switch(s->value->type) { + case booleanvalue: + break; + case integervalue: + fprintf (headerfile, "enum { %s = %d };\n\n", + s->gen_name, s->value->u.integervalue); + break; + case nullvalue: + break; + case stringvalue: + break; + case objectidentifiervalue: { + struct objid *o, **list; + int i, len; + + generate_header_of_codefile(s->gen_name); + + len = 0; + for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next) + len++; + list = emalloc(sizeof(*list) * len); + + i = 0; + for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next) + list[i++] = o; + + fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name); + for (i = len - 1 ; i >= 0; i--) { + o = list[i]; + fprintf(headerfile, "%s(%d) ", + o->label ? o->label : "label-less", o->value); + } + + fprintf (headerfile, "} */\n"); + fprintf (headerfile, "const heim_oid *oid_%s(void);\n\n", + s->gen_name); + + fprintf (codefile, "static int oid_%s_variable_num[%d] = {", + s->gen_name, len); + for (i = len - 1 ; i >= 0; i--) { + fprintf(codefile, "%d%s ", list[i]->value, i > 0 ? "," : ""); + } + fprintf(codefile, "};\n"); + + fprintf (codefile, "static const heim_oid oid_%s_variable = " + "{ %d, oid_%s_variable_num };\n\n", + s->gen_name, len, s->gen_name); + + fprintf (codefile, "const heim_oid *oid_%s(void)\n" + "{\n" + "return &oid_%s_variable;\n" + "}\n\n", + s->gen_name, s->gen_name); + + close_codefile(); + + break; + } + default: + abort(); + } +} + +static void +space(int level) +{ + while(level-- > 0) + fprintf(headerfile, " "); +} + +static char * +last_member_p(struct member *m) +{ + struct member *n = ASN1_TAILQ_NEXT(m, members); + if (n == NULL) + return ""; + if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL) + return ""; + return ","; +} + +static struct member * +have_ellipsis(Type *t) +{ + struct member *m; + ASN1_TAILQ_FOREACH(m, t->members, members) { + if (m->ellipsis) + return m; + } + return NULL; +} + +static void +define_asn1 (int level, Type *t) +{ + switch (t->type) { + case TType: + fprintf (headerfile, "%s", t->symbol->name); + break; + case TInteger: + if(t->members == NULL) { + fprintf (headerfile, "INTEGER"); + if (t->range) + fprintf (headerfile, " (%d..%d)", + t->range->min, t->range->max); + } else { + Member *m; + fprintf (headerfile, "INTEGER {\n"); + ASN1_TAILQ_FOREACH(m, t->members, members) { + space (level + 1); + fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val, + last_member_p(m)); + } + space(level); + fprintf (headerfile, "}"); + } + break; + case TBoolean: + fprintf (headerfile, "BOOLEAN"); + break; + case TOctetString: + fprintf (headerfile, "OCTET STRING"); + break; + case TEnumerated : + case TBitString: { + Member *m; + + space(level); + if(t->type == TBitString) + fprintf (headerfile, "BIT STRING {\n"); + else + fprintf (headerfile, "ENUMERATED {\n"); + ASN1_TAILQ_FOREACH(m, t->members, members) { + space(level + 1); + fprintf (headerfile, "%s(%d)%s\n", m->name, m->val, + last_member_p(m)); + } + space(level); + fprintf (headerfile, "}"); + break; + } + case TChoice: + case TSet: + case TSequence: { + Member *m; + int max_width = 0; + + if(t->type == TChoice) + fprintf(headerfile, "CHOICE {\n"); + else if(t->type == TSet) + fprintf(headerfile, "SET {\n"); + else + fprintf(headerfile, "SEQUENCE {\n"); + ASN1_TAILQ_FOREACH(m, t->members, members) { + if(strlen(m->name) > max_width) + max_width = strlen(m->name); + } + max_width += 3; + if(max_width < 16) max_width = 16; + ASN1_TAILQ_FOREACH(m, t->members, members) { + int width = max_width; + space(level + 1); + if (m->ellipsis) { + fprintf (headerfile, "..."); + } else { + width -= fprintf(headerfile, "%s", m->name); + fprintf(headerfile, "%*s", width, ""); + define_asn1(level + 1, m->type); + if(m->optional) + fprintf(headerfile, " OPTIONAL"); + } + if(last_member_p(m)) + fprintf (headerfile, ","); + fprintf (headerfile, "\n"); + } + space(level); + fprintf (headerfile, "}"); + break; + } + case TSequenceOf: + fprintf (headerfile, "SEQUENCE OF "); + define_asn1 (0, t->subtype); + break; + case TSetOf: + fprintf (headerfile, "SET OF "); + define_asn1 (0, t->subtype); + break; + case TGeneralizedTime: + fprintf (headerfile, "GeneralizedTime"); + break; + case TGeneralString: + fprintf (headerfile, "GeneralString"); + break; + case TTag: { + const char *classnames[] = { "UNIVERSAL ", "APPLICATION ", + "" /* CONTEXT */, "PRIVATE " }; + if(t->tag.tagclass != ASN1_C_UNIV) + fprintf (headerfile, "[%s%d] ", + classnames[t->tag.tagclass], + t->tag.tagvalue); + if(t->tag.tagenv == TE_IMPLICIT) + fprintf (headerfile, "IMPLICIT "); + define_asn1 (level, t->subtype); + break; + } + case TUTCTime: + fprintf (headerfile, "UTCTime"); + break; + case TUTF8String: + space(level); + fprintf (headerfile, "UTF8String"); + break; + case TPrintableString: + space(level); + fprintf (headerfile, "PrintableString"); + break; + case TIA5String: + space(level); + fprintf (headerfile, "IA5String"); + break; + case TBMPString: + space(level); + fprintf (headerfile, "BMPString"); + break; + case TUniversalString: + space(level); + fprintf (headerfile, "UniversalString"); + break; + case TOID : + space(level); + fprintf(headerfile, "OBJECT IDENTIFIER"); + break; + case TNull: + space(level); + fprintf (headerfile, "NULL"); + break; + default: + abort (); + } +} + +static void +define_type (int level, char *name, Type *t, int typedefp, int preservep) +{ + switch (t->type) { + case TType: + space(level); + fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name); + break; + case TInteger: + space(level); + if(t->members) { + Member *m; + fprintf (headerfile, "enum %s {\n", typedefp ? name : ""); + ASN1_TAILQ_FOREACH(m, t->members, members) { + space (level + 1); + fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val, + last_member_p(m)); + } + fprintf (headerfile, "} %s;\n", name); + } else if (t->range == NULL) { + fprintf (headerfile, "heim_integer %s;\n", name); + } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { + fprintf (headerfile, "int %s;\n", name); + } else if (t->range->min == 0 && t->range->max == UINT_MAX) { + fprintf (headerfile, "unsigned int %s;\n", name); + } else if (t->range->min == 0 && t->range->max == INT_MAX) { + fprintf (headerfile, "unsigned int %s;\n", name); + } else + errx(1, "%s: unsupported range %d -> %d", + name, t->range->min, t->range->max); + break; + case TBoolean: + space(level); + fprintf (headerfile, "int %s;\n", name); + break; + case TOctetString: + space(level); + fprintf (headerfile, "heim_octet_string %s;\n", name); + break; + case TBitString: { + Member *m; + Type i; + struct range range = { 0, INT_MAX }; + + i.type = TInteger; + i.range = ⦥ + i.members = NULL; + + space(level); + if(ASN1_TAILQ_EMPTY(t->members)) + fprintf (headerfile, "heim_bit_string %s;\n", name); + else { + fprintf (headerfile, "struct %s {\n", typedefp ? name : ""); + ASN1_TAILQ_FOREACH(m, t->members, members) { + char *n; + + asprintf (&n, "%s:1", m->gen_name); + if (n == NULL) + errx(1, "malloc"); + define_type (level + 1, n, &i, FALSE, FALSE); + free (n); + } + space(level); + fprintf (headerfile, "} %s;\n\n", name); + } + break; + } + case TEnumerated: { + Member *m; + + space(level); + fprintf (headerfile, "enum %s {\n", typedefp ? name : ""); + ASN1_TAILQ_FOREACH(m, t->members, members) { + space(level + 1); + if (m->ellipsis) + fprintf (headerfile, "/* ... */\n"); + else + fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val, + last_member_p(m)); + } + space(level); + fprintf (headerfile, "} %s;\n\n", name); + break; + } + case TSet: + case TSequence: { + Member *m; + + space(level); + fprintf (headerfile, "struct %s {\n", typedefp ? name : ""); + if (t->type == TSequence && preservep) { + space(level + 1); + fprintf(headerfile, "heim_octet_string _save;\n"); + } + ASN1_TAILQ_FOREACH(m, t->members, members) { + if (m->ellipsis) { + ; + } else if (m->optional) { + char *n; + + asprintf (&n, "*%s", m->gen_name); + if (n == NULL) + errx(1, "malloc"); + define_type (level + 1, n, m->type, FALSE, FALSE); + free (n); + } else + define_type (level + 1, m->gen_name, m->type, FALSE, FALSE); + } + space(level); + fprintf (headerfile, "} %s;\n", name); + break; + } + case TSetOf: + case TSequenceOf: { + Type i; + struct range range = { 0, INT_MAX }; + + i.type = TInteger; + i.range = ⦥ + i.members = NULL; + + space(level); + fprintf (headerfile, "struct %s {\n", typedefp ? name : ""); + define_type (level + 1, "len", &i, FALSE, FALSE); + define_type (level + 1, "*val", t->subtype, FALSE, FALSE); + space(level); + fprintf (headerfile, "} %s;\n", name); + break; + } + case TGeneralizedTime: + space(level); + fprintf (headerfile, "time_t %s;\n", name); + break; + case TGeneralString: + space(level); + fprintf (headerfile, "heim_general_string %s;\n", name); + break; + case TTag: + define_type (level, name, t->subtype, typedefp, preservep); + break; + case TChoice: { + int first = 1; + Member *m; + + space(level); + fprintf (headerfile, "struct %s {\n", typedefp ? name : ""); + if (preservep) { + space(level + 1); + fprintf(headerfile, "heim_octet_string _save;\n"); + } + space(level + 1); + fprintf (headerfile, "enum {\n"); + m = have_ellipsis(t); + if (m) { + space(level + 2); + fprintf (headerfile, "%s = 0,\n", m->label); + first = 0; + } + ASN1_TAILQ_FOREACH(m, t->members, members) { + space(level + 2); + if (m->ellipsis) + fprintf (headerfile, "/* ... */\n"); + else + fprintf (headerfile, "%s%s%s\n", m->label, + first ? " = 1" : "", + last_member_p(m)); + first = 0; + } + space(level + 1); + fprintf (headerfile, "} element;\n"); + space(level + 1); + fprintf (headerfile, "union {\n"); + ASN1_TAILQ_FOREACH(m, t->members, members) { + if (m->ellipsis) { + space(level + 2); + fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n"); + } else if (m->optional) { + char *n; + + asprintf (&n, "*%s", m->gen_name); + if (n == NULL) + errx(1, "malloc"); + define_type (level + 2, n, m->type, FALSE, FALSE); + free (n); + } else + define_type (level + 2, m->gen_name, m->type, FALSE, FALSE); + } + space(level + 1); + fprintf (headerfile, "} u;\n"); + space(level); + fprintf (headerfile, "} %s;\n", name); + break; + } + case TUTCTime: + space(level); + fprintf (headerfile, "time_t %s;\n", name); + break; + case TUTF8String: + space(level); + fprintf (headerfile, "heim_utf8_string %s;\n", name); + break; + case TPrintableString: + space(level); + fprintf (headerfile, "heim_printable_string %s;\n", name); + break; + case TIA5String: + space(level); + fprintf (headerfile, "heim_ia5_string %s;\n", name); + break; + case TBMPString: + space(level); + fprintf (headerfile, "heim_bmp_string %s;\n", name); + break; + case TUniversalString: + space(level); + fprintf (headerfile, "heim_universal_string %s;\n", name); + break; + case TOID : + space(level); + fprintf (headerfile, "heim_oid %s;\n", name); + break; + case TNull: + space(level); + fprintf (headerfile, "int %s;\n", name); + break; + default: + abort (); + } +} + +static void +generate_type_header (const Symbol *s) +{ + int preservep = preserve_type(s->name) ? TRUE : FALSE; + + fprintf (headerfile, "/*\n"); + fprintf (headerfile, "%s ::= ", s->name); + define_asn1 (0, s->type); + fprintf (headerfile, "\n*/\n\n"); + + fprintf (headerfile, "typedef "); + define_type (0, s->gen_name, s->type, TRUE, preservep); + + fprintf (headerfile, "\n"); +} + + +void +generate_type (const Symbol *s) +{ + generate_header_of_codefile(s->gen_name); + + generate_type_header (s); + generate_type_encode (s); + generate_type_decode (s); + generate_type_free (s); + generate_type_length (s); + generate_type_copy (s); + generate_glue (s->type, s->gen_name); + fprintf(headerfile, "\n\n"); + close_codefile(); } diff --git a/lib/asn1/gen_copy.c b/lib/asn1/gen_copy.c index 6f8a4bac4..601f2830a 100644 --- a/lib/asn1/gen_copy.c +++ b/lib/asn1/gen_copy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -35,123 +35,212 @@ RCSID("$Id$"); +static int used_fail; + static void copy_primitive (const char *typename, const char *from, const char *to) { - fprintf (codefile, "if(copy_%s(%s, %s)) return ENOMEM;\n", + fprintf (codefile, "if(copy_%s(%s, %s)) goto fail;\n", typename, from, to); + used_fail++; } static void -copy_type (const char *from, const char *to, const Type *t) +copy_type (const char *from, const char *to, const Type *t, int preserve) { - switch (t->type) { - case TType: + switch (t->type) { + case TType: #if 0 - copy_type (from, to, t->symbol->type); + copy_type (from, to, t->symbol->type, preserve); #endif - fprintf (codefile, "if(copy_%s(%s, %s)) return ENOMEM;\n", - t->symbol->gen_name, from, to); - break; - case TInteger: - case TUInteger: - case TBoolean: - case TEnumerated : - fprintf(codefile, "*(%s) = *(%s);\n", to, from); - break; - case TOctetString: - copy_primitive ("octet_string", from, to); - break; - case TOID: - copy_primitive ("oid", from, to); - break; - case TBitString: { - fprintf(codefile, "*(%s) = *(%s);\n", to, from); - break; - } - case TSequence: { - Member *m; - int tag = -1; + fprintf (codefile, "if(copy_%s(%s, %s)) goto fail;\n", + t->symbol->gen_name, from, to); + used_fail++; + break; + case TInteger: + if (t->range == NULL && t->members == NULL) { + copy_primitive ("heim_integer", from, to); + break; + } + case TBoolean: + case TEnumerated : + fprintf(codefile, "*(%s) = *(%s);\n", to, from); + break; + case TOctetString: + copy_primitive ("octet_string", from, to); + break; + case TBitString: + if (ASN1_TAILQ_EMPTY(t->members)) + copy_primitive ("bit_string", from, to); + else + fprintf(codefile, "*(%s) = *(%s);\n", to, from); + break; + case TSet: + case TSequence: + case TChoice: { + Member *m, *have_ellipsis = NULL; - if (t->members == NULL) - break; + if(t->members == NULL) + break; - for (m = t->members; m && tag != m->val; m = m->next) { - char *fn; - char *tn; + if ((t->type == TSequence || t->type == TChoice) && preserve) { + fprintf(codefile, + "{ int ret;\n" + "ret = copy_octet_string(&(%s)->_save, &(%s)->_save);\n" + "if (ret) goto fail;\n" + "}\n", + from, to); + used_fail++; + } - asprintf (&fn, "%s(%s)->%s", - m->optional ? "" : "&", from, m->gen_name); - asprintf (&tn, "%s(%s)->%s", - m->optional ? "" : "&", to, m->gen_name); - if(m->optional){ - fprintf(codefile, "if(%s) {\n", fn); - fprintf(codefile, "%s = malloc(sizeof(*%s));\n", tn, tn); - fprintf(codefile, "if(%s == NULL) return ENOMEM;\n", tn); - } - copy_type (fn, tn, m->type); - if(m->optional){ - fprintf(codefile, "}else\n"); - fprintf(codefile, "%s = NULL;\n", tn); - } - if (tag == -1) - tag = m->val; - free (fn); - free (tn); - } - break; - } - case TSequenceOf: { - char *f; - char *T; + if(t->type == TChoice) { + fprintf(codefile, "(%s)->element = (%s)->element;\n", to, from); + fprintf(codefile, "switch((%s)->element) {\n", from); + } - fprintf (codefile, "if(((%s)->val = " - "malloc((%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n", - to, from, to, from); - fprintf (codefile, "return ENOMEM;\n"); - fprintf(codefile, - "for((%s)->len = 0; (%s)->len < (%s)->len; (%s)->len++){\n", - to, to, from, to); - asprintf(&f, "&(%s)->val[(%s)->len]", from, to); - asprintf(&T, "&(%s)->val[(%s)->len]", to, to); - copy_type(f, T, t->subtype); - fprintf(codefile, "}\n"); - free(f); - free(T); - break; - } - case TGeneralizedTime: - fprintf(codefile, "*(%s) = *(%s);\n", to, from); - break; - case TGeneralString: - copy_primitive ("general_string", from, to); - break; - case TUTF8String: - copy_primitive ("utf8string", from, to); - break; - case TNull: - break; - case TApplication: - copy_type (from, to, t->subtype); - break; - default : - abort (); - } + ASN1_TAILQ_FOREACH(m, t->members, members) { + char *fs; + char *ts; + + if (m->ellipsis) { + have_ellipsis = m; + continue; + } + + if(t->type == TChoice) + fprintf(codefile, "case %s:\n", m->label); + + asprintf (&fs, "%s(%s)->%s%s", + m->optional ? "" : "&", from, + t->type == TChoice ? "u." : "", m->gen_name); + if (fs == NULL) + errx(1, "malloc"); + asprintf (&ts, "%s(%s)->%s%s", + m->optional ? "" : "&", to, + t->type == TChoice ? "u." : "", m->gen_name); + if (ts == NULL) + errx(1, "malloc"); + if(m->optional){ + fprintf(codefile, "if(%s) {\n", fs); + fprintf(codefile, "%s = malloc(sizeof(*%s));\n", ts, ts); + fprintf(codefile, "if(%s == NULL) goto fail;\n", ts); + used_fail++; + } + copy_type (fs, ts, m->type, FALSE); + if(m->optional){ + fprintf(codefile, "}else\n"); + fprintf(codefile, "%s = NULL;\n", ts); + } + free (fs); + free (ts); + if(t->type == TChoice) + fprintf(codefile, "break;\n"); + } + if(t->type == TChoice) { + if (have_ellipsis) { + fprintf(codefile, "case %s: {\n" + "int ret;\n" + "ret = copy_octet_string(&(%s)->u.%s, &(%s)->u.%s);\n" + "if (ret) goto fail;\n" + "break;\n" + "}\n", + have_ellipsis->label, + from, have_ellipsis->gen_name, + to, have_ellipsis->gen_name); + used_fail++; + } + fprintf(codefile, "}\n"); + } + break; + } + case TSetOf: + case TSequenceOf: { + char *f; + char *T; + + fprintf (codefile, "if(((%s)->val = " + "malloc((%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n", + to, from, to, from); + fprintf (codefile, "goto fail;\n"); + used_fail++; + fprintf(codefile, + "for((%s)->len = 0; (%s)->len < (%s)->len; (%s)->len++){\n", + to, to, from, to); + asprintf(&f, "&(%s)->val[(%s)->len]", from, to); + if (f == NULL) + errx(1, "malloc"); + asprintf(&T, "&(%s)->val[(%s)->len]", to, to); + if (T == NULL) + errx(1, "malloc"); + copy_type(f, T, t->subtype, FALSE); + fprintf(codefile, "}\n"); + free(f); + free(T); + break; + } + case TGeneralizedTime: + fprintf(codefile, "*(%s) = *(%s);\n", to, from); + break; + case TGeneralString: + copy_primitive ("general_string", from, to); + break; + case TUTCTime: + fprintf(codefile, "*(%s) = *(%s);\n", to, from); + break; + case TUTF8String: + copy_primitive ("utf8string", from, to); + break; + case TPrintableString: + copy_primitive ("printable_string", from, to); + break; + case TIA5String: + copy_primitive ("ia5_string", from, to); + break; + case TBMPString: + copy_primitive ("bmp_string", from, to); + break; + case TUniversalString: + copy_primitive ("universal_string", from, to); + break; + case TTag: + copy_type (from, to, t->subtype, preserve); + break; + case TOID: + copy_primitive ("oid", from, to); + break; + case TNull: + break; + default : + abort (); + } } void generate_type_copy (const Symbol *s) { + int preserve = preserve_type(s->name) ? TRUE : FALSE; + + used_fail = 0; + fprintf (headerfile, "int copy_%s (const %s *, %s *);\n", s->gen_name, s->gen_name, s->gen_name); fprintf (codefile, "int\n" "copy_%s(const %s *from, %s *to)\n" - "{\n", + "{\n" + "memset(to, 0, sizeof(*to));\n", s->gen_name, s->gen_name, s->gen_name); + copy_type ("from", "to", s->type, preserve); + fprintf (codefile, "return 0;\n"); - copy_type ("from", "to", s->type); - fprintf (codefile, "return 0;\n}\n\n"); + if (used_fail) + fprintf (codefile, "fail:\n" + "free_%s(to);\n" + "return ENOMEM;\n", + s->gen_name); + + fprintf(codefile, + "}\n\n"); } diff --git a/lib/asn1/gen_decode.c b/lib/asn1/gen_decode.c index 14a053b45..58967613c 100644 --- a/lib/asn1/gen_decode.c +++ b/lib/asn1/gen_decode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -36,284 +36,538 @@ RCSID("$Id$"); static void -decode_primitive (const char *typename, const char *name) +decode_primitive (const char *typename, const char *name, const char *forwstr) { +#if 0 fprintf (codefile, "e = decode_%s(p, len, %s, &l);\n" - "FORW;\n", + "%s;\n", typename, - name); + name, + forwstr); +#else + fprintf (codefile, + "e = der_get_%s(p, len, %s, &l);\n" + "if(e) %s;\np += l; len -= l; ret += l;\n", + typename, + name, + forwstr); +#endif +} + +static int +is_primitive_type(int type) +{ + switch(type) { + case TInteger: + case TBoolean: + case TOctetString: + case TBitString: + case TEnumerated: + case TGeneralizedTime: + case TGeneralString: + case TOID: + case TUTCTime: + case TUTF8String: + case TPrintableString: + case TIA5String: + case TBMPString: + case TUniversalString: + case TNull: + return 1; + default: + return 0; + } } static void -decode_type (const char *name, const Type *t) +find_tag (const Type *t, + Der_class *cl, Der_type *ty, unsigned *tag) { switch (t->type) { - case TType: -#if 0 - decode_type (name, t->symbol->type); -#endif - fprintf (codefile, - "e = decode_%s(p, len, %s, &l);\n" - "FORW;\n", - t->symbol->gen_name, name); + case TBitString: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_BitString; break; - case TInteger: - if(t->members == NULL) - decode_primitive ("integer", name); - else { - char *s; - asprintf(&s, "(int*)%s", name); - if(s == NULL) - errx (1, "out of memory"); - decode_primitive ("integer", s); - free(s); + case TBoolean: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_Boolean; + break; + case TChoice: + errx(1, "Cannot have recursive CHOICE"); + case TEnumerated: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_Enumerated; + break; + case TGeneralString: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_GeneralString; + break; + case TGeneralizedTime: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_GeneralizedTime; + break; + case TIA5String: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_IA5String; + break; + case TInteger: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_Integer; + break; + case TNull: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_Null; + break; + case TOID: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_OID; + break; + case TOctetString: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_OctetString; + break; + case TPrintableString: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_PrintableString; + break; + case TSequence: + case TSequenceOf: + *cl = ASN1_C_UNIV; + *ty = CONS; + *tag = UT_Sequence; + break; + case TSet: + case TSetOf: + *cl = ASN1_C_UNIV; + *ty = CONS; + *tag = UT_Set; + break; + case TTag: + *cl = t->tag.tagclass; + *ty = is_primitive_type(t->subtype->type) ? PRIM : CONS; + *tag = t->tag.tagvalue; + break; + case TType: + return find_tag(t->symbol->type, cl, ty, tag); + case TUTCTime: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_UTCTime; + break; + case TUTF8String: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_UTF8String; + break; + case TBMPString: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_BMPString; + break; + case TUniversalString: + *cl = ASN1_C_UNIV; + *ty = PRIM; + *tag = UT_UniversalString; + break; + default: + abort(); + } +} + +static int +decode_type (const char *name, const Type *t, int optional, + const char *forwstr) +{ + switch (t->type) { + case TType: { + if (optional) + fprintf(codefile, + "%s = calloc(1, sizeof(*%s));\n" + "if (%s == NULL) %s;\n", + name, name, name, forwstr); + fprintf (codefile, + "e = decode_%s(p, len, %s, &l);\n", + t->symbol->gen_name, name); + if (optional) { + fprintf (codefile, + "if(e) {\n" + "free(%s);\n" + "%s = NULL;\n" + "} else {\n" + "p += l; len -= l; ret += l;\n" + "}\n", + name, name); + } else { + fprintf (codefile, + "if(e) %s;\n", + forwstr); + fprintf (codefile, + "p += l; len -= l; ret += l;\n"); } break; - case TUInteger: - decode_primitive ("unsigned", name); + } + case TInteger: + if(t->members) { + char *s; + asprintf(&s, "(int*)%s", name); + if (s == NULL) + errx (1, "out of memory"); + decode_primitive ("integer", s, forwstr); + free(s); + } else if (t->range == NULL) { + decode_primitive ("heim_integer", name, forwstr); + } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { + decode_primitive ("integer", name, forwstr); + } else if (t->range->min == 0 && t->range->max == UINT_MAX) { + decode_primitive ("unsigned", name, forwstr); + } else if (t->range->min == 0 && t->range->max == INT_MAX) { + decode_primitive ("unsigned", name, forwstr); + } else + errx(1, "%s: unsupported range %d -> %d", + name, t->range->min, t->range->max); break; + case TBoolean: + decode_primitive ("boolean", name, forwstr); + break; case TEnumerated: - decode_primitive ("enumerated", name); + decode_primitive ("enumerated", name, forwstr); break; case TOctetString: - decode_primitive ("octet_string", name); - break; - case TOID : - decode_primitive ("oid", name); + decode_primitive ("octet_string", name, forwstr); break; case TBitString: { Member *m; - int tag = -1; - int pos; + int pos = 0; - fprintf (codefile, - "e = der_match_tag_and_length (p, len, ASN1_C_UNIV, PRIM, UT_BitString," - "&reallen, &l);\n" - "FORW;\n" - "if(len < reallen)\n" - "return ASN1_OVERRUN;\n" - "p++;\n" - "len--;\n" - "reallen--;\n" - "ret++;\n"); - pos = 0; - for (m = t->members; m && tag != m->val; m = m->next) { + if (ASN1_TAILQ_EMPTY(t->members)) { + decode_primitive ("bit_string", name, forwstr); + break; + } + fprintf(codefile, + "if (len < 1) return ASN1_OVERRUN;\n" + "p++; len--; ret++;\n"); + fprintf(codefile, + "do {\n" + "if (len < 1) break;\n"); + ASN1_TAILQ_FOREACH(m, t->members, members) { while (m->val / 8 > pos / 8) { fprintf (codefile, - "p++; len--; reallen--; ret++;\n"); + "p++; len--; ret++;\n" + "if (len < 1) break;\n"); pos += 8; } fprintf (codefile, - "%s->%s = (*p >> %d) & 1;\n", + "(%s)->%s = (*p >> %d) & 1;\n", name, m->gen_name, 7 - m->val % 8); - if (tag == -1) - tag = m->val; } + fprintf(codefile, + "} while(0);\n"); fprintf (codefile, - "p += reallen; len -= reallen; ret += reallen;\n"); + "p += len; ret += len;\n"); break; } case TSequence: { Member *m; - int tag = -1; - int fd_counter = unique_get_next(); - int fd_counter_inner = unique_get_next(); if (t->members == NULL) break; - fprintf (codefile, - "e = der_match_tag_and_length (p, len, ASN1_C_UNIV, CONS, UT_Sequence," - "&reallen, &l);\n" - "FORW;\n" - "{\n" - "int dce_fix%d;\n" - "if((dce_fix%d = fix_dce(reallen, &len)) < 0)\n" - "return ASN1_BAD_FORMAT;\n", - fd_counter, fd_counter); - - for (m = t->members; m && tag != m->val; m = m->next) { + ASN1_TAILQ_FOREACH(m, t->members, members) { char *s; - asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name); - if (0 && m->type->type == TType){ - if(m->optional) - fprintf (codefile, - "%s = malloc(sizeof(*%s));\n" - "if(%s == NULL) return ENOMEM;\n", s, s, s); - fprintf (codefile, - "e = decode_seq_%s(p, len, %d, %d, %s, &l);\n", - m->type->symbol->gen_name, - m->val, - m->optional, - s); - if(m->optional) - fprintf (codefile, - "if (e == ASN1_MISSING_FIELD) {\n" - "free(%s);\n" - "%s = NULL;\n" - "e = l = 0;\n" - "}\n", - s, s); - - fprintf (codefile, "FORW;\n"); - - }else{ - fprintf (codefile, "{\n" - "size_t newlen, oldlen;\n\n" - "e = der_match_tag (p, len, ASN1_C_CONTEXT, CONS, %d, &l);\n", - m->val); - fprintf (codefile, - "if (e)\n"); - if(m->optional) - /* XXX should look at e */ - fprintf (codefile, - "%s = NULL;\n", s); - else - fprintf (codefile, - "return e;\n"); - fprintf (codefile, - "else {\n"); - fprintf (codefile, - "p += l;\n" - "len -= l;\n" - "ret += l;\n" - "e = der_get_length (p, len, &newlen, &l);\n" - "FORW;\n" - "{\n" - - "int dce_fix%d;\n" - "oldlen = len;\n" - "if((dce_fix%d = fix_dce(newlen, &len)) < 0)" - "return ASN1_BAD_FORMAT;\n", - fd_counter_inner, - fd_counter_inner); - if (m->optional) - fprintf (codefile, - "%s = malloc(sizeof(*%s));\n" - "if(%s == NULL) return ENOMEM;\n", s, s, s); - decode_type (s, m->type); - fprintf (codefile, - "if(dce_fix%d){\n" - "e = der_match_tag_and_length (p, len, " - "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" - "FORW;\n" - "}else \n" - "len = oldlen - newlen;\n" - "}\n" - "}\n", - fd_counter_inner); - fprintf (codefile, - "}\n"); - } - if (tag == -1) - tag = m->val; + if (m->ellipsis) + continue; + + asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", + name, m->gen_name); + if (s == NULL) + errx(1, "malloc"); + decode_type (s, m->type, m->optional, forwstr); free (s); } - fprintf(codefile, - "if(dce_fix%d){\n" - "e = der_match_tag_and_length (p, len, " - "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" - "FORW;\n" - "}\n" - "}\n", - fd_counter); break; } + case TSet: { + Member *m; + unsigned int memno; + + if(t->members == NULL) + break; + + fprintf(codefile, "{\n"); + fprintf(codefile, "unsigned int members = 0;\n"); + fprintf(codefile, "while(len > 0) {\n"); + fprintf(codefile, + "Der_class class;\n" + "Der_type type;\n" + "int tag;\n" + "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n" + "if(e) %s;\n", forwstr); + fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n"); + memno = 0; + ASN1_TAILQ_FOREACH(m, t->members, members) { + char *s; + + assert(m->type->type == TTag); + + fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n", + classname(m->type->tag.tagclass), + is_primitive_type(m->type->subtype->type) ? "PRIM" : "CONS", + valuename(m->type->tag.tagclass, m->type->tag.tagvalue)); + + asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name); + if (s == NULL) + errx(1, "malloc"); + if(m->optional) + fprintf(codefile, + "%s = calloc(1, sizeof(*%s));\n" + "if (%s == NULL) { e = ENOMEM; %s; }\n", + s, s, s, forwstr); + decode_type (s, m->type, 0, forwstr); + free (s); + + fprintf(codefile, "members |= (1 << %d);\n", memno); + memno++; + fprintf(codefile, "break;\n"); + } + fprintf(codefile, + "default:\n" + "return ASN1_MISPLACED_FIELD;\n" + "break;\n"); + fprintf(codefile, "}\n"); + fprintf(codefile, "}\n"); + memno = 0; + ASN1_TAILQ_FOREACH(m, t->members, members) { + char *s; + + asprintf (&s, "%s->%s", name, m->gen_name); + if (s == NULL) + errx(1, "malloc"); + fprintf(codefile, "if((members & (1 << %d)) == 0)\n", memno); + if(m->optional) + fprintf(codefile, "%s = NULL;\n", s); + else if(m->defval) + gen_assign_defval(s, m->defval); + else + fprintf(codefile, "return ASN1_MISSING_FIELD;\n"); + free(s); + memno++; + } + fprintf(codefile, "}\n"); + break; + } + case TSetOf: case TSequenceOf: { char *n; - int oldret_counter = unique_get_next(); - - fprintf (codefile, - "e = der_match_tag_and_length (p, len, ASN1_C_UNIV, CONS, UT_Sequence," - "&reallen, &l);\n" - "FORW;\n" - "if(len < reallen)\n" - "return ASN1_OVERRUN;\n" - "len = reallen;\n"); fprintf (codefile, "{\n" "size_t origlen = len;\n" - "int oldret%d = ret;\n" + "size_t oldret = ret;\n" + "void *tmp;\n" "ret = 0;\n" "(%s)->len = 0;\n" "(%s)->val = NULL;\n" "while(ret < origlen) {\n" + "tmp = realloc((%s)->val, " + " sizeof(*((%s)->val)) * ((%s)->len + 1));\n" + "if (tmp == NULL) { %s; }\n" "(%s)->len++;\n" - "(%s)->val = realloc((%s)->val, sizeof(*((%s)->val)) * (%s)->len);\n", - oldret_counter, name, name, name, name, name, name, name); + "(%s)->val = tmp;\n", + name, name, name, name, name, forwstr, name, name); + asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name); - decode_type (n, t->subtype); + if (n == NULL) + errx(1, "malloc"); + decode_type (n, t->subtype, 0, forwstr); fprintf (codefile, "len = origlen - ret;\n" "}\n" - "ret += oldret%d;\n" - "}\n", - oldret_counter); + "ret += oldret;\n" + "}\n"); free (n); break; } case TGeneralizedTime: - decode_primitive ("generalized_time", name); + decode_primitive ("generalized_time", name, forwstr); break; case TGeneralString: - decode_primitive ("general_string", name); + decode_primitive ("general_string", name, forwstr); + break; + case TTag:{ + fprintf(codefile, + "{\n" + "int tagdatalen;\n" + "size_t oldlen;\n"); + if(dce_fix) + fprintf(codefile, + "int dce_fix;\n"); + fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, %s, %s, " + "&tagdatalen, &l);\n", + classname(t->tag.tagclass), + is_primitive_type(t->subtype->type) ? "PRIM" : "CONS", + valuename(t->tag.tagclass, t->tag.tagvalue)); + if(optional) { + fprintf(codefile, + "if(e) {\n" + "%s = NULL;\n" + "} else {\n" + "%s = calloc(1, sizeof(*%s));\n" + "if (%s == NULL) { e = ENOMEM; %s; }\n", + name, name, name, name, forwstr); + } else { + fprintf(codefile, "if(e) %s;\n", forwstr); + } + fprintf (codefile, + "p += l; len -= l; ret += l;\n" + "oldlen = len;\n"); + if(dce_fix) + fprintf (codefile, + "if((dce_fix = _heim_fix_dce(tagdatalen, &len)) < 0)\n" + "{ e = ASN1_BAD_FORMAT; %s; }\n", + forwstr); + else + fprintf(codefile, + "if (tagdatalen > len) { e = ASN1_OVERRUN; %s; }\n" + "len = tagdatalen;\n", forwstr); + decode_type (name, t->subtype, 0, forwstr); + if(dce_fix) + fprintf(codefile, + "if(dce_fix){\n" + "e = der_match_tag_and_length (p, len, " + "(Der_class)0,(Der_type)0, UT_EndOfContent, " + "&tagdatalen, &l);\n" + "if(e) %s;\np += l; len -= l; ret += l;\n" + "} else \n", forwstr); + fprintf(codefile, + "len = oldlen - tagdatalen;\n"); + if(optional) + fprintf(codefile, + "}\n"); + fprintf(codefile, + "}\n"); + break; + } + case TChoice: { + Member *m, *have_ellipsis = NULL; + const char *els = ""; + + if (t->members == NULL) + break; + + ASN1_TAILQ_FOREACH(m, t->members, members) { + const Type *tt = m->type; + char *s; + Der_class cl; + Der_type ty; + unsigned tag; + + if (m->ellipsis) { + have_ellipsis = m; + continue; + } + + find_tag(tt, &cl, &ty, &tag); + + fprintf(codefile, + "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n", + els, + classname(cl), + ty ? "CONS" : "PRIM", + valuename(cl, tag)); + asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&", + name, m->gen_name); + if (s == NULL) + errx(1, "malloc"); + decode_type (s, m->type, m->optional, forwstr); + free(s); + fprintf(codefile, + "}\n"); + els = "else "; + } + if (have_ellipsis) { + fprintf(codefile, + "else {\n" + "(%s)->u.%s.data = calloc(1, len);\n" + "if ((%s)->u.%s.data == NULL) {\n" + "e = ENOMEM; %s;\n" + "}\n" + "(%s)->u.%s.length = len;\n" + "memcpy((%s)->u.%s.data, p, len);\n" + "(%s)->element = %s;\n" + "p += len;\n" + "ret += len;\n" + "len -= len;\n" + "}\n", + name, have_ellipsis->gen_name, + name, have_ellipsis->gen_name, + forwstr, + name, have_ellipsis->gen_name, + name, have_ellipsis->gen_name, + name, have_ellipsis->label); + } else { + fprintf(codefile, + "else {\n" + "e = ASN1_PARSE_ERROR;\n" + "%s;\n" + "}\n", + forwstr); + } + break; + } + case TUTCTime: + decode_primitive ("utctime", name, forwstr); break; case TUTF8String: - decode_primitive ("utf8string", name); + decode_primitive ("utf8string", name, forwstr); + break; + case TPrintableString: + decode_primitive ("printable_string", name, forwstr); + break; + case TIA5String: + decode_primitive ("ia5_string", name, forwstr); + break; + case TBMPString: + decode_primitive ("bmp_string", name, forwstr); + break; + case TUniversalString: + decode_primitive ("universal_string", name, forwstr); break; case TNull: - fprintf (codefile, - "e = decode_nulltype(p, len, &l);\n" - "FORW;\n"); + fprintf (codefile, "/* NULL */\n"); break; - case TApplication: - fprintf (codefile, - "e = der_match_tag_and_length (p, len, ASN1_C_APPL, CONS, %d, " - "&reallen, &l);\n" - "FORW;\n" - "{\n" - "int dce_fix;\n" - "if((dce_fix = fix_dce(reallen, &len)) < 0)\n" - "return ASN1_BAD_FORMAT;\n", - t->application); - decode_type (name, t->subtype); - fprintf(codefile, - "if(dce_fix){\n" - "e = der_match_tag_and_length (p, len, " - "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" - "FORW;\n" - "}\n" - "}\n"); - - break; - case TBoolean: - decode_primitive ("boolean", name); + case TOID: + decode_primitive ("oid", name, forwstr); break; default : abort (); } + return 0; } void generate_type_decode (const Symbol *s) { - unique_reset(); + int preserve = preserve_type(s->name) ? TRUE : FALSE; + fprintf (headerfile, "int " "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n", s->gen_name, s->gen_name); - fprintf (codefile, "#define FORW " - "if(e) goto fail; " - "p += l; " - "len -= l; " - "ret += l\n\n"); - - fprintf (codefile, "int\n" "decode_%s(const unsigned char *p," " size_t len, %s *data, size_t *size)\n" @@ -322,28 +576,45 @@ generate_type_decode (const Symbol *s) switch (s->type->type) { case TInteger: - case TUInteger: case TBoolean: case TOctetString: case TOID: case TGeneralizedTime: case TGeneralString: case TUTF8String: + case TPrintableString: + case TIA5String: + case TBMPString: + case TUniversalString: + case TUTCTime: case TNull: case TEnumerated: case TBitString: case TSequence: case TSequenceOf: - case TApplication: + case TSet: + case TSetOf: + case TTag: case TType: + case TChoice: fprintf (codefile, "size_t ret = 0, reallen;\n" "size_t l;\n" - "int e;\n\n"); + "int e;\n"); + if (preserve) + fprintf (codefile, "const unsigned char *begin = p;\n"); + + fprintf (codefile, "\n"); fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); fprintf (codefile, "reallen = 0;\n"); /* hack to avoid `unused variable' */ - decode_type ("data", s->type); + decode_type ("data", s->type, 0, "goto fail"); + if (preserve) + fprintf (codefile, + "data->_save.data = calloc(1, ret);\n" + "if (data->_save.data == NULL) { e = ENOMEM; goto fail; }\n" + "data->_save.length = ret;\n" + "memcpy(data->_save.data, begin, ret);\n"); fprintf (codefile, "if(size) *size = ret;\n" "return 0;\n"); @@ -358,62 +629,3 @@ generate_type_decode (const Symbol *s) } fprintf (codefile, "}\n\n"); } - -void -generate_seq_type_decode (const Symbol *s) -{ - fprintf (headerfile, - "int decode_seq_%s(const unsigned char *, size_t, int, int, " - "%s *, size_t *);\n", - s->gen_name, s->gen_name); - - fprintf (codefile, "int\n" - "decode_seq_%s(const unsigned char *p, size_t len, int tag, " - "int optional, %s *data, size_t *size)\n" - "{\n", - s->gen_name, s->gen_name); - - fprintf (codefile, - "size_t newlen, oldlen;\n" - "size_t l, ret = 0;\n" - "int e;\n" - "int dce_fix;\n"); - - fprintf (codefile, - "e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, tag, &l);\n" - "if (e)\n" - "return e;\n"); - fprintf (codefile, - "p += l;\n" - "len -= l;\n" - "ret += l;\n" - "e = der_get_length(p, len, &newlen, &l);\n" - "if (e)\n" - "return e;\n" - "p += l;\n" - "len -= l;\n" - "ret += l;\n" - "oldlen = len;\n" - "if ((dce_fix = fix_dce(newlen, &len)) < 0)\n" - "return ASN1_BAD_FORMAT;\n" - "e = decode_%s(p, len, data, &l);\n" - "if (e)\n" - "return e;\n" - "p += l;\n" - "len -= l;\n" - "ret += l;\n" - "if (dce_fix) {\n" - "size_t reallen;\n\n" - "e = der_match_tag_and_length(p, len, " - "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" - "if (e)\n" - "return e;\n" - "ret += l;\n" - "}\n", - s->gen_name); - fprintf (codefile, - "if(size) *size = ret;\n" - "return 0;\n"); - - fprintf (codefile, "}\n\n"); -} diff --git a/lib/asn1/gen_encode.c b/lib/asn1/gen_encode.c index 0b97dddd2..6128d9be1 100644 --- a/lib/asn1/gen_encode.c +++ b/lib/asn1/gen_encode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -39,15 +39,76 @@ static void encode_primitive (const char *typename, const char *name) { fprintf (codefile, - "e = encode_%s(p, len, %s, &l);\n" - "BACK;\n", + "e = der_put_%s(p, len, %s, &l);\n" + "if (e) return e;\np -= l; len -= l; ret += l;\n\n", typename, name); } -static void +const char * +classname(Der_class class) +{ + const char *cn[] = { "ASN1_C_UNIV", "ASN1_C_APPL", + "ASN1_C_CONTEXT", "ASN1_C_PRIV" }; + if(class < ASN1_C_UNIV || class > ASN1_C_PRIVATE) + return "???"; + return cn[class]; +} + + +const char * +valuename(Der_class class, int value) +{ + static char s[32]; + struct { + int value; + char *s; + } *p, values[] = { +#define X(Y) { Y, #Y } + X(UT_BMPString), + X(UT_BitString), + X(UT_Boolean), + X(UT_EmbeddedPDV), + X(UT_Enumerated), + X(UT_External), + X(UT_GeneralString), + X(UT_GeneralizedTime), + X(UT_GraphicString), + X(UT_IA5String), + X(UT_Integer), + X(UT_Null), + X(UT_NumericString), + X(UT_OID), + X(UT_ObjectDescriptor), + X(UT_OctetString), + X(UT_PrintableString), + X(UT_Real), + X(UT_RelativeOID), + X(UT_Sequence), + X(UT_Set), + X(UT_TeletexString), + X(UT_UTCTime), + X(UT_UTF8String), + X(UT_UniversalString), + X(UT_VideotexString), + X(UT_VisibleString), +#undef X + { -1, NULL } + }; + if(class == ASN1_C_UNIV) { + for(p = values; p->value != -1; p++) + if(p->value == value) + return p->s; + } + snprintf(s, sizeof(s), "%d", value); + return s; +} + +static int encode_type (const char *name, const Type *t) { + int constructed = 1; + switch (t->type) { case TType: #if 0 @@ -55,45 +116,60 @@ encode_type (const char *name, const Type *t) #endif fprintf (codefile, "e = encode_%s(p, len, %s, &l);\n" - "BACK;\n", + "if (e) return e;\np -= l; len -= l; ret += l;\n\n", t->symbol->gen_name, name); break; case TInteger: - if(t->members == NULL) - encode_primitive ("integer", name); - else { + if(t->members) { char *s; asprintf(&s, "(const int*)%s", name); if(s == NULL) errx(1, "out of memory"); encode_primitive ("integer", s); free(s); - } + } else if (t->range == NULL) { + encode_primitive ("heim_integer", name); + } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { + encode_primitive ("integer", name); + } else if (t->range->min == 0 && t->range->max == UINT_MAX) { + encode_primitive ("unsigned", name); + } else if (t->range->min == 0 && t->range->max == INT_MAX) { + encode_primitive ("unsigned", name); + } else + errx(1, "%s: unsupported range %d -> %d", + name, t->range->min, t->range->max); + constructed = 0; break; - case TUInteger: - encode_primitive ("unsigned", name); + case TBoolean: + encode_primitive ("boolean", name); + constructed = 0; break; case TOctetString: encode_primitive ("octet_string", name); - break; - case TOID : - encode_primitive ("oid", name); + constructed = 0; break; case TBitString: { Member *m; int pos; int rest; - int tag = -1; - if (t->members == NULL) + if (ASN1_TAILQ_EMPTY(t->members)) { + encode_primitive("bit_string", name); + constructed = 0; break; + } fprintf (codefile, "{\n" "unsigned char c = 0;\n"); + if (!rfc1510_bitstring) + fprintf (codefile, + "int bit_set = 0;\n"); +#if 0 pos = t->members->prev->val; /* fix for buggy MIT (and OSF?) code */ if (pos > 31) abort (); +#endif /* * It seems that if we do not always set pos to 31 here, the MIT * code will do the wrong thing. @@ -101,139 +177,293 @@ encode_type (const char *name, const Type *t) * I hate ASN.1 (and DER), but I hate it even more when everybody * has to screw it up differently. */ - pos = 31; - rest = 7 - (pos % 8); + pos = ASN1_TAILQ_LAST(t->members, memhead)->val; + if (rfc1510_bitstring) { + if (pos < 31) + pos = 31; + rest = 7 - (pos % 8); + } else + rest = 0; - for (m = t->members->prev; m && tag != m->val; m = m->prev) { + ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) { while (m->val / 8 < pos / 8) { + if (!rfc1510_bitstring) + fprintf (codefile, + "if (c != 0 || bit_set) {\n"); fprintf (codefile, + "if (len < 1) return ASN1_OVERFLOW;\n" "*p-- = c; len--; ret++;\n" "c = 0;\n"); + if (!rfc1510_bitstring) + fprintf (codefile, + "bit_set = 1;\n" + "}\n"); pos -= 8; } fprintf (codefile, - "if(%s->%s) c |= 1<<%d;\n", name, m->gen_name, - 7 - m->val % 8); - - if (tag == -1) - tag = m->val; + "if((%s)->%s) {\n" + "c |= 1<<%d;\n", + name, m->gen_name, 7 - m->val % 8); + if (!rfc1510_bitstring) + rest = 7 - m->val % 8; + fprintf (codefile, + "}\n"); } + if (!rfc1510_bitstring) + fprintf (codefile, + "if (c != 0 || bit_set) {\n"); fprintf (codefile, - "*p-- = c;\n" + "if (len < 1) return ASN1_OVERFLOW;\n" + "*p-- = c; len--; ret++;\n"); + if (!rfc1510_bitstring) + fprintf (codefile, + "}\n"); + + fprintf (codefile, + "if (len < 1) return ASN1_OVERFLOW;\n" "*p-- = %d;\n" - "len -= 2;\n" - "ret += 2;\n" - "}\n\n" - "e = der_put_length_and_tag (p, len, ret, ASN1_C_UNIV, PRIM," - "UT_BitString, &l);\n" - "BACK;\n", + "len -= 1;\n" + "ret += 1;\n" + "}\n\n", rest); + constructed = 0; break; } case TEnumerated : { encode_primitive ("enumerated", name); + constructed = 0; break; } + + case TSet: case TSequence: { Member *m; - int tag = -1; - int oldret_counter = unique_get_next(); if (t->members == NULL) break; - - for (m = t->members->prev; m && tag != m->val; m = m->prev) { + + ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) { char *s; + if (m->ellipsis) + continue; + asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name); + if (s == NULL) + errx(1, "malloc"); + fprintf(codefile, "/* %s */\n", m->name); if (m->optional) fprintf (codefile, - "if(%s)\n", + "if(%s) ", s); -#if 1 - fprintf (codefile, "{\n" - "int oldret%d = ret;\n" - "ret = 0;\n", - oldret_counter); -#endif + else if(m->defval) + gen_compare_defval(s + 1, m->defval); + fprintf (codefile, "{\n"); + fprintf (codefile, "size_t oldret = ret;\n"); + fprintf (codefile, "ret = 0;\n"); encode_type (s, m->type); - fprintf (codefile, - "e = der_put_length_and_tag (p, len, ret, ASN1_C_CONTEXT, CONS, " - "%d, &l);\n" - "BACK;\n", - m->val); -#if 1 - fprintf (codefile, - "ret += oldret%d;\n" - "}\n", - oldret_counter); -#endif - if (tag == -1) - tag = m->val; + fprintf (codefile, "ret += oldret;\n"); + fprintf (codefile, "}\n"); free (s); } + break; + } + case TSetOf: { + + fprintf(codefile, + "{\n" + "struct heim_octet_string *val;\n" + "size_t elen, totallen = 0;\n" + "int eret;\n"); + + fprintf(codefile, + "val = malloc(sizeof(val[0]) * (%s)->len);\n" + "if (val == NULL && (%s)->len != 0) return ENOMEM;\n", + name, name); + + fprintf(codefile, + "for(i = 0; i < (%s)->len; i++) {\n", + name); + + fprintf(codefile, + "ASN1_MALLOC_ENCODE(%s, val[i].data, " + "val[i].length, &(%s)->val[i], &elen, eret);\n", + t->subtype->symbol->gen_name, + name); + + fprintf(codefile, + "if(eret) {\n" + "i--;\n" + "while (i >= 0) {\n" + "free(val[i].data);\n" + "i--;\n" + "}\n" + "free(val);\n" + "return eret;\n" + "}\n" + "totallen += elen;\n" + "}\n"); + + fprintf(codefile, + "if (totallen > len) {\n" + "for (i = 0; i < (%s)->len; i++) {\n" + "free(val[i].data);\n" + "}\n" + "free(val);\n" + "return ASN1_OVERFLOW;\n" + "}\n", + name); + + fprintf(codefile, + "qsort(val, (%s)->len, sizeof(val[0]), _heim_der_set_sort);\n", + name); + fprintf (codefile, - "e = der_put_length_and_tag (p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);\n" - "BACK;\n"); + "for(i = (%s)->len - 1; i >= 0; --i) {\n" + "p -= val[i].length;\n" + "ret += val[i].length;\n" + "memcpy(p + 1, val[i].data, val[i].length);\n" + "free(val[i].data);\n" + "}\n" + "free(val);\n" + "}\n", + name); break; } case TSequenceOf: { - int oldret_counter = unique_get_next(); char *n; fprintf (codefile, "for(i = (%s)->len - 1; i >= 0; --i) {\n" -#if 1 - "int oldret%d = ret;\n" + "size_t oldret = ret;\n" "ret = 0;\n", -#else - , -#endif - name, oldret_counter); + name); asprintf (&n, "&(%s)->val[i]", name); + if (n == NULL) + errx(1, "malloc"); encode_type (n, t->subtype); fprintf (codefile, -#if 1 - "ret += oldret%d;\n" -#endif - "}\n" - "e = der_put_length_and_tag (p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);\n" - "BACK;\n" -#if 1 - , oldret_counter -#endif - ); + "ret += oldret;\n" + "}\n"); free (n); break; } case TGeneralizedTime: encode_primitive ("generalized_time", name); + constructed = 0; break; case TGeneralString: encode_primitive ("general_string", name); + constructed = 0; + break; + case TTag: { + int c = encode_type (name, t->subtype); + fprintf (codefile, + "e = der_put_length_and_tag (p, len, ret, %s, %s, %s, &l);\n" + "if (e) return e;\np -= l; len -= l; ret += l;\n\n", + classname(t->tag.tagclass), + c ? "CONS" : "PRIM", + valuename(t->tag.tagclass, t->tag.tagvalue)); + break; + } + case TChoice:{ + Member *m, *have_ellipsis = NULL; + char *s; + + if (t->members == NULL) + break; + + fprintf(codefile, "\n"); + + asprintf (&s, "(%s)", name); + if (s == NULL) + errx(1, "malloc"); + fprintf(codefile, "switch(%s->element) {\n", s); + + ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) { + char *s2; + + if (m->ellipsis) { + have_ellipsis = m; + continue; + } + + fprintf (codefile, "case %s: {", m->label); + asprintf(&s2, "%s(%s)->u.%s", m->optional ? "" : "&", + s, m->gen_name); + if (s2 == NULL) + errx(1, "malloc"); + if (m->optional) + fprintf (codefile, "if(%s) {\n", s2); + fprintf (codefile, "size_t oldret;\n"); + fprintf (codefile, "oldret = ret;\n"); + fprintf (codefile, "ret = 0;\n"); + constructed = encode_type (s2, m->type); + fprintf (codefile, "ret += oldret;\n"); + if(m->optional) + fprintf (codefile, "}\n"); + fprintf(codefile, "break;\n"); + fprintf(codefile, "}\n"); + free (s2); + } + free (s); + if (have_ellipsis) { + fprintf(codefile, + "case %s: {\n" + "if (len < %s->u.%s.length)\n" + "return ASN1_OVERFLOW;\n" + "p -= %s->u.%s.length;\n" + "ret += %s->u.%s.length;\n" + "memcpy(p + 1, %s->u.%s.data, %s->u.%s.length);\n" + "break;\n" + "}\n", + have_ellipsis->label, + name, have_ellipsis->gen_name, + name, have_ellipsis->gen_name, + name, have_ellipsis->gen_name, + name, have_ellipsis->gen_name, + name, have_ellipsis->gen_name); + } + fprintf(codefile, "};\n"); + break; + } + case TOID: + encode_primitive ("oid", name); + constructed = 0; + break; + case TUTCTime: + encode_primitive ("utctime", name); + constructed = 0; break; case TUTF8String: encode_primitive ("utf8string", name); + constructed = 0; + break; + case TPrintableString: + encode_primitive ("printable_string", name); + constructed = 0; + break; + case TIA5String: + encode_primitive ("ia5_string", name); + constructed = 0; + break; + case TBMPString: + encode_primitive ("bmp_string", name); + constructed = 0; + break; + case TUniversalString: + encode_primitive ("universal_string", name); + constructed = 0; break; case TNull: - fprintf (codefile, - "e = encode_nulltype(p, len, &l);\n" - "BACK;\n"); - break; - case TApplication: - encode_type (name, t->subtype); - fprintf (codefile, - "e = der_put_length_and_tag (p, len, ret, ASN1_C_APPL, CONS, %d, &l);\n" - "BACK;\n", - t->application); - break; - case TBoolean: - encode_primitive ("boolean", name); + fprintf (codefile, "/* NULL */\n"); + constructed = 0; break; default: abort (); } + return constructed; } void @@ -244,9 +474,6 @@ generate_type_encode (const Symbol *s) "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n", s->gen_name, s->gen_name); - fprintf (codefile, "#define BACK if (e) return e; p -= l; len -= l; ret += l\n\n"); - - fprintf (codefile, "int\n" "encode_%s(unsigned char *p, size_t len," " const %s *data, size_t *size)\n" @@ -255,20 +482,27 @@ generate_type_encode (const Symbol *s) switch (s->type->type) { case TInteger: - case TUInteger: case TBoolean: case TOctetString: case TGeneralizedTime: case TGeneralString: + case TUTCTime: case TUTF8String: + case TPrintableString: + case TIA5String: + case TBMPString: + case TUniversalString: case TNull: case TBitString: case TEnumerated: case TOID: case TSequence: case TSequenceOf: - case TApplication: + case TSet: + case TSetOf: + case TTag: case TType: + case TChoice: fprintf (codefile, "size_t ret = 0;\n" "size_t l;\n" diff --git a/lib/asn1/gen_free.c b/lib/asn1/gen_free.c index c1c6db77e..2c0fc5b73 100644 --- a/lib/asn1/gen_free.c +++ b/lib/asn1/gen_free.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -42,92 +42,136 @@ free_primitive (const char *typename, const char *name) } static void -free_type (const char *name, const Type *t) +free_type (const char *name, const Type *t, int preserve) { - switch (t->type) { - case TType: + switch (t->type) { + case TType: #if 0 - free_type (name, t->symbol->type); + free_type (name, t->symbol->type, preserve); #endif - fprintf (codefile, "free_%s(%s);\n", t->symbol->gen_name, name); - break; - case TInteger: - case TUInteger: - case TBoolean: - case TEnumerated : - break; - case TOctetString: - free_primitive ("octet_string", name); - break; - case TOID : - free_primitive ("oid", name); - break; - case TBitString: { - break; - } - case TSequence: { - Member *m; - int tag = -1; + fprintf (codefile, "free_%s(%s);\n", t->symbol->gen_name, name); + break; + case TInteger: + case TBoolean: + case TEnumerated : + case TNull: + case TGeneralizedTime: + case TUTCTime: + break; + case TBitString: + if (ASN1_TAILQ_EMPTY(t->members)) + free_primitive("bit_string", name); + break; + case TOctetString: + free_primitive ("octet_string", name); + break; + case TChoice: + case TSet: + case TSequence: { + Member *m, *have_ellipsis = NULL; - if (t->members == NULL) - break; + if (t->members == NULL) + break; + + if ((t->type == TSequence || t->type == TChoice) && preserve) + fprintf(codefile, "free_octet_string(&data->_save);\n"); + + if(t->type == TChoice) + fprintf(codefile, "switch((%s)->element) {\n", name); - for (m = t->members; m && tag != m->val; m = m->next) { - char *s; + ASN1_TAILQ_FOREACH(m, t->members, members) { + char *s; - asprintf (&s, "%s(%s)->%s", - m->optional ? "" : "&", name, m->gen_name); - if(m->optional) - fprintf(codefile, "if(%s) {\n", s); - free_type (s, m->type); - if(m->optional) - fprintf(codefile, - "free(%s);\n" - "%s = NULL;\n" - "}\n", s, s); - if (tag == -1) - tag = m->val; - free (s); - } - break; - } - case TSequenceOf: { - char *n; + if (m->ellipsis){ + have_ellipsis = m; + continue; + } - fprintf (codefile, "while((%s)->len){\n", name); - asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name); - free_type(n, t->subtype); - fprintf(codefile, - "(%s)->len--;\n" - "}\n", - name); - fprintf(codefile, - "free((%s)->val);\n" - "(%s)->val = NULL;\n", name, name); - free(n); - break; - } - case TGeneralizedTime: - break; - case TGeneralString: - free_primitive ("general_string", name); - break; - case TUTF8String: - free_primitive ("utf8string", name); - break; - case TNull: - break; - case TApplication: - free_type (name, t->subtype); - break; - default : - abort (); - } + if(t->type == TChoice) + fprintf(codefile, "case %s:\n", m->label); + asprintf (&s, "%s(%s)->%s%s", + m->optional ? "" : "&", name, + t->type == TChoice ? "u." : "", m->gen_name); + if (s == NULL) + errx(1, "malloc"); + if(m->optional) + fprintf(codefile, "if(%s) {\n", s); + free_type (s, m->type, FALSE); + if(m->optional) + fprintf(codefile, + "free(%s);\n" + "%s = NULL;\n" + "}\n",s, s); + free (s); + if(t->type == TChoice) + fprintf(codefile, "break;\n"); + } + + if(t->type == TChoice) { + if (have_ellipsis) + fprintf(codefile, + "case %s:\n" + "free_octet_string(&(%s)->u.%s);\n" + "break;", + have_ellipsis->label, + name, have_ellipsis->gen_name); + fprintf(codefile, "}\n"); + } + break; + } + case TSetOf: + case TSequenceOf: { + char *n; + + fprintf (codefile, "while((%s)->len){\n", name); + asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name); + if (n == NULL) + errx(1, "malloc"); + free_type(n, t->subtype, FALSE); + fprintf(codefile, + "(%s)->len--;\n" + "}\n", + name); + fprintf(codefile, + "free((%s)->val);\n" + "(%s)->val = NULL;\n", name, name); + free(n); + break; + } + case TGeneralString: + free_primitive ("general_string", name); + break; + case TUTF8String: + free_primitive ("utf8string", name); + break; + case TPrintableString: + free_primitive ("printable_string", name); + break; + case TIA5String: + free_primitive ("ia5_string", name); + break; + case TBMPString: + free_primitive ("bmp_string", name); + break; + case TUniversalString: + free_primitive ("universal_string", name); + break; + case TTag: + free_type (name, t->subtype, preserve); + break; + case TOID : + free_primitive ("oid", name); + break; + default : + abort (); + } } void generate_type_free (const Symbol *s) { + int preserve = preserve_type(s->name) ? TRUE : FALSE; + fprintf (headerfile, "void free_%s (%s *);\n", s->gen_name, s->gen_name); @@ -137,7 +181,7 @@ generate_type_free (const Symbol *s) "{\n", s->gen_name, s->gen_name); - free_type ("data", s->type); + free_type ("data", s->type, preserve); fprintf (codefile, "}\n\n"); } diff --git a/lib/asn1/gen_glue.c b/lib/asn1/gen_glue.c index b4e98e07f..b01012be8 100644 --- a/lib/asn1/gen_glue.c +++ b/lib/asn1/gen_glue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1999 Kungliga Tekniska Högskolan + * Copyright (c) 1997, 1999, 2000, 2003 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -36,56 +36,48 @@ RCSID("$Id$"); static void -generate_2int (const Symbol *s) +generate_2int (const Type *t, const char *gen_name) { - Type *t = s->type; Member *m; - int tag = -1; fprintf (headerfile, "unsigned %s2int(%s);\n", - s->gen_name, s->gen_name); + gen_name, gen_name); fprintf (codefile, "unsigned %s2int(%s f)\n" "{\n" "unsigned r = 0;\n", - s->gen_name, s->gen_name); + gen_name, gen_name); - for (m = t->members; m && m->val != tag; m = m->next) { + ASN1_TAILQ_FOREACH(m, t->members, members) { fprintf (codefile, "if(f.%s) r |= (1U << %d);\n", m->gen_name, m->val); - - if (tag == -1) - tag = m->val; } fprintf (codefile, "return r;\n" "}\n\n"); } static void -generate_int2 (const Symbol *s) +generate_int2 (const Type *t, const char *gen_name) { - Type *t = s->type; Member *m; - int tag = -1; fprintf (headerfile, "%s int2%s(unsigned);\n", - s->gen_name, s->gen_name); + gen_name, gen_name); fprintf (codefile, "%s int2%s(unsigned n)\n" "{\n" "\t%s flags;\n\n", - s->gen_name, s->gen_name, s->gen_name); + gen_name, gen_name, gen_name); - for (m = t->members; m && m->val != tag; m = m->next) { - fprintf (codefile, "\tflags.%s = (n >> %d) & 1;\n", - m->gen_name, m->val); - - if (tag == -1) - tag = m->val; + if(t->members) { + ASN1_TAILQ_FOREACH(m, t->members, members) { + fprintf (codefile, "\tflags.%s = (n >> %d) & 1;\n", + m->gen_name, m->val); + } } fprintf (codefile, "\treturn flags;\n" "}\n\n"); @@ -96,28 +88,24 @@ generate_int2 (const Symbol *s) */ static void -generate_units (const Symbol *s) +generate_units (const Type *t, const char *gen_name) { - Type *t = s->type; Member *m; - int tag = -1; fprintf (headerfile, "const struct units * asn1_%s_units(void);", - s->gen_name); + gen_name); fprintf (codefile, "static struct units %s_units[] = {\n", - s->gen_name); + gen_name); - if(t->members) - for (m = t->members->prev; m && m->val != tag; m = m->prev) { + if(t->members) { + ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) { fprintf (codefile, "\t{\"%s\",\t1U << %d},\n", m->gen_name, m->val); - - if (tag == -1) - tag = m->val; } + } fprintf (codefile, "\t{NULL,\t0}\n" @@ -127,19 +115,24 @@ generate_units (const Symbol *s) "const struct units * asn1_%s_units(void){\n" "return %s_units;\n" "}\n\n", - s->gen_name, s->gen_name); + gen_name, gen_name); } void -generate_glue (const Symbol *s) +generate_glue (const Type *t, const char *gen_name) { - switch(s->type->type) { + switch(t->type) { + case TTag: + generate_glue(t->subtype, gen_name); + break; case TBitString : - generate_2int (s); - generate_int2 (s); - generate_units (s); + if (!ASN1_TAILQ_EMPTY(t->members)) { + generate_2int (t, gen_name); + generate_int2 (t, gen_name); + generate_units (t, gen_name); + } break; default : break; diff --git a/lib/asn1/gen_length.c b/lib/asn1/gen_length.c index ae348c566..ee8340b53 100644 --- a/lib/asn1/gen_length.c +++ b/lib/asn1/gen_length.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -43,7 +43,22 @@ length_primitive (const char *typename, fprintf (codefile, "%s += length_%s(%s);\n", variable, typename, name); } -static void +static size_t +length_tag(unsigned int tag) +{ + size_t len = 0; + + if(tag <= 30) + return 1; + while(tag) { + tag /= 128; + len++; + } + return len + 1; +} + + +static int length_type (const char *name, const Type *t, const char *variable) { switch (t->type) { @@ -55,19 +70,28 @@ length_type (const char *name, const Type *t, const char *variable) variable, t->symbol->gen_name, name); break; case TInteger: - if(t->members == NULL) - length_primitive ("integer", name, variable); - else { - char *s; - asprintf(&s, "(const int*)%s", name); - if(s == NULL) + if(t->members) { + char *s; + asprintf(&s, "(const int*)%s", name); + if(s == NULL) errx (1, "out of memory"); - length_primitive ("integer", s, variable); - free(s); - } + length_primitive ("integer", s, variable); + free(s); + } else if (t->range == NULL) { + length_primitive ("heim_integer", name, variable); + } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { + length_primitive ("integer", name, variable); + } else if (t->range->min == 0 && t->range->max == UINT_MAX) { + length_primitive ("unsigned", name, variable); + } else if (t->range->min == 0 && t->range->max == INT_MAX) { + length_primitive ("unsigned", name, variable); + } else + errx(1, "%s: unsupported range %d -> %d", + name, t->range->min, t->range->max); + break; - case TUInteger: - length_primitive ("unsigned", name, variable); + case TBoolean: + fprintf (codefile, "%s += 1;\n", variable); break; case TEnumerated : length_primitive ("enumerated", name, variable); @@ -75,71 +99,112 @@ length_type (const char *name, const Type *t, const char *variable) case TOctetString: length_primitive ("octet_string", name, variable); break; - case TOID : - length_primitive ("oid", name, variable); - break; case TBitString: { - /* - * XXX - Hope this is correct - * look at TBitString case in `encode_type' - */ - fprintf (codefile, "%s += 7;\n", variable); + if (ASN1_TAILQ_EMPTY(t->members)) + length_primitive("bit_string", name, variable); + else { + if (!rfc1510_bitstring) { + Member *m; + int pos = ASN1_TAILQ_LAST(t->members, memhead)->val; + + fprintf(codefile, + "do {\n"); + ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) { + while (m->val / 8 < pos / 8) { + pos -= 8; + } + fprintf (codefile, + "if((%s)->%s) { %s += %d; break; }\n", + name, m->gen_name, variable, (pos + 8) / 8); + } + fprintf(codefile, + "} while(0);\n"); + fprintf (codefile, "%s += 1;\n", variable); + } else { + fprintf (codefile, "%s += 5;\n", variable); + } + } break; } - case TSequence: { - Member *m; - int tag = -1; - int oldret_counter = unique_get_next(); + case TSet: + case TSequence: + case TChoice: { + Member *m, *have_ellipsis = NULL; if (t->members == NULL) break; - for (m = t->members; m && tag != m->val; m = m->next) { - char *s; + if(t->type == TChoice) + fprintf (codefile, "switch((%s)->element) {\n", name); - asprintf (&s, "%s(%s)->%s", - m->optional ? "" : "&", name, m->gen_name); + ASN1_TAILQ_FOREACH(m, t->members, members) { + char *s; + + if (m->ellipsis) { + have_ellipsis = m; + continue; + } + + if(t->type == TChoice) + fprintf(codefile, "case %s:\n", m->label); + + asprintf (&s, "%s(%s)->%s%s", + m->optional ? "" : "&", name, + t->type == TChoice ? "u." : "", m->gen_name); + if (s == NULL) + errx(1, "malloc"); if (m->optional) fprintf (codefile, "if(%s)", s); + else if(m->defval) + gen_compare_defval(s + 1, m->defval); fprintf (codefile, "{\n" - "int oldret%d = %s;\n" - "%s = 0;\n", oldret_counter, variable, variable); + "size_t oldret = %s;\n" + "%s = 0;\n", variable, variable); length_type (s, m->type, "ret"); - fprintf (codefile, "%s += 1 + length_len(%s) + oldret%d;\n", - variable, variable, oldret_counter); + fprintf (codefile, "ret += oldret;\n"); fprintf (codefile, "}\n"); - if (tag == -1) - tag = m->val; free (s); + if(t->type == TChoice) + fprintf(codefile, "break;\n"); + } + if(t->type == TChoice) { + if (have_ellipsis) + fprintf(codefile, + "case %s:\n" + "ret += %s->u.%s.length;\n" + "break;\n", + have_ellipsis->label, + name, + have_ellipsis->gen_name); + fprintf (codefile, "}\n"); /* switch */ } - fprintf (codefile, - "%s += 1 + length_len(%s);\n", variable, variable); break; } + case TSetOf: case TSequenceOf: { char *n; - int oldret_counter = unique_get_next(); - int oldret_counter_inner = unique_get_next(); fprintf (codefile, "{\n" - "int oldret%d = %s;\n" + "int oldret = %s;\n" "int i;\n" "%s = 0;\n", - oldret_counter, variable, variable); + variable, variable); fprintf (codefile, "for(i = (%s)->len - 1; i >= 0; --i){\n", name); - fprintf (codefile, "int oldret%d = %s;\n" - "%s = 0;\n", oldret_counter_inner, variable, variable); + fprintf (codefile, "int oldret = %s;\n" + "%s = 0;\n", variable, variable); asprintf (&n, "&(%s)->val[i]", name); + if (n == NULL) + errx(1, "malloc"); length_type(n, t->subtype, variable); - fprintf (codefile, "%s += oldret%d;\n", - variable, oldret_counter_inner); + fprintf (codefile, "%s += oldret;\n", + variable); fprintf (codefile, "}\n"); fprintf (codefile, - "%s += 1 + length_len(%s) + oldret%d;\n" - "}\n", variable, variable, oldret_counter); + "%s += oldret;\n" + "}\n", variable); free(n); break; } @@ -149,28 +214,43 @@ length_type (const char *name, const Type *t, const char *variable) case TGeneralString: length_primitive ("general_string", name, variable); break; + case TUTCTime: + length_primitive ("utctime", name, variable); + break; case TUTF8String: length_primitive ("utf8string", name, variable); break; + case TPrintableString: + length_primitive ("printable_string", name, variable); + break; + case TIA5String: + length_primitive ("ia5_string", name, variable); + break; + case TBMPString: + length_primitive ("bmp_string", name, variable); + break; + case TUniversalString: + length_primitive ("universal_string", name, variable); + break; case TNull: - fprintf (codefile, "%s += length_nulltype();\n", variable); + fprintf (codefile, "/* NULL */\n"); break; - case TApplication: + case TTag: length_type (name, t->subtype, variable); - fprintf (codefile, "ret += 1 + length_len (ret);\n"); + fprintf (codefile, "ret += %d + length_len (ret);\n", length_tag(t->tag.tagvalue)); break; - case TBoolean: - length_primitive ("boolean", name, variable); + case TOID: + length_primitive ("oid", name, variable); break; default : abort (); } + return 0; } void generate_type_length (const Symbol *s) { - unique_reset(); fprintf (headerfile, "size_t length_%s(const %s *);\n", s->gen_name, s->gen_name); diff --git a/lib/asn1/gen_locl.h b/lib/asn1/gen_locl.h index 35d378046..9e270c8b3 100644 --- a/lib/asn1/gen_locl.h +++ b/lib/asn1/gen_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -51,6 +51,8 @@ #include #include "hash.h" #include "symbol.h" +#include "asn1-common.h" +#include "der.h" void generate_type (const Symbol *); void generate_constant (const Symbol *); @@ -61,10 +63,14 @@ void generate_type_free (const Symbol *s); void generate_type_length (const Symbol *s); void generate_type_copy (const Symbol *s); void generate_type_maybe (const Symbol *s); -void generate_glue (const Symbol *s); +void generate_glue (const Type *, const char*); + +const char *classname(Der_class); +const char *valuename(Der_class class, int); + +void gen_compare_defval(const char *var, struct value *val); +void gen_assign_defval(const char *var, struct value *val); -void unique_reset(void); -int unique_get_next(void); void init_generate (const char *filename, const char *basename); const char *get_filename (void); @@ -72,6 +78,12 @@ void close_generate(void); void add_import(const char *module); int yyparse(void); +int preserve_type(const char *); + extern FILE *headerfile, *codefile, *logfile; +extern int dce_fix; +extern int rfc1510_bitstring; + +extern int error_flag; #endif /* __GEN_LOCL_H__ */ diff --git a/lib/asn1/heim_asn1.h b/lib/asn1/heim_asn1.h index f1735a7bb..99f8e9514 100644 --- a/lib/asn1/heim_asn1.h +++ b/lib/asn1/heim_asn1.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Kungliga Tekniska Högskolan + * Copyright (c) 2003-2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -34,12 +34,8 @@ #ifndef __HEIM_ANY_H__ #define __HEIM_ANY_H__ 1 -typedef struct heim_any { - size_t length; - void *data; -} heim_any; - -typedef struct heim_any heim_any_set; +typedef struct heim_octet_string heim_any; +typedef struct heim_octet_string heim_any_set; int encode_heim_any(unsigned char *, size_t, const heim_any *, size_t *); int decode_heim_any(const unsigned char *, size_t, heim_any *, size_t *); @@ -54,5 +50,6 @@ int decode_heim_any_set(const unsigned char *, size_t, void free_heim_any_set(heim_any_set *); size_t length_heim_any_set(const heim_any_set *); int copy_heim_any_set(const heim_any_set *, heim_any_set *); +int heim_any_cmp(const heim_any_set *, const heim_any_set *); #endif /* __HEIM_ANY_H__ */ diff --git a/lib/asn1/k5.asn1 b/lib/asn1/k5.asn1 index ad72a01fc..bbc2ddf36 100644 --- a/lib/asn1/k5.asn1 +++ b/lib/asn1/k5.asn1 @@ -11,7 +11,11 @@ NAME-TYPE ::= INTEGER { KRB5_NT_SRV_XHST(4), -- Service with host as remaining components KRB5_NT_UID(5), -- Unique ID KRB5_NT_X500_PRINCIPAL(6), -- PKINIT - KRB5_NT_ENTERPRISE(10) -- May be mapped to principal name + KRB5_NT_SMTP_NAME(7), -- Name in form of SMTP email name + KRB5_NT_ENTERPRISE_PRINCIPAL(10), -- Windows 2000 UPN + KRB5_NT_ENT_PRINCIPAL_AND_ID(-130), -- Windows 2000 UPN and SID + KRB5_NT_MS_PRINCIPAL(-128), -- NT 4 style name + KRB5_NT_MS_PRINCIPAL_AND_ID(-129) -- NT style name and SID } -- message types @@ -49,6 +53,7 @@ PADATA-TYPE ::= INTEGER { KRB5-PADATA-SAM-RESPONSE(13), -- (sam/otp) KRB5-PADATA-PK-AS-REQ-19(14), -- (PKINIT-19) KRB5-PADATA-PK-AS-REP-19(15), -- (PKINIT-19) + KRB5-PADATA-PK-AS-REQ-WIN(15), -- (PKINIT - old number) KRB5-PADATA-PK-AS-REQ(16), -- (PKINIT-25) KRB5-PADATA-PK-AS-REP(17), -- (PKINIT-25) KRB5-PADATA-ETYPE-INFO2(19), @@ -58,7 +63,6 @@ PADATA-TYPE ::= INTEGER { KRB5-PADATA-SAM-ETYPE-INFO(23), KRB5-PADATA-SERVER-REFERRAL(25), KRB5-PADATA-TD-KRB-PRINCIPAL(102), -- PrincipalName - KRB5-PADATA-TD-KRB-REALM(103), -- Realm KRB5-PADATA-PK-TD-TRUSTED-CERTIFIERS(104), -- PKINIT KRB5-PADATA-PK-TD-CERTIFICATE-INDEX(105), -- PKINIT KRB5-PADATA-TD-APP-DEFINED-ERROR(106), -- application specific @@ -137,9 +141,13 @@ ENCTYPE ::= INTEGER { ETYPE_DES3_CBC_NONE_CMS(-0x100a) } + + + -- this is sugar to make something ASN1 does not have: unsigned -UNSIGNED ::= INTEGER (0..4294967295) +krb5uint32 ::= INTEGER (0..4294967295) +krb5int32 ::= INTEGER (-2147483648..2147483647) KerberosString ::= GeneralString @@ -156,14 +164,14 @@ Principal ::= SEQUENCE { } HostAddress ::= SEQUENCE { - addr-type[0] INTEGER, + addr-type[0] krb5int32, address[1] OCTET STRING } -- This is from RFC1510. -- -- HostAddresses ::= SEQUENCE OF SEQUENCE { --- addr-type[0] INTEGER, +-- addr-type[0] krb5int32, -- address[1] OCTET STRING -- } @@ -174,7 +182,7 @@ HostAddresses ::= SEQUENCE OF HostAddress KerberosTime ::= GeneralizedTime -- Specifying UTC time zone (Z) AuthorizationData ::= SEQUENCE OF SEQUENCE { - ad-type[0] INTEGER, + ad-type[0] krb5int32, ad-data[1] OCTET STRING } @@ -243,23 +251,23 @@ LastReq ::= SEQUENCE OF SEQUENCE { EncryptedData ::= SEQUENCE { etype[0] ENCTYPE, -- EncryptionType - kvno[1] INTEGER OPTIONAL, + kvno[1] krb5int32 OPTIONAL, cipher[2] OCTET STRING -- ciphertext } EncryptionKey ::= SEQUENCE { - keytype[0] INTEGER, + keytype[0] krb5int32, keyvalue[1] OCTET STRING } -- encoded Transited field TransitedEncoding ::= SEQUENCE { - tr-type[0] INTEGER, -- must be registered + tr-type[0] krb5int32, -- must be registered contents[1] OCTET STRING } Ticket ::= [APPLICATION 1] SEQUENCE { - tkt-vno[0] INTEGER, + tkt-vno[0] krb5int32, realm[1] Realm, sname[2] PrincipalName, enc-part[3] EncryptedData @@ -285,14 +293,14 @@ Checksum ::= SEQUENCE { } Authenticator ::= [APPLICATION 2] SEQUENCE { - authenticator-vno[0] INTEGER, + authenticator-vno[0] krb5int32, crealm[1] Realm, cname[2] PrincipalName, cksum[3] Checksum OPTIONAL, - cusec[4] INTEGER, + cusec[4] krb5int32, ctime[5] KerberosTime, subkey[6] EncryptionKey OPTIONAL, - seq-number[7] UNSIGNED OPTIONAL, + seq-number[7] krb5uint32 OPTIONAL, authorization-data[8] AuthorizationData OPTIONAL } @@ -305,7 +313,7 @@ PA-DATA ::= SEQUENCE { ETYPE-INFO-ENTRY ::= SEQUENCE { etype[0] ENCTYPE, salt[1] OCTET STRING OPTIONAL, - salttype[2] INTEGER OPTIONAL + salttype[2] krb5int32 OPTIONAL } ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY @@ -320,6 +328,13 @@ ETYPE-INFO2 ::= SEQUENCE OF ETYPE-INFO2-ENTRY METHOD-DATA ::= SEQUENCE OF PA-DATA +TypedData ::= SEQUENCE { + data-type[0] krb5int32, + data-value[1] OCTET STRING OPTIONAL +} + +TYPED-DATA ::= SEQUENCE OF TypedData + KDC-REQ-BODY ::= SEQUENCE { kdc-options[0] KDCOptions, cname[1] PrincipalName OPTIONAL, -- Used only in AS-REQ @@ -329,7 +344,7 @@ KDC-REQ-BODY ::= SEQUENCE { from[4] KerberosTime OPTIONAL, till[5] KerberosTime OPTIONAL, rtime[6] KerberosTime OPTIONAL, - nonce[7] INTEGER, + nonce[7] krb5int32, etype[8] SEQUENCE OF ENCTYPE, -- EncryptionType, -- in preference order addresses[9] HostAddresses OPTIONAL, @@ -339,7 +354,7 @@ KDC-REQ-BODY ::= SEQUENCE { } KDC-REQ ::= SEQUENCE { - pvno[1] INTEGER, + pvno[1] krb5int32, msg-type[2] MESSAGE-TYPE, padata[3] METHOD-DATA OPTIONAL, req-body[4] KDC-REQ-BODY @@ -353,7 +368,7 @@ TGS-REQ ::= [APPLICATION 12] KDC-REQ PA-ENC-TS-ENC ::= SEQUENCE { patimestamp[0] KerberosTime, -- client's time - pausec[1] INTEGER OPTIONAL + pausec[1] krb5int32 OPTIONAL } -- draft-brezak-win2k-krb-authz-01 @@ -362,8 +377,11 @@ PA-PAC-REQUEST ::= SEQUENCE { -- should be included or not } +-- PacketCable provisioning server location, PKT-SP-SEC-I09-030728.pdf +PROV-SRV-LOCATION ::= GeneralString + KDC-REP ::= SEQUENCE { - pvno[0] INTEGER, + pvno[0] krb5int32, msg-type[1] MESSAGE-TYPE, padata[2] METHOD-DATA OPTIONAL, crealm[3] Realm, @@ -378,7 +396,7 @@ TGS-REP ::= [APPLICATION 13] KDC-REP EncKDCRepPart ::= SEQUENCE { key[0] EncryptionKey, last-req[1] LastReq, - nonce[2] INTEGER, + nonce[2] krb5int32, key-expiration[3] KerberosTime OPTIONAL, flags[4] TicketFlags, authtime[5] KerberosTime, @@ -394,7 +412,7 @@ EncASRepPart ::= [APPLICATION 25] EncKDCRepPart EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart AP-REQ ::= [APPLICATION 14] SEQUENCE { - pvno[0] INTEGER, + pvno[0] krb5int32, msg-type[1] MESSAGE-TYPE, ap-options[2] APOptions, ticket[3] Ticket, @@ -402,50 +420,50 @@ AP-REQ ::= [APPLICATION 14] SEQUENCE { } AP-REP ::= [APPLICATION 15] SEQUENCE { - pvno[0] INTEGER, + pvno[0] krb5int32, msg-type[1] MESSAGE-TYPE, enc-part[2] EncryptedData } EncAPRepPart ::= [APPLICATION 27] SEQUENCE { ctime[0] KerberosTime, - cusec[1] INTEGER, + cusec[1] krb5int32, subkey[2] EncryptionKey OPTIONAL, - seq-number[3] UNSIGNED OPTIONAL + seq-number[3] krb5uint32 OPTIONAL } KRB-SAFE-BODY ::= SEQUENCE { user-data[0] OCTET STRING, timestamp[1] KerberosTime OPTIONAL, - usec[2] INTEGER OPTIONAL, - seq-number[3] UNSIGNED OPTIONAL, + usec[2] krb5int32 OPTIONAL, + seq-number[3] krb5uint32 OPTIONAL, s-address[4] HostAddress OPTIONAL, r-address[5] HostAddress OPTIONAL } KRB-SAFE ::= [APPLICATION 20] SEQUENCE { - pvno[0] INTEGER, + pvno[0] krb5int32, msg-type[1] MESSAGE-TYPE, safe-body[2] KRB-SAFE-BODY, cksum[3] Checksum } KRB-PRIV ::= [APPLICATION 21] SEQUENCE { - pvno[0] INTEGER, + pvno[0] krb5int32, msg-type[1] MESSAGE-TYPE, enc-part[3] EncryptedData } EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE { user-data[0] OCTET STRING, timestamp[1] KerberosTime OPTIONAL, - usec[2] INTEGER OPTIONAL, - seq-number[3] UNSIGNED OPTIONAL, + usec[2] krb5int32 OPTIONAL, + seq-number[3] krb5uint32 OPTIONAL, s-address[4] HostAddress OPTIONAL, -- sender's addr r-address[5] HostAddress OPTIONAL -- recip's addr } KRB-CRED ::= [APPLICATION 22] SEQUENCE { - pvno[0] INTEGER, + pvno[0] krb5int32, msg-type[1] MESSAGE-TYPE, -- KRB_CRED tickets[2] SEQUENCE OF Ticket, enc-part[3] EncryptedData @@ -467,21 +485,21 @@ KrbCredInfo ::= SEQUENCE { EncKrbCredPart ::= [APPLICATION 29] SEQUENCE { ticket-info[0] SEQUENCE OF KrbCredInfo, - nonce[1] INTEGER OPTIONAL, + nonce[1] krb5int32 OPTIONAL, timestamp[2] KerberosTime OPTIONAL, - usec[3] INTEGER OPTIONAL, + usec[3] krb5int32 OPTIONAL, s-address[4] HostAddress OPTIONAL, r-address[5] HostAddress OPTIONAL } KRB-ERROR ::= [APPLICATION 30] SEQUENCE { - pvno[0] INTEGER, + pvno[0] krb5int32, msg-type[1] MESSAGE-TYPE, ctime[2] KerberosTime OPTIONAL, - cusec[3] INTEGER OPTIONAL, + cusec[3] krb5int32 OPTIONAL, stime[4] KerberosTime, - susec[5] INTEGER, - error-code[6] INTEGER, + susec[5] krb5int32, + error-code[6] krb5int32, crealm[7] Realm OPTIONAL, cname[8] PrincipalName OPTIONAL, realm[9] Realm, -- Correct realm @@ -496,15 +514,15 @@ ChangePasswdDataMS ::= SEQUENCE { targrealm[2] Realm OPTIONAL } -EtypeList ::= SEQUENCE OF INTEGER +EtypeList ::= SEQUENCE OF krb5int32 -- the client's proposed enctype list in -- decreasing preference order, favorite choice first -krb5-pvno INTEGER ::= 5 -- current Kerberos protocol version number +pvno krb5int32 ::= 5 -- current Kerberos protocol version number -- transited encodings -DOMAIN-X500-COMPRESS INTEGER ::= 1 +DOMAIN-X500-COMPRESS krb5int32 ::= 1 -- authorization data primitives @@ -544,7 +562,7 @@ SAMFlags ::= BIT STRING { } PA-SAM-CHALLENGE-2-BODY ::= SEQUENCE { - sam-type[0] INTEGER, + sam-type[0] krb5int32, sam-flags[1] SAMFlags, sam-type-name[2] GeneralString OPTIONAL, sam-track-id[3] GeneralString OPTIONAL, @@ -552,8 +570,8 @@ PA-SAM-CHALLENGE-2-BODY ::= SEQUENCE { sam-challenge[5] GeneralString OPTIONAL, sam-response-prompt[6] GeneralString OPTIONAL, sam-pk-for-sad[7] EncryptionKey OPTIONAL, - sam-nonce[8] INTEGER, - sam-etype[9] INTEGER, + sam-nonce[8] krb5int32, + sam-etype[9] krb5int32, ... } @@ -564,27 +582,31 @@ PA-SAM-CHALLENGE-2 ::= SEQUENCE { } PA-SAM-RESPONSE-2 ::= SEQUENCE { - sam-type[0] INTEGER, + sam-type[0] krb5int32, sam-flags[1] SAMFlags, sam-track-id[2] GeneralString OPTIONAL, sam-enc-nonce-or-sad[3] EncryptedData, -- PA-ENC-SAM-RESPONSE-ENC - sam-nonce[4] INTEGER, + sam-nonce[4] krb5int32, ... } PA-ENC-SAM-RESPONSE-ENC ::= SEQUENCE { - sam-nonce[0] INTEGER, + sam-nonce[0] krb5int32, sam-sad[1] GeneralString OPTIONAL, ... } +-- This is really part of CMS, but its here because KCRYPTO provides +-- the crypto framework for CMS glue in heimdal. + RC2CBCParameter ::= SEQUENCE { - rc2ParameterVersion [0] INTEGER, - iv [1] OCTET STRING -- exactly 8 octets + rc2ParameterVersion krb5int32, + iv OCTET STRING -- exactly 8 octets } CBCParameter ::= OCTET STRING + END -- etags -r '/\([A-Za-z][-A-Za-z0-9]*\).*::=/\1/' k5.asn1 diff --git a/lib/asn1/lex.h b/lib/asn1/lex.h index 221cd6a8c..34cef1716 100644 --- a/lib/asn1/lex.h +++ b/lib/asn1/lex.h @@ -37,5 +37,6 @@ void error_message (const char *, ...) __attribute__ ((format (printf, 1, 2))); +extern int error_flag; int yylex(void); diff --git a/lib/asn1/lex.l b/lib/asn1/lex.l index 8004cb0e0..005f5e5ad 100644 --- a/lib/asn1/lex.l +++ b/lib/asn1/lex.l @@ -1,6 +1,6 @@ %{ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -52,62 +52,118 @@ static unsigned lineno = 1; -#define YY_NO_UNPUT - #undef ECHO static void handle_comment(int type); - +static char *handle_string(void); %} %% -INTEGER { return INTEGER; } -BOOLEAN { return BOOLEAN; } -IMPORTS { return IMPORTS; } -FROM { return FROM; } -SEQUENCE { return SEQUENCE; } -CHOICE { return CHOICE; } -OF { return OF; } -OCTET { return OCTET; } -STRING { return STRING; } -GeneralizedTime { return GeneralizedTime; } -GeneralString { return GeneralString; } -UTF8String { return UTF8String; } -NULL { return NULLTYPE; } -BIT { return BIT; } -APPLICATION { return APPLICATION; } -OPTIONAL { return OPTIONAL; } -BEGIN { return TBEGIN; } -END { return END; } -DEFAULT { return DEFAULT; } -DEFINITIONS { return DEFINITIONS; } -ENUMERATED { return ENUMERATED; } -EXTERNAL { return EXTERNAL; } -OBJECT { return OBJECT; } -IDENTIFIER { return IDENTIFIER; } -[-,;{}()|\"] { return *yytext; } +ABSENT { return kw_ABSENT; } +ABSTRACT-SYNTAX { return kw_ABSTRACT_SYNTAX; } +ALL { return kw_ALL; } +APPLICATION { return kw_APPLICATION; } +AUTOMATIC { return kw_AUTOMATIC; } +BEGIN { return kw_BEGIN; } +BIT { return kw_BIT; } +BMPString { return kw_BMPString; } +BOOLEAN { return kw_BOOLEAN; } +BY { return kw_BY; } +CHARACTER { return kw_CHARACTER; } +CHOICE { return kw_CHOICE; } +CLASS { return kw_CLASS; } +COMPONENT { return kw_COMPONENT; } +COMPONENTS { return kw_COMPONENTS; } +CONSTRAINED { return kw_CONSTRAINED; } +CONTAINING { return kw_CONTAINING; } +DEFAULT { return kw_DEFAULT; } +DEFINITIONS { return kw_DEFINITIONS; } +EMBEDDED { return kw_EMBEDDED; } +ENCODED { return kw_ENCODED; } +END { return kw_END; } +ENUMERATED { return kw_ENUMERATED; } +EXCEPT { return kw_EXCEPT; } +EXPLICIT { return kw_EXPLICIT; } +EXPORTS { return kw_EXPORTS; } +EXTENSIBILITY { return kw_EXTENSIBILITY; } +EXTERNAL { return kw_EXTERNAL; } +FALSE { return kw_FALSE; } +FROM { return kw_FROM; } +GeneralString { return kw_GeneralString; } +GeneralizedTime { return kw_GeneralizedTime; } +GraphicString { return kw_GraphicString; } +IA5String { return kw_IA5String; } +IDENTIFIER { return kw_IDENTIFIER; } +IMPLICIT { return kw_IMPLICIT; } +IMPLIED { return kw_IMPLIED; } +IMPORTS { return kw_IMPORTS; } +INCLUDES { return kw_INCLUDES; } +INSTANCE { return kw_INSTANCE; } +INTEGER { return kw_INTEGER; } +INTERSECTION { return kw_INTERSECTION; } +ISO646String { return kw_ISO646String; } +MAX { return kw_MAX; } +MIN { return kw_MIN; } +MINUS-INFINITY { return kw_MINUS_INFINITY; } +NULL { return kw_NULL; } +NumericString { return kw_NumericString; } +OBJECT { return kw_OBJECT; } +OCTET { return kw_OCTET; } +OF { return kw_OF; } +OPTIONAL { return kw_OPTIONAL; } +ObjectDescriptor { return kw_ObjectDescriptor; } +PATTERN { return kw_PATTERN; } +PDV { return kw_PDV; } +PLUS-INFINITY { return kw_PLUS_INFINITY; } +PRESENT { return kw_PRESENT; } +PRIVATE { return kw_PRIVATE; } +PrintableString { return kw_PrintableString; } +REAL { return kw_REAL; } +RELATIVE_OID { return kw_RELATIVE_OID; } +SEQUENCE { return kw_SEQUENCE; } +SET { return kw_SET; } +SIZE { return kw_SIZE; } +STRING { return kw_STRING; } +SYNTAX { return kw_SYNTAX; } +T61String { return kw_T61String; } +TAGS { return kw_TAGS; } +TRUE { return kw_TRUE; } +TYPE-IDENTIFIER { return kw_TYPE_IDENTIFIER; } +TeletexString { return kw_TeletexString; } +UNION { return kw_UNION; } +UNIQUE { return kw_UNIQUE; } +UNIVERSAL { return kw_UNIVERSAL; } +UTCTime { return kw_UTCTime; } +UTF8String { return kw_UTF8String; } +UniversalString { return kw_UniversalString; } +VideotexString { return kw_VideotexString; } +VisibleString { return kw_VisibleString; } +WITH { return kw_WITH; } +[-,;{}()|] { return *yytext; } "[" { return *yytext; } "]" { return *yytext; } ::= { return EEQUAL; } -- { handle_comment(0); } \/\* { handle_comment(1); } -0x[0-9A-Fa-f]+|[0-9]+ { char *e, *y = yytext; +"\"" { yylval.name = handle_string(); return STRING; } + +-?0x[0-9A-Fa-f]+|-?[0-9]+ { char *e, *y = yytext; yylval.constant = strtol((const char *)yytext, &e, 0); if(e == y) error_message("malformed constant (%s)", yytext); else - return CONSTANT; + return NUMBER; } [A-Za-z][-A-Za-z0-9_]* { - yylval.name = strdup ((const char *)yytext); - return IDENT; + yylval.name = estrdup ((const char *)yytext); + return IDENTIFIER; } [ \t] ; \n { ++lineno; } -\.\.\. { return DOTDOTDOT; } -\.\. { return DOTDOT; } +\.\.\. { return ELLIPSIS; } +\.\. { return RANGE; } . { error_message("Ignoring char(%c)\n", *yytext); } %% @@ -128,6 +184,7 @@ error_message (const char *format, ...) fprintf (stderr, "%s:%d: ", get_filename(), lineno); vfprintf (stderr, format, args); va_end (args); + error_flag++; } static void @@ -165,6 +222,12 @@ handle_comment(int type) seen_slash = 1; continue; } + if(seen_star && c == '/') { + if(--level == 0) + return; + seen_star = 0; + continue; + } if(c == '*') { if(seen_slash) { level++; @@ -184,3 +247,50 @@ handle_comment(int type) if(c == EOF) error_message("unterminated comment, possibly started on line %d\n", start_lineno); } + +static char * +handle_string(void) +{ + int start_lineno = lineno; + int c; + char buf[1024]; + char *p = buf; + int f = 0; + int skip_ws = 0; + + while((c = input()) != EOF) { + if(isspace(c) && skip_ws) { + if(c == '\n') + lineno++; + continue; + } + skip_ws = 0; + + if(c == '"') { + if(f) { + *p++ = '"'; + f = 0; + } else + f = 1; + continue; + } + if(f == 1) { + unput(c); + break; + } + if(c == '\n') { + lineno++; + while(p > buf && isspace((unsigned char)p[-1])) + p--; + skip_ws = 1; + continue; + } + *p++ = c; + } + if(c == EOF) + error_message("unterminated string, possibly started on line %d\n", start_lineno); + *p++ = '\0'; + fprintf(stderr, "string -- %s\n", buf); + return estrdup(buf); +} + diff --git a/lib/asn1/gen.h b/lib/asn1/libasn1.h similarity index 83% rename from lib/asn1/gen.h rename to lib/asn1/libasn1.h index a18d5e15a..53155f2c6 100644 --- a/lib/asn1/gen.h +++ b/lib/asn1/libasn1.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,6 +33,19 @@ /* $Id$ */ -#include -#include "symbol.h" +#ifndef __LIBASN1_H__ +#define __LIBASN1_H__ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include "krb5_asn1.h" +#include "der.h" +#include "asn1_err.h" +#include + +#endif /* __LIBASN1_H__ */ diff --git a/lib/asn1/main.c b/lib/asn1/main.c index 01c98c420..a8041210a 100644 --- a/lib/asn1/main.c +++ b/lib/asn1/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,14 +33,32 @@ #include "gen_locl.h" #include +#include "lex.h" RCSID("$Id$"); extern FILE *yyin; +static getarg_strings preserve; + +int +preserve_type(const char *p) +{ + int i; + for (i = 0; i < preserve.num_strings; i++) + if (strcmp(preserve.strings[i], p) == 0) + return 1; + return 0; +} + +int dce_fix; +int rfc1510_bitstring; int version_flag; int help_flag; struct getargs args[] = { + { "encode-rfc1510-bit-string", 0, arg_flag, &rfc1510_bitstring }, + { "decode-dce-ber", 0, arg_flag, &dce_fix }, + { "preserve-binary", 0, arg_strings, &preserve }, { "version", 0, arg_flag, &version_flag }, { "help", 0, arg_flag, &help_flag } }; @@ -53,12 +71,14 @@ usage(int code) exit(code); } +int error_flag; + int main(int argc, char **argv) { int ret; - const char *file; - const char *name = NULL; + char *file; + char *name = NULL; int optidx = 0; setprogname(argv[0]); @@ -79,12 +99,21 @@ main(int argc, char **argv) yyin = fopen (file, "r"); if (yyin == NULL) err (1, "open %s", file); - name = argv[optidx + 1]; + if (argc == optidx + 1) { + char *p; + name = estrdup(file); + p = strrchr(name, '.'); + if (p) + *p = '\0'; + } else + name = argv[optidx + 1]; } init_generate (file, name); initsym (); ret = yyparse (); + if(ret != 0 || error_flag != 0) + exit(1); close_generate (); - return ret; + return 0; } diff --git a/lib/asn1/parse.y b/lib/asn1/parse.y index fb85b81f0..b70da99e0 100644 --- a/lib/asn1/parse.y +++ b/lib/asn1/parse.y @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -43,223 +43,770 @@ #include "symbol.h" #include "lex.h" #include "gen_locl.h" +#include "der.h" RCSID("$Id$"); static Type *new_type (Typetype t); +static Type *new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype); void yyerror (char *); +static struct objid *new_objid(const char *label, int value); +static void add_oid_to_tail(struct objid *, struct objid *); +static void fix_labels(Symbol *s); -static void append (Member *l, Member *r); +struct string_list { + char *string; + struct string_list *next; +}; %} %union { - int constant; - char *name; - Type *type; - Member *member; - char *defval; + int constant; + struct value *value; + struct range range; + char *name; + Type *type; + Member *member; + struct objid *objid; + char *defval; + struct string_list *sl; + struct tagtype tag; + struct memhead *members; } -%token INTEGER SEQUENCE CHOICE OF OCTET STRING GeneralizedTime GeneralString -%token BIT APPLICATION OPTIONAL EEQUAL TBEGIN END DEFINITIONS ENUMERATED -%token UTF8String NULLTYPE -%token EXTERNAL DEFAULT -%token DOTDOT DOTDOTDOT -%token BOOLEAN -%token IMPORTS FROM -%token OBJECT IDENTIFIER -%token IDENT -%token CONSTANT +%token kw_ABSENT +%token kw_ABSTRACT_SYNTAX +%token kw_ALL +%token kw_APPLICATION +%token kw_AUTOMATIC +%token kw_BEGIN +%token kw_BIT +%token kw_BMPString +%token kw_BOOLEAN +%token kw_BY +%token kw_CHARACTER +%token kw_CHOICE +%token kw_CLASS +%token kw_COMPONENT +%token kw_COMPONENTS +%token kw_CONSTRAINED +%token kw_CONTAINING +%token kw_DEFAULT +%token kw_DEFINITIONS +%token kw_EMBEDDED +%token kw_ENCODED +%token kw_END +%token kw_ENUMERATED +%token kw_EXCEPT +%token kw_EXPLICIT +%token kw_EXPORTS +%token kw_EXTENSIBILITY +%token kw_EXTERNAL +%token kw_FALSE +%token kw_FROM +%token kw_GeneralString +%token kw_GeneralizedTime +%token kw_GraphicString +%token kw_IA5String +%token kw_IDENTIFIER +%token kw_IMPLICIT +%token kw_IMPLIED +%token kw_IMPORTS +%token kw_INCLUDES +%token kw_INSTANCE +%token kw_INTEGER +%token kw_INTERSECTION +%token kw_ISO646String +%token kw_MAX +%token kw_MIN +%token kw_MINUS_INFINITY +%token kw_NULL +%token kw_NumericString +%token kw_OBJECT +%token kw_OCTET +%token kw_OF +%token kw_OPTIONAL +%token kw_ObjectDescriptor +%token kw_PATTERN +%token kw_PDV +%token kw_PLUS_INFINITY +%token kw_PRESENT +%token kw_PRIVATE +%token kw_PrintableString +%token kw_REAL +%token kw_RELATIVE_OID +%token kw_SEQUENCE +%token kw_SET +%token kw_SIZE +%token kw_STRING +%token kw_SYNTAX +%token kw_T61String +%token kw_TAGS +%token kw_TRUE +%token kw_TYPE_IDENTIFIER +%token kw_TeletexString +%token kw_UNION +%token kw_UNIQUE +%token kw_UNIVERSAL +%token kw_UTCTime +%token kw_UTF8String +%token kw_UniversalString +%token kw_VideotexString +%token kw_VisibleString +%token kw_WITH -%type constant optional2 -%type type -%type memberdecls memberdecl memberdeclstart bitdecls bitdecl +%token RANGE +%token EEQUAL +%token ELLIPSIS -%type defvalue +%token IDENTIFIER referencename +%token STRING -%start envelope +%token NUMBER +%type SignedNumber +%type Class tagenv + +%type Value +%type BuiltinValue +%type IntegerValue +%type BooleanValue +%type ObjectIdentifierValue +%type CharacterStringValue +%type NullValue +%type DefinedValue +%type ReferencedValue +%type Valuereference + +%type Type +%type BuiltinType +%type BitStringType +%type BooleanType +%type ChoiceType +%type EnumeratedType +%type IntegerType +%type NullType +%type OctetStringType +%type SequenceType +%type SequenceOfType +%type SetType +%type SetOfType +%type TaggedType +%type ReferencedType +%type DefinedType +%type UsefulType +%type ObjectIdentifierType +%type CharacterStringType +%type RestrictedCharactedStringType + +%type Tag + +%type ComponentType +%type NamedBit +%type NamedNumber +%type NamedType +%type ComponentTypeList +%type Enumerations +%type NamedBitList +%type NamedNumberList + +%type objid objid_list objid_element objid_opt +%type range + +%type referencenames + +%start ModuleDefinition %% -envelope : IDENT DEFINITIONS EEQUAL TBEGIN specification END {} - ; - -specification : - | specification declaration - ; - -declaration : imports_decl - | type_decl - | constant_decl - ; - -referencenames : IDENT ',' referencenames +ModuleDefinition: IDENTIFIER kw_DEFINITIONS TagDefault ExtensionDefault + EEQUAL kw_BEGIN ModuleBody kw_END { - Symbol *s = addsym($1); + checkundefined(); + } + ; + +TagDefault : kw_EXPLICIT kw_TAGS + | kw_IMPLICIT kw_TAGS + { error_message("implicit tagging is not supported"); } + | kw_AUTOMATIC kw_TAGS + { error_message("automatic tagging is not supported"); } + | /* empty */ + ; + +ExtensionDefault: kw_EXTENSIBILITY kw_IMPLIED + { error_message("no extensibility options supported"); } + | /* empty */ + ; + +ModuleBody : /* Exports */ Imports AssignmentList + | /* empty */ + ; + +Imports : kw_IMPORTS SymbolsImported ';' + | /* empty */ + ; + +SymbolsImported : SymbolsFromModuleList + | /* empty */ + ; + +SymbolsFromModuleList: SymbolsFromModule + | SymbolsFromModuleList SymbolsFromModule + ; + +SymbolsFromModule: referencenames kw_FROM IDENTIFIER objid_opt + { + struct string_list *sl; + for(sl = $1; sl != NULL; sl = sl->next) { + Symbol *s = addsym(sl->string); s->stype = Stype; + } + add_import($3); } - | IDENT + ; + +AssignmentList : Assignment + | Assignment AssignmentList + ; + +Assignment : TypeAssignment + | ValueAssignment + ; + +referencenames : IDENTIFIER ',' referencenames { - Symbol *s = addsym($1); - s->stype = Stype; + $$ = emalloc(sizeof(*$$)); + $$->string = $1; + $$->next = $3; } - ; - -imports_decl : IMPORTS referencenames FROM IDENT ';' - { add_import($4); } - ; - -type_decl : IDENT EEQUAL type + | IDENTIFIER { - Symbol *s = addsym ($1); - s->stype = Stype; - s->type = $3; - generate_type (s); + $$ = emalloc(sizeof(*$$)); + $$->string = $1; + $$->next = NULL; } ; -constant_decl : IDENT type EEQUAL constant +TypeAssignment : IDENTIFIER EEQUAL Type { - Symbol *s = addsym ($1); - s->stype = SConstant; - s->constant = $4; - generate_constant (s); + Symbol *s = addsym ($1); + s->stype = Stype; + s->type = $3; + fix_labels(s); + generate_type (s); } ; -type : INTEGER { $$ = new_type(TInteger); } - | INTEGER '(' constant DOTDOT constant ')' { - if($3 != 0) - error_message("Only 0 supported as low range"); - if($5 != INT_MIN && $5 != UINT_MAX && $5 != INT_MAX) - error_message("Only %u supported as high range", - UINT_MAX); - $$ = new_type(TUInteger); +Type : BuiltinType + | ReferencedType + ; + +BuiltinType : BitStringType + | BooleanType + | CharacterStringType + | ChoiceType + | EnumeratedType + | IntegerType + | NullType + | ObjectIdentifierType + | OctetStringType + | SequenceType + | SequenceOfType + | SetType + | SetOfType + | TaggedType + ; + +BooleanType : kw_BOOLEAN + { + $$ = new_tag(ASN1_C_UNIV, UT_Boolean, + TE_EXPLICIT, new_type(TBoolean)); } - | INTEGER '{' bitdecls '}' - { + ; + +range : '(' Value RANGE Value ')' + { + if($2->type != integervalue || + $4->type != integervalue) + error_message("Non-integer value used in range"); + $$.min = $2->u.integervalue; + $$.max = $4->u.integervalue; + } + ; + +IntegerType : kw_INTEGER + { + $$ = new_tag(ASN1_C_UNIV, UT_Integer, + TE_EXPLICIT, new_type(TInteger)); + } + | kw_INTEGER range + { $$ = new_type(TInteger); - $$->members = $3; - } - | OBJECT IDENTIFIER { $$ = new_type(TOID); } - | ENUMERATED '{' bitdecls '}' - { - $$ = new_type(TEnumerated); - $$->members = $3; + $$->range = emalloc(sizeof(*$$->range)); + *($$->range) = $2; + $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$); } - | OCTET STRING { $$ = new_type(TOctetString); } - | GeneralString { $$ = new_type(TGeneralString); } - | UTF8String { $$ = new_type(TUTF8String); } - | NULLTYPE { $$ = new_type(TNull); } - | GeneralizedTime { $$ = new_type(TGeneralizedTime); } - | SEQUENCE OF type + | kw_INTEGER '{' NamedNumberList '}' { - $$ = new_type(TSequenceOf); - $$->subtype = $3; + $$ = new_type(TInteger); + $$->members = $3; + $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$); } - | SEQUENCE '{' memberdecls '}' + ; + +NamedNumberList : NamedNumber + { + $$ = emalloc(sizeof(*$$)); + ASN1_TAILQ_INIT($$); + ASN1_TAILQ_INSERT_HEAD($$, $1, members); + } + | NamedNumberList ',' NamedNumber + { + ASN1_TAILQ_INSERT_TAIL($1, $3, members); + $$ = $1; + } + | NamedNumberList ',' ELLIPSIS + { $$ = $1; } /* XXX used for Enumerations */ + ; + +NamedNumber : IDENTIFIER '(' SignedNumber ')' + { + $$ = emalloc(sizeof(*$$)); + $$->name = $1; + $$->gen_name = estrdup($1); + output_name ($$->gen_name); + $$->val = $3; + $$->optional = 0; + $$->ellipsis = 0; + $$->type = NULL; + } + ; + +EnumeratedType : kw_ENUMERATED '{' Enumerations '}' + { + $$ = new_type(TInteger); + $$->members = $3; + $$ = new_tag(ASN1_C_UNIV, UT_Enumerated, TE_EXPLICIT, $$); + } + ; + +Enumerations : NamedNumberList /* XXX */ + ; + +BitStringType : kw_BIT kw_STRING + { + $$ = new_type(TBitString); + $$->members = emalloc(sizeof(*$$->members)); + ASN1_TAILQ_INIT($$->members); + $$ = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, $$); + } + | kw_BIT kw_STRING '{' NamedBitList '}' + { + $$ = new_type(TBitString); + $$->members = $4; + $$ = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, $$); + } + ; + +ObjectIdentifierType: kw_OBJECT kw_IDENTIFIER + { + $$ = new_tag(ASN1_C_UNIV, UT_OID, + TE_EXPLICIT, new_type(TOID)); + } + ; +OctetStringType : kw_OCTET kw_STRING + { + $$ = new_tag(ASN1_C_UNIV, UT_OctetString, + TE_EXPLICIT, new_type(TOctetString)); + } + ; + +NullType : kw_NULL + { + $$ = new_tag(ASN1_C_UNIV, UT_Null, + TE_EXPLICIT, new_type(TNull)); + } + ; + +SequenceType : kw_SEQUENCE '{' /* ComponentTypeLists */ ComponentTypeList '}' { $$ = new_type(TSequence); $$->members = $3; + $$ = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, $$); } - | CHOICE '{' memberdecls '}' + | kw_SEQUENCE '{' '}' + { + $$ = new_type(TSequence); + $$->members = NULL; + $$ = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, $$); + } + ; + +SequenceOfType : kw_SEQUENCE kw_OF Type + { + $$ = new_type(TSequenceOf); + $$->subtype = $3; + $$ = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, $$); + } + ; + +SetType : kw_SET '{' /* ComponentTypeLists */ ComponentTypeList '}' + { + $$ = new_type(TSet); + $$->members = $3; + $$ = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, $$); + } + | kw_SET '{' '}' + { + $$ = new_type(TSet); + $$->members = NULL; + $$ = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, $$); + } + ; + +SetOfType : kw_SET kw_OF Type + { + $$ = new_type(TSetOf); + $$->subtype = $3; + $$ = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, $$); + } + ; + +ChoiceType : kw_CHOICE '{' /* AlternativeTypeLists */ ComponentTypeList '}' { $$ = new_type(TChoice); $$->members = $3; } - | BIT STRING '{' bitdecls '}' - { - $$ = new_type(TBitString); - $$->members = $4; - } - | IDENT + ; + +ReferencedType : DefinedType + | UsefulType + ; + +DefinedType : IDENTIFIER { Symbol *s = addsym($1); $$ = new_type(TType); - if(s->stype != Stype) + if(s->stype != Stype && s->stype != SUndefined) error_message ("%s is not a type\n", $1); else $$->symbol = s; } - | '[' APPLICATION constant ']' type + ; + +UsefulType : kw_GeneralizedTime { - $$ = new_type(TApplication); - $$->subtype = $5; - $$->application = $3; + $$ = new_tag(ASN1_C_UNIV, UT_GeneralizedTime, + TE_EXPLICIT, new_type(TGeneralizedTime)); } - | BOOLEAN { $$ = new_type(TBoolean); } - ; - -memberdecls : { $$ = NULL; } - | memberdecl { $$ = $1; } - | memberdecls ',' DOTDOTDOT { $$ = $1; } - | memberdecls ',' memberdecl { $$ = $1; append($$, $3); } - ; - -memberdeclstart : IDENT '[' constant ']' type + | kw_UTCTime { - $$ = malloc(sizeof(*$$)); - $$->name = $1; - $$->gen_name = strdup($1); - output_name ($$->gen_name); - $$->val = $3; - $$->optional = 0; - $$->defval = NULL; - $$->type = $5; - $$->next = $$->prev = $$; + $$ = new_tag(ASN1_C_UNIV, UT_UTCTime, + TE_EXPLICIT, new_type(TUTCTime)); + } + ; + +TaggedType : Tag tagenv Type + { + $$ = new_type(TTag); + $$->tag = $1; + $$->tag.tagenv = $2; + if($3->type == TTag && $2 == TE_IMPLICIT) { + $$->subtype = $3->subtype; + free($3); + } else + $$->subtype = $3; + } + ; + +Tag : '[' Class NUMBER ']' + { + $$.tagclass = $2; + $$.tagvalue = $3; + $$.tagenv = TE_EXPLICIT; + } + ; + +Class : /* */ + { + $$ = ASN1_C_CONTEXT; + } + | kw_UNIVERSAL + { + $$ = ASN1_C_UNIV; + } + | kw_APPLICATION + { + $$ = ASN1_C_APPL; + } + | kw_PRIVATE + { + $$ = ASN1_C_PRIVATE; + } + ; + +tagenv : /* */ + { + $$ = TE_EXPLICIT; + } + | kw_EXPLICIT + { + $$ = TE_EXPLICIT; + } + | kw_IMPLICIT + { + $$ = TE_IMPLICIT; } ; -memberdecl : memberdeclstart optional2 - { $1->optional = $2 ; $$ = $1; } - | memberdeclstart defvalue - { $1->defval = $2 ; $$ = $1; } - | memberdeclstart - { $$ = $1; } - ; - - -optional2 : OPTIONAL { $$ = 1; } - ; - -defvalue : DEFAULT constant - { asprintf(&$$, "%d", $2); } - | DEFAULT '"' IDENT '"' - { $$ = strdup ($3); } - ; - -bitdecls : { $$ = NULL; } - | bitdecl { $$ = $1; } - | bitdecls ',' DOTDOTDOT { $$ = $1; } - | bitdecls ',' bitdecl { $$ = $1; append($$, $3); } - ; - -bitdecl : IDENT '(' constant ')' +ValueAssignment : IDENTIFIER Type EEQUAL Value { - $$ = malloc(sizeof(*$$)); + Symbol *s; + s = addsym ($1); + + s->stype = SValue; + s->value = $4; + generate_constant (s); + } + ; + +CharacterStringType: RestrictedCharactedStringType + ; + +RestrictedCharactedStringType: kw_GeneralString + { + $$ = new_tag(ASN1_C_UNIV, UT_GeneralString, + TE_EXPLICIT, new_type(TGeneralString)); + } + | kw_UTF8String + { + $$ = new_tag(ASN1_C_UNIV, UT_UTF8String, + TE_EXPLICIT, new_type(TUTF8String)); + } + | kw_PrintableString + { + $$ = new_tag(ASN1_C_UNIV, UT_PrintableString, + TE_EXPLICIT, new_type(TPrintableString)); + } + | kw_IA5String + { + $$ = new_tag(ASN1_C_UNIV, UT_IA5String, + TE_EXPLICIT, new_type(TIA5String)); + } + | kw_BMPString + { + $$ = new_tag(ASN1_C_UNIV, UT_BMPString, + TE_EXPLICIT, new_type(TBMPString)); + } + | kw_UniversalString + { + $$ = new_tag(ASN1_C_UNIV, UT_UniversalString, + TE_EXPLICIT, new_type(TUniversalString)); + } + + ; + +ComponentTypeList: ComponentType + { + $$ = emalloc(sizeof(*$$)); + ASN1_TAILQ_INIT($$); + ASN1_TAILQ_INSERT_HEAD($$, $1, members); + } + | ComponentTypeList ',' ComponentType + { + ASN1_TAILQ_INSERT_TAIL($1, $3, members); + $$ = $1; + } + | ComponentTypeList ',' ELLIPSIS + { + struct member *m = ecalloc(1, sizeof(*m)); + m->name = estrdup("..."); + m->gen_name = estrdup("asn1_ellipsis"); + m->ellipsis = 1; + ASN1_TAILQ_INSERT_TAIL($1, m, members); + $$ = $1; + } + ; + +NamedType : IDENTIFIER Type + { + $$ = emalloc(sizeof(*$$)); $$->name = $1; - $$->gen_name = strdup($1); + $$->gen_name = estrdup($1); + output_name ($$->gen_name); + $$->type = $2; + $$->ellipsis = 0; + } + ; + +ComponentType : NamedType + { + $$ = $1; + $$->optional = 0; + $$->defval = NULL; + } + | NamedType kw_OPTIONAL + { + $$ = $1; + $$->optional = 1; + $$->defval = NULL; + } + | NamedType kw_DEFAULT Value + { + $$ = $1; + $$->optional = 0; + $$->defval = $3; + } + ; + +NamedBitList : NamedBit + { + $$ = emalloc(sizeof(*$$)); + ASN1_TAILQ_INIT($$); + ASN1_TAILQ_INSERT_HEAD($$, $1, members); + } + | NamedBitList ',' NamedBit + { + ASN1_TAILQ_INSERT_TAIL($1, $3, members); + $$ = $1; + } + ; + +NamedBit : IDENTIFIER '(' NUMBER ')' + { + $$ = emalloc(sizeof(*$$)); + $$->name = $1; + $$->gen_name = estrdup($1); output_name ($$->gen_name); $$->val = $3; $$->optional = 0; + $$->ellipsis = 0; $$->type = NULL; - $$->prev = $$->next = $$; } ; -constant : CONSTANT { $$ = $1; } - | '-' CONSTANT { $$ = -$2; } - | IDENT { - Symbol *s = addsym($1); - if(s->stype != SConstant) - error_message ("%s is not a constant\n", - s->name); - else - $$ = s->constant; - } +objid_opt : objid + | /* empty */ { $$ = NULL; } ; + +objid : '{' objid_list '}' + { + $$ = $2; + } + ; + +objid_list : /* empty */ + { + $$ = NULL; + } + | objid_element objid_list + { + if ($2) { + $$ = $2; + add_oid_to_tail($2, $1); + } else { + $$ = $1; + } + } + ; + +objid_element : IDENTIFIER '(' NUMBER ')' + { + $$ = new_objid($1, $3); + } + | IDENTIFIER + { + Symbol *s = addsym($1); + if(s->stype != SValue || + s->value->type != objectidentifiervalue) { + error_message("%s is not an object identifier\n", + s->name); + exit(1); + } + $$ = s->value->u.objectidentifiervalue; + } + | NUMBER + { + $$ = new_objid(NULL, $1); + } + ; + +Value : BuiltinValue + | ReferencedValue + ; + +BuiltinValue : BooleanValue + | CharacterStringValue + | IntegerValue + | ObjectIdentifierValue + | NullValue + ; + +ReferencedValue : DefinedValue + ; + +DefinedValue : Valuereference + ; + +Valuereference : IDENTIFIER + { + Symbol *s = addsym($1); + if(s->stype != SValue) + error_message ("%s is not a value\n", + s->name); + else + $$ = s->value; + } + ; + +CharacterStringValue: STRING + { + $$ = emalloc(sizeof(*$$)); + $$->type = stringvalue; + $$->u.stringvalue = $1; + } + ; + +BooleanValue : kw_TRUE + { + $$ = emalloc(sizeof(*$$)); + $$->type = booleanvalue; + $$->u.booleanvalue = 0; + } + | kw_FALSE + { + $$ = emalloc(sizeof(*$$)); + $$->type = booleanvalue; + $$->u.booleanvalue = 0; + } + ; + +IntegerValue : SignedNumber + { + $$ = emalloc(sizeof(*$$)); + $$->type = integervalue; + $$->u.integervalue = $1; + } + ; + +SignedNumber : NUMBER + ; + +NullValue : kw_NULL + { + } + ; + +ObjectIdentifierValue: objid + { + $$ = emalloc(sizeof(*$$)); + $$->type = objectidentifiervalue; + $$->u.objectidentifiervalue = $1; + } + ; + %% void @@ -269,27 +816,80 @@ yyerror (char *s) } static Type * -new_type (Typetype tt) +new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype) { - Type *t = malloc(sizeof(*t)); - if (t == NULL) { - error_message ("out of memory in malloc(%lu)", - (unsigned long)sizeof(*t)); - exit (1); - } - t->type = tt; - t->application = 0; - t->members = NULL; - t->subtype = NULL; - t->symbol = NULL; - return t; + Type *t; + if(oldtype->type == TTag && oldtype->tag.tagenv == TE_IMPLICIT) { + t = oldtype; + oldtype = oldtype->subtype; /* XXX */ + } else + t = new_type (TTag); + + t->tag.tagclass = tagclass; + t->tag.tagvalue = tagvalue; + t->tag.tagenv = tagenv; + t->subtype = oldtype; + return t; +} + +static struct objid * +new_objid(const char *label, int value) +{ + struct objid *s; + s = emalloc(sizeof(*s)); + s->label = label; + s->value = value; + s->next = NULL; + return s; } static void -append (Member *l, Member *r) +add_oid_to_tail(struct objid *head, struct objid *tail) { - l->prev->next = r; - r->prev = l->prev; - l->prev = r; - r->next = l; + struct objid *o; + o = head; + while (o->next) + o = o->next; + o->next = tail; +} + +static Type * +new_type (Typetype tt) +{ + Type *t = ecalloc(1, sizeof(*t)); + t->type = tt; + return t; +} + +static void fix_labels2(Type *t, const char *prefix); +static void fix_labels1(struct memhead *members, const char *prefix) +{ + Member *m; + + if(members == NULL) + return; + ASN1_TAILQ_FOREACH(m, members, members) { + asprintf(&m->label, "%s_%s", prefix, m->gen_name); + if (m->label == NULL) + errx(1, "malloc"); + if(m->type != NULL) + fix_labels2(m->type, m->label); + } +} + +static void fix_labels2(Type *t, const char *prefix) +{ + for(; t; t = t->subtype) + fix_labels1(t->members, prefix); +} + +static void +fix_labels(Symbol *s) +{ + char *p; + asprintf(&p, "choice_%s", s->gen_name); + if (p == NULL) + errx(1, "malloc"); + fix_labels2(s->type, p); + free(p); } diff --git a/lib/asn1/pkcs12.asn1 b/lib/asn1/pkcs12.asn1 new file mode 100644 index 000000000..20913c53e --- /dev/null +++ b/lib/asn1/pkcs12.asn1 @@ -0,0 +1,79 @@ +-- $Id$ -- + +PKCS12 DEFINITIONS ::= + +BEGIN + +IMPORTS ContentInfo FROM cms + DigestInfo FROM rfc2459 + heim_any, heim_any_set FROM heim; + +-- The PFX PDU + +id-pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + rsadsi(113549) pkcs(1) pkcs-12(12) } + +id-pkcs-12PbeIds OBJECT IDENTIFIER ::= { id-pkcs-12 1} +id-pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 1} +id-pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 2} +id-pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 3} +id-pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 4} +id-pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 5} +id-pbewithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 6} + +id-pkcs12-bagtypes OBJECT IDENTIFIER ::= { id-pkcs-12 10 1} + +id-pkcs12-keyBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 1 } +id-pkcs12-pkcs8ShroudedKeyBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 2 } +id-pkcs12-certBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 3 } +id-pkcs12-crlBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 4 } +id-pkcs12-secretBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 5 } +id-pkcs12-safeContentsBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 6 } + + +PKCS12-MacData ::= SEQUENCE { + mac DigestInfo, + macSalt OCTET STRING, + iterations INTEGER OPTIONAL +} + +PKCS12-PFX ::= SEQUENCE { + version INTEGER, + authSafe ContentInfo, + macData PKCS12-MacData OPTIONAL +} + +PKCS12-AuthenticatedSafe ::= SEQUENCE OF ContentInfo + -- Data if unencrypted + -- EncryptedData if password-encrypted + -- EnvelopedData if public key-encrypted + +PKCS12-Attribute ::= SEQUENCE { + attrId OBJECT IDENTIFIER, + attrValues -- SET OF -- heim_any_set +} + +PKCS12-Attributes ::= SET OF PKCS12-Attribute + +PKCS12-SafeBag ::= SEQUENCE { + bagId OBJECT IDENTIFIER, + bagValue [0] heim_any, + bagAttributes PKCS12-Attributes OPTIONAL +} + +PKCS12-SafeContents ::= SEQUENCE OF PKCS12-SafeBag + +PKCS12-CertBag ::= SEQUENCE { + certType OBJECT IDENTIFIER, + certValue [0] heim_any +} + +PKCS12-PBEParams ::= SEQUENCE { + salt OCTET STRING, + iterations INTEGER (0..4294967295) OPTIONAL +} + +-- KeyBag ::= PrivateKeyInfo +-- PKCS8ShroudedKeyBag ::= EncryptedPrivateKeyInfo + +END diff --git a/lib/asn1/pkcs8.asn1 b/lib/asn1/pkcs8.asn1 new file mode 100644 index 000000000..ee107855e --- /dev/null +++ b/lib/asn1/pkcs8.asn1 @@ -0,0 +1,30 @@ +-- $Id$ -- + +PKCS8 DEFINITIONS ::= + +BEGIN + +IMPORTS Attribute, AlgorithmIdentifier FROM rfc2459 + heim_any, heim_any_set FROM heim; + +PKCS8PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + +PKCS8PrivateKey ::= OCTET STRING + +PKCS8Attributes ::= SET OF Attribute + +PKCS8PrivateKeyInfo ::= SEQUENCE { + version INTEGER, + privateKeyAlgorithm PKCS8PrivateKeyAlgorithmIdentifier, + privateKey PKCS8PrivateKey, + attributes [0] IMPLICIT PKCS8Attributes OPTIONAL +} + +PKCS8EncryptedData ::= OCTET STRING + +PKCS8EncryptedPrivateKeyInfo ::= SEQUENCE { + encryptionAlgorithm AlgorithmIdentifier, + encryptedData PKCS8EncryptedData +} + +END diff --git a/lib/asn1/pkcs9.asn1 b/lib/asn1/pkcs9.asn1 new file mode 100644 index 000000000..0f541f771 --- /dev/null +++ b/lib/asn1/pkcs9.asn1 @@ -0,0 +1,22 @@ +-- $Id$ -- + +PKCS9 DEFINITIONS ::= + +BEGIN + +-- The PFX PDU + +id-pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + rsadsi(113549) pkcs(1) pkcs-9(9) } + +id-pkcs-9-at-friendlyName OBJECT IDENTIFIER ::= {id-pkcs-9 20} +id-pkcs-9-at-localKeyId OBJECT IDENTIFIER ::= {id-pkcs-9 21} +id-pkcs-9-at-certTypes OBJECT IDENTIFIER ::= {id-pkcs-9 22} +id-pkcs-9-at-certTypes-x509 OBJECT IDENTIFIER ::= {id-pkcs-9-at-certTypes 1} + +PKCS9-BMPString ::= BMPString + +PKCS9-friendlyName ::= SET OF PKCS9-BMPString + +END + diff --git a/lib/asn1/pkinit.asn1 b/lib/asn1/pkinit.asn1 index 92c5de75d..224702cc5 100644 --- a/lib/asn1/pkinit.asn1 +++ b/lib/asn1/pkinit.asn1 @@ -1,189 +1,171 @@ +-- $Id$ -- + PKINIT DEFINITIONS ::= BEGIN -IMPORTS EncryptionKey, PrincipalName, Realm, KerberosTime, TypedData - FROM krb5; -IMPORTS SignedData, EnvelopedData FROM CMS; -IMPORTS CertificateSerialNumber, AttributeTypeAndValue, Name FROM X509; +IMPORTS EncryptionKey, PrincipalName, Realm, KerberosTime, Checksum FROM krb5 + IssuerAndSerialNumber, ContentInfo FROM cms + SubjectPublicKeyInfo, AlgorithmIdentifier FROM rfc2459 + heim_any FROM heim; +id-pkinit OBJECT IDENTIFIER ::= + { iso (1) org (3) dod (6) internet (1) security (5) + kerberosv5 (2) pkinit (3) } --- 3.1 +id-pkauthdata OBJECT IDENTIFIER ::= { id-pkinit 1 } +id-pkdhkeydata OBJECT IDENTIFIER ::= { id-pkinit 2 } +id-pkrkeydata OBJECT IDENTIFIER ::= { id-pkinit 3 } +id-pkekuoid OBJECT IDENTIFIER ::= { id-pkinit 4 } +id-pkkdcekuoid OBJECT IDENTIFIER ::= { id-pkinit 5 } -CertPrincipalName ::= SEQUENCE { - name-type[0] INTEGER, - name-string[1] SEQUENCE OF UTF8String -} +pa-pk-as-req INTEGER ::= 16 +pa-pk-as-rep INTEGER ::= 17 +ad-initial-verified-cas INTEGER ::= 9 --- 3.2.2 +td-trusted-certifiers INTEGER ::= 104 +td-invalid-certificates INTEGER ::= 105 +td-dh-parameters INTEGER ::= 109 +DHNonce ::= OCTET STRING -TrustedCertifiers ::= SEQUENCE OF PrincipalName - -- X.500 name encoded as a principal name - -- see Section 3.1 -CertificateIndex ::= INTEGER - -- 0 = 1st certificate, - -- (in order of encoding) - -- 1 = 2nd certificate, etc - -PA-PK-AS-REP ::= CHOICE { - -- PA TYPE 15 - dhSignedData[0] SignedData, - -- Defined in CMS and used only with - -- Diffie-Hellman key exchange (if the - -- client public value was present in the - -- request). - -- This choice MUST be supported - -- by compliant implementations. - encKeyPack[1] EnvelopedData - -- Defined in CMS - -- The temporary key is encrypted - -- using the client public key - -- key - -- SignedReplyKeyPack, encrypted - -- with the temporary key, is also - -- included. -} - - - -KdcDHKeyInfo ::= SEQUENCE { - -- used only when utilizing Diffie-Hellman - nonce[0] INTEGER, - -- binds responce to the request - subjectPublicKey[2] BIT STRING - -- Equals public exponent (g^a mod p) - -- INTEGER encoded as payload of - -- BIT STRING -} - -ReplyKeyPack ::= SEQUENCE { - -- not used for Diffie-Hellman - replyKey[0] EncryptionKey, - -- used to encrypt main reply - -- ENCTYPE is at least as strong as - -- ENCTYPE of session key - nonce[1] INTEGER - -- binds response to the request - -- must be same as the nonce - -- passed in the PKAuthenticator -} - --- subjectAltName EXTENSION ::= { --- SYNTAX GeneralNames --- IDENTIFIED BY id-ce-subjectAltName --- } - -OtherName ::= SEQUENCE { - type-id OBJECT IDENTIFIER, - value[0] OCTET STRING --- value[0] EXPLICIT ANY DEFINED BY type-id -} - -GeneralName ::= CHOICE { - otherName [0] OtherName, +TrustedCA ::= SEQUENCE { + caName [0] IMPLICIT OCTET STRING, + certificateSerialNumber [1] INTEGER OPTIONAL, + subjectKeyIdentifier [2] OCTET STRING OPTIONAL, ... } -GeneralNames ::= SEQUENCE -- SIZE(1..MAX) - OF GeneralName - -KerberosName ::= SEQUENCE { - realm[0] Realm, - -- as defined in RFC 1510 - principalName[1] CertPrincipalName - -- defined above -} - - --- krb5 OBJECT IDENTIFIER ::= { --- iso (1) org (3) dod (6) internet (1) security (5) kerberosv5 (2) --- } - --- krb5PrincipalName OBJECT IDENTIFIER ::= { krb5 2 } - --- 3.2.1 - - -IssuerAndSerialNumber ::= SEQUENCE { - issuer Name, - serialNumber CertificateSerialNumber -} - -TrustedCas ::= CHOICE { - principalName[0] KerberosName, - -- as defined below - caName[1] Name, - -- fully qualified X.500 name - -- as defined by X.509 - issuerAndSerial[2] IssuerAndSerialNumber - -- Since a CA may have a number of - -- certificates, only one of which - -- a client trusts -} - PA-PK-AS-REQ ::= SEQUENCE { - -- PA TYPE 14 - signedAuthPack[0] SignedData, - -- defined in CMS [11] - -- AuthPack (below) defines the data - -- that is signed - trustedCertifiers[1] SEQUENCE OF TrustedCas OPTIONAL, - -- CAs that the client trusts - kdcCert[2] IssuerAndSerialNumber OPTIONAL, - -- as defined in CMS [11] - -- specifies a particular KDC - -- certificate if the client - -- already has it; - encryptionCert[3] IssuerAndSerialNumber OPTIONAL - -- For example, this may be the - -- client's Diffie-Hellman - -- certificate, or it may be the - -- client's RSA encryption - -- certificate. + signedAuthPack [0] IMPLICIT OCTET STRING, + trustedCertifiers [1] SEQUENCE OF TrustedCA OPTIONAL, + kdcPkId [2] IMPLICIT OCTET STRING OPTIONAL, + ... } PKAuthenticator ::= SEQUENCE { - kdcName[0] PrincipalName, - kdcRealm[1] Realm, - cusec[2] INTEGER, - -- for replay prevention as in RFC1510 - ctime[3] KerberosTime, - -- for replay prevention as in RFC1510 - nonce[4] INTEGER + cusec [0] INTEGER -- (0..999999) --, + ctime [1] KerberosTime, + nonce [2] INTEGER (0..4294967295), + paChecksum [3] OCTET STRING, + ... } --- This is the real definition of AlgorithmIdentifier --- AlgorithmIdentifier ::= SEQUENCE { --- algorithm ALGORITHM.&id, --- parameters ALGORITHM.&Type --- } -- as specified by the X.509 recommendation[10] - --- But we'll use this one instead: - -AlgorithmIdentifier ::= SEQUENCE { - algorithm OBJECT IDENTIFIER, - parameters CHOICE { - a INTEGER - } -} - - - -SubjectPublicKeyInfo ::= SEQUENCE { - algorithm AlgorithmIdentifier, - -- dhKeyAgreement - subjectPublicKey BIT STRING - -- for DH, equals - -- public exponent (INTEGER encoded - -- as payload of BIT STRING) -} -- as specified by the X.509 recommendation[10] - AuthPack ::= SEQUENCE { - pkAuthenticator[0] PKAuthenticator, - clientPublicValue[1] SubjectPublicKeyInfo OPTIONAL - -- if client is using Diffie-Hellman - -- (ephemeral-ephemeral only) + pkAuthenticator [0] PKAuthenticator, + clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL, + supportedCMSTypes [2] SEQUENCE OF AlgorithmIdentifier OPTIONAL, + clientDHNonce [3] DHNonce OPTIONAL, + ... +} + +TD-TRUSTED-CERTIFIERS ::= SEQUENCE OF TrustedCA +TD-INVALID-CERTIFICATES ::= SEQUENCE OF OCTET STRING + +KRB5PrincipalName ::= SEQUENCE { + realm [0] Realm, + principalName [1] PrincipalName +} + +AD-INITIAL-VERIFIED-CAS ::= SEQUENCE OF TrustedCA + + +DHRepInfo ::= SEQUENCE { + dhSignedData [0] IMPLICIT OCTET STRING, + serverDHNonce [1] DHNonce OPTIONAL +} + +PA-PK-AS-REP ::= CHOICE { + dhInfo [0] DHRepInfo, + encKeyPack [1] IMPLICIT OCTET STRING, + ... +} + +KDCDHKeyInfo ::= SEQUENCE { + subjectPublicKey [0] BIT STRING, + nonce [1] INTEGER (0..4294967295), + dhKeyExpiration [2] KerberosTime OPTIONAL, + ... +} + +ReplyKeyPack ::= SEQUENCE { + replyKey [0] EncryptionKey, + nonce [1] INTEGER (0..4294967295), + ... +} + +TD-DH-PARAMETERS ::= SEQUENCE OF AlgorithmIdentifier + + +-- Windows and pk-init-19 compat glue -- + +PKAuthenticator-Win2k ::= SEQUENCE { + kdcName [0] PrincipalName, + kdcRealm [1] Realm, + cusec [2] INTEGER (0..4294967295), + ctime [3] KerberosTime, + nonce [4] INTEGER (-2147483648..2147483647) +} + +AuthPack-Win2k ::= SEQUENCE { + pkAuthenticator [0] PKAuthenticator-Win2k, + clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL } +PA-PK-AS-REP-Win2k ::= CHOICE { + dhSignedData [0] IMPLICIT OCTET STRING, + encKeyPack [1] IMPLICIT OCTET STRING +} + + +KDCDHKeyInfo-Win2k ::= SEQUENCE { + nonce [0] INTEGER (-2147483648..2147483647), + subjectPublicKey [2] BIT STRING +} + +TrustedCA-19 ::= CHOICE { + caName [1] heim_any, + issuerAndSerial [2] IssuerAndSerialNumber +} + +PA-PK-AS-REQ-19 ::= SEQUENCE { -- PAType 14 + signedAuthPack [0] ContentInfo, -- AuthPack + trustedCertifiers [1] SEQUENCE OF TrustedCA-19 OPTIONAL, + kdcCert [2] IssuerAndSerialNumber OPTIONAL, + encryptionCert [3] IssuerAndSerialNumber OPTIONAL, + ... +} + +PA-PK-AS-REQ-Win2k ::= SEQUENCE { + signed-auth-pack [0] IMPLICIT OCTET STRING, + trusted-certifiers [2] SEQUENCE OF TrustedCA-19 OPTIONAL, + kdc-cert [3] IMPLICIT OCTET STRING OPTIONAL, + encryption-cert [4] IMPLICIT OCTET STRING OPTIONAL +} + +PKAuthenticator-19 ::= SEQUENCE { + cusec [0] INTEGER (0..4294967295), + ctime [1] KerberosTime, + nonce [2] INTEGER (0..4294967295), + paChecksum [3] Checksum, + ... +} + +AuthPack-19 ::= SEQUENCE { + pkAuthenticator [0] PKAuthenticator-19, + clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL +} + +PA-PK-AS-REP-19 ::= CHOICE { + dhSignedData [0] ContentInfo, + encKeyPack [1] ContentInfo, + ... +} + +ReplyKeyPack-19 ::= SEQUENCE { + replyKey [0] EncryptionKey, + nonce [1] INTEGER (0..4294967295), + ... +} + END diff --git a/lib/asn1/rfc2459.asn1 b/lib/asn1/rfc2459.asn1 index c9adec609..8ba58008b 100644 --- a/lib/asn1/rfc2459.asn1 +++ b/lib/asn1/rfc2459.asn1 @@ -1,21 +1,291 @@ +-- $Id$ -- +-- Definitions from rfc2459/rfc3280 + RFC2459 DEFINITIONS ::= BEGIN -AttributeType ::= OBJECT-IDENTIFIER +IMPORTS heim_any FROM heim; -AttributeValue ::= OCTET STRING --ANY DEFINED BY AttributeType - -AttributeTypeAndValue ::= SEQUENCE { - type AttributeType, - value AttributeValue +Version ::= INTEGER { + rfc3280_version_1(0), + rfc3280_version_2(1), + rfc3280_version_3(2) } -RelativeDistinguishedName ::= --SET -SEQUENCE OF AttributeTypeAndValue +id-pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + rsadsi(113549) pkcs(1) 1 } +id-pkcs1-rsaEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 1 } +id-pkcs1-md2WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 2 } +id-pkcs1-md5WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 4 } +id-pkcs1-sha1WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 5 } + +id-pkcs-2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + rsadsi(113549) pkcs(1) 2 } +id-pkcs2-md2 OBJECT IDENTIFIER ::= { id-pkcs-2 2 } +id-pkcs2-md4 OBJECT IDENTIFIER ::= { id-pkcs-2 4 } +id-pkcs2-md5 OBJECT IDENTIFIER ::= { id-pkcs-2 5 } + +id-pkcs-3 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + rsadsi(113549) pkcs(1) 3 } + +id-pkcs3-rc2-cbc OBJECT IDENTIFIER ::= { id-pkcs-3 2 } +id-pkcs3-rc4 OBJECT IDENTIFIER ::= { id-pkcs-3 4 } +id-pkcs3-des-ede3-cbc OBJECT IDENTIFIER ::= { id-pkcs-3 7 } + +id-rsadsi-encalg OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + rsadsi(113549) 3 } + +id-rsadsi-des-ede3-cbc OBJECT IDENTIFIER ::= { id-rsadsi-encalg 7 } + +id-secsig-sha-1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) + oiw(14) secsig(3) algorithm(2) 26 } + +id-nit-aes-algs OBJECT IDENTIFIER ::= { + joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) + nistAlgorithm(4) 1 } + +id-aes-128-cbc OBJECT IDENTIFIER ::= { id-nit-aes-algs 2 } +id-aes-192-cbc OBJECT IDENTIFIER ::= { id-nit-aes-algs 22 } +id-aes-256-cbc OBJECT IDENTIFIER ::= { id-nit-aes-algs 42 } + +id-dhpublicnumber OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) ansi-x942(10046) + number-type(2) 1 } + +id-x509-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} + +AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters heim_any OPTIONAL +} + +AttributeType ::= OBJECT IDENTIFIER + +AttributeValue ::= heim_any + +TeletexStringx ::= [UNIVERSAL 20] IMPLICIT OCTET STRING + +DirectoryString ::= CHOICE { + ia5String IA5String, + teletexString TeletexStringx, + printableString PrintableString, + universalString UniversalString, + utf8String UTF8String, + bmpString BMPString +} + +Attribute ::= SEQUENCE { + type AttributeType, + value AttributeValue +} + +AttributeTypeAndValue ::= SEQUENCE { + type AttributeType, + value DirectoryString +} + +RelativeDistinguishedName ::= SET OF AttributeTypeAndValue RDNSequence ::= SEQUENCE OF RelativeDistinguishedName -Name ::= CHOICE { -- RFC2459 - x RDNSequence +Name ::= CHOICE { + rdnSequence RDNSequence } -END \ No newline at end of file +CertificateSerialNumber ::= INTEGER + +Time ::= CHOICE { + utcTime UTCTime, + generalTime GeneralizedTime +} + +Validity ::= SEQUENCE { + notBefore Time, + notAfter Time +} + +UniqueIdentifier ::= BIT STRING + +SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING +} + +Extension ::= SEQUENCE { + extnID OBJECT IDENTIFIER, + critical BOOLEAN OPTIONAL, -- DEFAULT FALSE XXX + extnValue OCTET STRING +} + +Extensions ::= SEQUENCE OF Extension -- SIZE (1..MAX) + +TBSCertificate ::= SEQUENCE { + version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, + serialNumber CertificateSerialNumber, + signature AlgorithmIdentifier, + issuer Name, + validity Validity, + subject Name, + subjectPublicKeyInfo SubjectPublicKeyInfo, + issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version shall be v2 or v3 + subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version shall be v2 or v3 + extensions [3] EXPLICIT Extensions OPTIONAL + -- If present, version shall be v3 +} + +Certificate ::= SEQUENCE { + tbsCertificate TBSCertificate, + signatureAlgorithm AlgorithmIdentifier, + signatureValue BIT STRING +} + +Certificates ::= SEQUENCE OF Certificate + +ValidationParms ::= SEQUENCE { + seed BIT STRING, + pgenCounter INTEGER +} + +DomainParameters ::= SEQUENCE { + p INTEGER, -- odd prime, p=jq +1 + g INTEGER, -- generator, g + q INTEGER, -- factor of p-1 + j INTEGER OPTIONAL, -- subgroup factor + validationParms ValidationParms OPTIONAL -- ValidationParms +} + +OtherName ::= SEQUENCE { + type-id OBJECT IDENTIFIER, + value [0] EXPLICIT heim_any +} + +GeneralName ::= CHOICE { + otherName [0] OtherName, + rfc822Name [1] IA5String, + dNSName [2] IA5String, +-- x400Address [3] ORAddress,-- + directoryName [4] Name, +-- ediPartyName [5] EDIPartyName, -- + uniformResourceIdentifier [6] IA5String, + iPAddress [7] OCTET STRING, + registeredID [8] OBJECT IDENTIFIER +} + +GeneralNames ::= SEQUENCE -- SIZE (1..MAX) -- OF GeneralName + +id-x509-ce-keyUsage OBJECT IDENTIFIER ::= { id-x509-ce 15 } + +KeyUsage ::= BIT STRING { + digitalSignature (0), + nonRepudiation (1), + keyEncipherment (2), + dataEncipherment (3), + keyAgreement (4), + keyCertSign (5), + cRLSign (6), + encipherOnly (7), + decipherOnly (8) +} + +id-x509-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-x509-ce 35 } + +KeyIdentifier ::= OCTET STRING + +AuthorityKeyIdentifier ::= SEQUENCE { + keyIdentifier [0] IMPLICIT OCTET STRING OPTIONAL, + authorityCertIssuer [1] IMPLICIT heim_any OPTIONAL, + authorityCertSerialNumber [2] IMPLICIT INTEGER OPTIONAL +} + +id-x509-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-x509-ce 14 } + +SubjectKeyIdentifier ::= KeyIdentifier + +id-x509-ce-basicConstraints OBJECT IDENTIFIER ::= { id-x509-ce 19 } + +BasicConstraints ::= SEQUENCE { + cA BOOLEAN OPTIONAL -- DEFAULT FALSE --, + pathLenConstraint INTEGER (0..4294967295) OPTIONAL +} + +id-x509-ce-nameConstraints OBJECT IDENTIFIER ::= { id-x509-ce 30 } + +BaseDistance ::= INTEGER -- (0..MAX) -- + +GeneralSubtree ::= SEQUENCE { + base GeneralName, + minimum [0] BaseDistance OPTIONAL -- DEFAULT 0 --, + maximum [1] BaseDistance OPTIONAL +} + +GeneralSubtrees ::= SEQUENCE -- SIZE (1..MAX) -- OF GeneralSubtree + +NameConstraints ::= SEQUENCE { + permittedSubtrees [0] GeneralSubtrees OPTIONAL, + excludedSubtrees [1] GeneralSubtrees OPTIONAL +} + +id-x509-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::= { id-x509-ce 16 } +id-x509-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-x509-ce 32 } +id-x509-ce-policyMappings OBJECT IDENTIFIER ::= { id-x509-ce 33 } +id-x509-ce-subjectAltName OBJECT IDENTIFIER ::= { id-x509-ce 17 } +id-x509-ce-issuerAltName OBJECT IDENTIFIER ::= { id-x509-ce 18 } +id-x509-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-x509-ce 9 } +id-x509-ce-policyConstraints OBJECT IDENTIFIER ::= { id-x509-ce 36 } +id-x509-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-x509-ce 37} +id-x509-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-x509-ce 31 } +id-x509-ce-cRLNumber OBJECT IDENTIFIER ::= { id-x509-ce 20 } +id-x509-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-x509-ce 27 } +id-x509-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-x509-ce 28 } +id-x509-ce-cRLReasons OBJECT IDENTIFIER ::= { id-x509-ce 21 } +id-x509-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-x509-ce 23 } +id-x509-ce-invalidityDate OBJECT IDENTIFIER ::= { id-x509-ce 24 } +id-x509-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-x509-ce 29 } +id-x509-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-x509-ce 54 } +id-x509-ce-freshestCRL OBJECT IDENTIFIER ::= { id-x509-ce 46 } + +-- rfc3279 + +DSASigValue ::= SEQUENCE { + r INTEGER, + s INTEGER +} + +DSAPublicKey ::= INTEGER + +DSAParams ::= SEQUENCE { + p INTEGER, + q INTEGER, + g INTEGER +} + +-- really pkcs1 + +RSAPublicKey ::= SEQUENCE { + modulus INTEGER, -- n + publicExponent INTEGER -- e +} + +DigestInfo ::= SEQUENCE { + digestAlgorithm AlgorithmIdentifier, + digest OCTET STRING +} + +-- some ms ext + +-- szOID_ENROLL_CERTTYPE_EXTENSION "1.3.6.1.4.1.311.20.2" is Encoded as a + +-- UNICODESTRING (0x1E tag) + +-- szOID_CERTIFICATE_TEMPLATE "1.3.6.1.4.1.311.21.7" is Encoded as: + +-- TemplateVersion ::= INTEGER (0..4294967295) + +-- CertificateTemplate ::= SEQUENCE { +-- templateID OBJECT IDENTIFIER, +-- templateMajorVersion TemplateVersion, +-- templateMinorVersion TemplateVersion OPTIONAL +-- } + +END diff --git a/lib/asn1/setchgpw2.asn1 b/lib/asn1/setchgpw2.asn1 index 7c05b0fa2..66f5287d1 100644 --- a/lib/asn1/setchgpw2.asn1 +++ b/lib/asn1/setchgpw2.asn1 @@ -168,25 +168,25 @@ Request ::= [ APPLICATION 0 ] SEQUENCE { languages[2] SEQUENCE OF Language-Tag OPTIONAL, targ-name[3] PrincipalName OPTIONAL, targ-realm[4] Realm OPTIONAL, --- operation[5] Op-Req, + operation[5] Op-Req, ... } -Responce ::= [ APPLICATION 1 ] SEQUENCE { +Response ::= [ APPLICATION 1 ] SEQUENCE { pvno-major[0] INTEGER DEFAULT 2, pvno-minor[1] INTEGER DEFAULT 0, language[2] Language-Tag DEFAULT "i-default", --- result[3] Op-rep OPTIONAL, + result[3] Op-rep OPTIONAL, ... } -Error-Responce ::= [ APPLICATION 2 ] SEQUENCE { +Error-Response ::= [ APPLICATION 2 ] SEQUENCE { pvno-major[0] INTEGER DEFAULT 2, pvno-minor[1] INTEGER DEFAULT 0, language[2] Language-Tag DEFAULT "i-default", error-code[3] ProtocolErrorCode, help-text[4] UTF8String OPTIONAL, --- op-error[5] Op-error OP-ERROR, + op-error[5] Op-error OP-ERROR, ... } diff --git a/lib/asn1/symbol.c b/lib/asn1/symbol.c index b9be7ad5a..4972e265e 100644 --- a/lib/asn1/symbol.c +++ b/lib/asn1/symbol.c @@ -1,90 +1,110 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include "gen_locl.h" +#include "lex.h" RCSID("$Id$"); static Hashtab *htab; static int -cmp (void *a, void *b) +cmp(void *a, void *b) { - Symbol *s1 = (Symbol *)a; - Symbol *s2 = (Symbol *)b; + Symbol *s1 = (Symbol *) a; + Symbol *s2 = (Symbol *) b; - return strcmp (s1->name, s2->name); + return strcmp(s1->name, s2->name); } static unsigned -hash (void *a) +hash(void *a) { - Symbol *s = (Symbol *)a; + Symbol *s = (Symbol *) a; - return hashjpw (s->name); + return hashjpw(s->name); } void -initsym (void) +initsym(void) { - htab = hashtabnew (101, cmp, hash); + htab = hashtabnew(101, cmp, hash); } void -output_name (char *s) +output_name(char *s) { - char *p; + char *p; - for (p = s; *p; ++p) - if (*p == '-') - *p = '_'; + for (p = s; *p; ++p) + if (*p == '-') + *p = '_'; } -Symbol* -addsym (char *name) +Symbol * +addsym(char *name) { - Symbol key, *s; + Symbol key, *s; - key.name = name; - s = (Symbol *)hashtabsearch (htab, (void *)&key); - if (s == NULL) { - s = (Symbol *)malloc (sizeof (*s)); - s->name = name; - s->gen_name = strdup(name); - output_name (s->gen_name); - s->stype = SUndefined; - hashtabadd (htab, s); - } - return s; + key.name = name; + s = (Symbol *) hashtabsearch(htab, (void *) &key); + if (s == NULL) { + s = (Symbol *) emalloc(sizeof(*s)); + s->name = name; + s->gen_name = estrdup(name); + output_name(s->gen_name); + s->stype = SUndefined; + hashtabadd(htab, s); + } + return s; +} + +static int +checkfunc(void *ptr, void *arg) +{ + Symbol *s = ptr; + if (s->stype == SUndefined) { + error_message("%s is still undefined\n", s->name); + *(int *) arg = 1; + } + return 0; +} + +int +checkundefined(void) +{ + int f = 0; + hashtabforeach(htab, checkfunc, &f); + return f; } diff --git a/lib/asn1/symbol.h b/lib/asn1/symbol.h index 770a64203..ba5ea84ea 100644 --- a/lib/asn1/symbol.h +++ b/lib/asn1/symbol.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -36,59 +36,104 @@ #ifndef _SYMBOL_H #define _SYMBOL_H +#include "asn1_queue.h" + enum typetype { - TApplication, TBitString, TBoolean, - TChoice, + TChoice, TEnumerated, - TGeneralString, - TGeneralizedTime, + TGeneralString, + TGeneralizedTime, + TIA5String, TInteger, TNull, - TOID, - TOctetString, - TSequence, + TOID, + TOctetString, + TPrintableString, + TSequence, TSequenceOf, + TSet, + TSetOf, + TTag, TType, - TUInteger, - TUTF8String + TUTCTime, + TUTF8String, + TBMPString, + TUniversalString }; typedef enum typetype Typetype; struct type; +struct value { + enum { booleanvalue, + nullvalue, + integervalue, + stringvalue, + objectidentifiervalue + } type; + union { + int booleanvalue; + int integervalue; + char *stringvalue; + struct objid *objectidentifiervalue; + } u; +}; + struct member { - char *name; - char *gen_name; - int val; - int optional; - struct type *type; - struct member *next, *prev; - char *defval; + char *name; + char *gen_name; + char *label; + int val; + int optional; + int ellipsis; + struct type *type; + ASN1_TAILQ_ENTRY(member) members; + struct value *defval; }; typedef struct member Member; +ASN1_TAILQ_HEAD(memhead, member); + struct symbol; +struct tagtype { + int tagclass; + int tagvalue; + enum { TE_IMPLICIT, TE_EXPLICIT } tagenv; +}; + +struct range { + int min; + int max; +}; + struct type { - Typetype type; - int application; - Member *members; - struct type *subtype; - struct symbol *symbol; + Typetype type; + struct memhead *members; + struct symbol *symbol; + struct type *subtype; + struct tagtype tag; + struct range *range; }; typedef struct type Type; +struct objid { + const char *label; + int value; + struct objid *next; +}; + struct symbol { - char *name; - char *gen_name; - enum { SUndefined, SConstant, Stype } stype; - int constant; - Type *type; + char *name; + char *gen_name; + enum { SUndefined, SValue, Stype } stype; + struct value *value; + Type *type; }; typedef struct symbol Symbol; @@ -96,4 +141,5 @@ typedef struct symbol Symbol; void initsym (void); Symbol *addsym (char *); void output_name (char *); +int checkundefined(void); #endif diff --git a/lib/asn1/test.asn1 b/lib/asn1/test.asn1 new file mode 100644 index 000000000..5a65e456b --- /dev/null +++ b/lib/asn1/test.asn1 @@ -0,0 +1,30 @@ +-- $Id$ -- + +TEST DEFINITIONS ::= + +BEGIN + +TESTLargeTag ::= SEQUENCE { + foo[127] INTEGER (-2147483648..2147483647) +} + +TESTSeq ::= SEQUENCE { + tag0[0] INTEGER (-2147483648..2147483647), + tag1[1] TESTLargeTag, + tagless INTEGER (-2147483648..2147483647), + tag3[2] INTEGER (-2147483648..2147483647) +} + +TESTChoice1 ::= CHOICE { + i1[1] INTEGER (-2147483648..2147483647), + i2[2] INTEGER (-2147483648..2147483647), + ... +} + +TESTChoice2 ::= CHOICE { + i1[1] INTEGER (-2147483648..2147483647), + ... +} + + +END diff --git a/lib/asn1/test.gen b/lib/asn1/test.gen new file mode 100644 index 000000000..bfb048648 --- /dev/null +++ b/lib/asn1/test.gen @@ -0,0 +1,14 @@ +# $Id$ +# Sample for TESTSeq in test.asn1 +# + +UNIV CONS Sequence 23 + CONTEXT CONS 0 3 + UNIV PRIM Integer 1 01 + CONTEXT CONS 1 8 + UNIV CONS Sequence 6 + CONTEXT CONS 127 3 + UNIV PRIM Integer 1 01 + UNIV PRIM Integer 1 01 + CONTEXT CONS 2 3 + UNIV PRIM Integer 1 01 diff --git a/lib/asn1/x509.asn1 b/lib/asn1/x509.asn1 index 4a15844c8..9535e2067 100644 --- a/lib/asn1/x509.asn1 +++ b/lib/asn1/x509.asn1 @@ -1,23 +1,79 @@ +-- $Id$ -- + X509 DEFINITIONS ::= BEGIN -CertificateSerialNumber ::= INTEGER -- X.509 '97 +IMPORTS heim_any FROM heim; -AttributeType ::= OBJECT-IDENTIFIER +Version ::= INTEGER -- { v1(0), v2(1), v3(2) } -- -AttributeValue ::= OCTET STRING --ANY DEFINED BY AttributeType +AlgorithmIdentifier ::= OBJECT IDENTIFIER -AttributeTypeAndValue ::= SEQUENCE { - type AttributeType, - value AttributeValue +AttributeType ::= OBJECT IDENTIFIER + +AttributeValue ::= heim_any + +Attribute ::= SEQUENCE { + type AttributeType, + value AttributeValue } -RelativeDistinguishedName ::= --SET -SEQUENCE OF AttributeTypeAndValue +RelativeDistinguishedName ::= SET OF Attribute -RDNSequence ::= SEQUENCE OF RelativeDistinguishedName +RDNSequence ::= SEQUENCE OF RelativeDistinguishedName -Name ::= CHOICE { -- RFC2459 - x RDNSequence +DistinguishedName ::= RDNSequence + +Name ::= CHOICE { -- only one possibility for now -- + rdnSequence RDNSequence } -END \ No newline at end of file +CertificateSerialNumber ::= INTEGER + +Time ::= CHOICE { + utcTime UTCTime, + generalTime GeneralizedTime +} + +Validity ::= SEQUENCE { + notBefore Time, + notAfter Time +} + +UniqueIdentifier ::= BIT STRING + +SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING +} + +Extension ::= SEQUENCE { + extnID OBJECT IDENTIFIER, + critical BOOLEAN DEFAULT FALSE, + extnValue OCTET STRING +} + +Extensions ::= SEQUENCE OF Extension -- SIZE (1..MAX) + +TBSCertificate ::= SEQUENCE { + version [0] EXPLICIT Version DEFAULT 1, + serialNumber CertificateSerialNumber, + signature AlgorithmIdentifier, + issuer Name, + validity Validity, + subject Name, + subjectPublicKeyInfo SubjectPublicKeyInfo, + issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version shall be v2 or v3 + subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version shall be v2 or v3 + extensions [3] EXPLICIT Extensions OPTIONAL + -- If present, version shall be v3 +} + +Certificate ::= SEQUENCE { + tbsCertificate TBSCertificate, + signatureAlgorithm AlgorithmIdentifier, + signatureValue BIT STRING +} + +END