diff --git a/crypto/heimdal/lib/asn1/Makefile.am b/crypto/heimdal/lib/asn1/Makefile.am index 47158b88aa42..608639aed276 100644 --- a/crypto/heimdal/lib/asn1/Makefile.am +++ b/crypto/heimdal/lib/asn1/Makefile.am @@ -1,254 +1,262 @@ # $Id$ include $(top_srcdir)/Makefile.am.common YFLAGS = -d -t lib_LTLIBRARIES = libasn1.la libasn1_la_LDFLAGS = -version-info 8:0:0 noinst_LTLIBRARIES = libasn1base.la if versionscript libasn1_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map endif libasn1_la_LIBADD = \ libasn1base.la \ @LIB_com_err@ \ $(LIBADD_roken) BUILT_SOURCES = \ $(gen_files_rfc2459:.x=.c) \ $(gen_files_cms:.x=.c) \ $(gen_files_krb5:.x=.c) \ $(gen_files_pkinit:.x=.c) \ $(gen_files_pkcs8:.x=.c) \ $(gen_files_pkcs9:.x=.c) \ $(gen_files_pkcs12:.x=.c) \ $(gen_files_digest:.x=.c) \ $(gen_files_kx509:.x=.c) gen_files_krb5 = asn1_krb5_asn1.x gen_files_cms = asn1_cms_asn1.x gen_files_rfc2459 = asn1_rfc2459_asn1.x gen_files_pkinit = asn1_pkinit_asn1.x gen_files_pkcs12 = asn1_pkcs12_asn1.x gen_files_pkcs8 = asn1_pkcs8_asn1.x gen_files_pkcs9 = asn1_pkcs9_asn1.x +gen_files_test_template = test_template_asn1-template.c gen_files_test = asn1_test_asn1.x gen_files_digest = asn1_digest_asn1.x gen_files_kx509 = asn1_kx509_asn1.x noinst_PROGRAMS = asn1_gen libexec_heimdal_PROGRAMS = asn1_compile asn1_print TESTS = check-der check-gen check-timegm check-ber check-template check_PROGRAMS = $(TESTS) asn1_gen_SOURCES = asn1_gen.c asn1_print_SOURCES = asn1_print.c check_der_SOURCES = check-der.c check-common.c check-common.h check_template_SOURCES = check-template.c check-common.c check-common.h -nodist_check_template_SOURCES = $(gen_files_test:.x=.c) +nodist_check_template_SOURCES = $(gen_files_test_template:.x=.c) dist_check_gen_SOURCES = check-gen.c check-common.c check-common.h nodist_check_gen_SOURCES = $(gen_files_test:.x=.c) build_HEADERZ = asn1-template.h asn1_compile_SOURCES = \ asn1_queue.h \ asn1parse.y \ der.h \ gen.c \ gen_copy.c \ gen_decode.c \ gen_encode.c \ gen_free.c \ gen_glue.c \ gen_length.c \ gen_locl.h \ gen_seq.c \ gen_template.c \ hash.c \ hash.h \ lex.l \ lex.h \ main.c \ asn1-template.h \ symbol.c \ symbol.h dist_libasn1base_la_SOURCES = \ der_locl.h \ der.c \ der.h \ der_get.c \ der_put.c \ der_free.c \ der_length.c \ der_copy.c \ der_cmp.c \ der_format.c \ heim_asn1.h \ extra.c \ template.c \ timegm.c nodist_libasn1base_la_SOURCES = \ asn1_err.h \ asn1_err.c nodist_libasn1_la_SOURCES = $(BUILT_SOURCES) asn1_compile_LDADD = \ $(LIB_roken) $(LEXLIB) check_der_LDADD = \ libasn1base.la \ $(LIB_roken) check_template_LDADD = $(check_der_LDADD) asn1_print_LDADD = $(check_der_LDADD) $(LIB_com_err) asn1_gen_LDADD = $(check_der_LDADD) check_timegm_LDADD = $(check_der_LDADD) check_gen_LDADD = \ libasn1.la \ $(LIB_roken) check_ber_LDADD = $(check_gen_LDADD) CLEANFILES = \ $(BUILT_SOURCES) \ $(gen_files_rfc2459) \ $(gen_files_cms) \ $(gen_files_krb5) \ $(gen_files_pkinit) \ $(gen_files_pkcs8) \ $(gen_files_pkcs9) \ $(gen_files_pkcs12) \ $(gen_files_digest) \ $(gen_files_kx509) \ + $(gen_files_test_template) \ $(gen_files_test) $(nodist_check_gen_SOURCES) \ asn1_err.c asn1_err.h \ 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* \ digest_asn1_files digest_asn1*.h* \ kx509_asn1_files kx509_asn1*.h* \ + test_template_asn1_files test_template_asn1*.h* \ test_asn1_files test_asn1*.h* dist_include_HEADERS = der.h heim_asn1.h der-protos.h der-private.h dist_include_HEADERS += asn1-common.h nodist_include_HEADERS = asn1_err.h nodist_include_HEADERS += krb5_asn1.h nodist_include_HEADERS += pkinit_asn1.h nodist_include_HEADERS += cms_asn1.h nodist_include_HEADERS += rfc2459_asn1.h nodist_include_HEADERS += pkcs8_asn1.h nodist_include_HEADERS += pkcs9_asn1.h nodist_include_HEADERS += pkcs12_asn1.h nodist_include_HEADERS += digest_asn1.h nodist_include_HEADERS += kx509_asn1.h priv_headers = krb5_asn1-priv.h priv_headers += pkinit_asn1-priv.h priv_headers += cms_asn1-priv.h priv_headers += rfc2459_asn1-priv.h priv_headers += pkcs8_asn1-priv.h priv_headers += pkcs9_asn1-priv.h priv_headers += pkcs12_asn1-priv.h priv_headers += digest_asn1-priv.h priv_headers += kx509_asn1-priv.h +priv_headers += test_template_asn1.h test_template_asn1-priv.h priv_headers += test_asn1.h test_asn1-priv.h $(asn1_compile_OBJECTS): asn1parse.h asn1parse.c $(srcdir)/der-protos.h $(srcdir)/der-private.h $(libasn1_la_OBJECTS): $(nodist_include_HEADERS) $(priv_headers) asn1_err.h $(srcdir)/der-protos.h $(srcdir)/der-private.h $(libasn1base_la_OBJECTS): asn1_err.h $(srcdir)/der-protos.h $(srcdir)/der-private.h $(check_gen_OBJECTS): test_asn1.h -$(check_template_OBJECTS): test_asn1_files +$(check_template_OBJECTS): test_template_asn1.h test_template_asn1_files $(asn1_print_OBJECTS): krb5_asn1.h asn1parse.h: asn1parse.c $(gen_files_krb5) krb5_asn1.hx krb5_asn1-priv.hx: krb5_asn1_files $(gen_files_pkinit) pkinit_asn1.hx pkinit_asn1-priv.hx: pkinit_asn1_files $(gen_files_pkcs8) pkcs8_asn1.hx pkcs8_asn1-priv.hx: pkcs8_asn1_files $(gen_files_pkcs9) pkcs9_asn1.hx pkcs9_asn1-priv.hx: pkcs9_asn1_files $(gen_files_pkcs12) pkcs12_asn1.hx pkcs12_asn1-priv.hx: pkcs12_asn1_files $(gen_files_digest) digest_asn1.hx digest_asn1-priv.hx: digest_asn1_files $(gen_files_kx509) kx509_asn1.hx kx509_asn1-priv.hx: kx509_asn1_files $(gen_files_rfc2459) rfc2459_asn1.hx rfc2459_asn1-priv.hx: rfc2459_asn1_files $(gen_files_cms) cms_asn1.hx cms_asn1-priv.hx: cms_asn1_files +$(gen_files_test_template) test_template_asn1.hx test_template_asn1-priv.hx: test_template_asn1_files $(gen_files_test) test_asn1.hx test_asn1-priv.hx: test_asn1_files rfc2459_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc2459.asn1 $(ASN1_COMPILE) --one-code-file --preserve-binary=TBSCertificate --preserve-binary=TBSCRLCertList --preserve-binary=Name --sequence=GeneralNames --sequence=Extensions --sequence=CRLDistributionPoints $(srcdir)/rfc2459.asn1 rfc2459_asn1 || (rm -f rfc2459_asn1_files ; exit 1) cms_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/cms.asn1 $(srcdir)/cms.opt $(ASN1_COMPILE) --one-code-file --option-file=$(srcdir)/cms.opt $(srcdir)/cms.asn1 cms_asn1 || (rm -f cms_asn1_files ; exit 1) krb5_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/krb5.asn1 $(srcdir)/krb5.opt $(ASN1_COMPILE) --one-code-file --option-file=$(srcdir)/krb5.opt $(srcdir)/krb5.asn1 krb5_asn1 || (rm -f krb5_asn1_files ; exit 1) pkinit_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1 $(ASN1_COMPILE) --one-code-file $(srcdir)/pkinit.asn1 pkinit_asn1 || (rm -f pkinit_asn1_files ; exit 1) pkcs8_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs8.asn1 $(ASN1_COMPILE) --one-code-file $(srcdir)/pkcs8.asn1 pkcs8_asn1 || (rm -f pkcs8_asn1_files ; exit 1) pkcs9_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs9.asn1 $(ASN1_COMPILE) --one-code-file $(srcdir)/pkcs9.asn1 pkcs9_asn1 || (rm -f pkcs9_asn1_files ; exit 1) pkcs12_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs12.asn1 $(ASN1_COMPILE) --one-code-file $(srcdir)/pkcs12.asn1 pkcs12_asn1 || (rm -f pkcs12_asn1_files ; exit 1) digest_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/digest.asn1 $(ASN1_COMPILE) --one-code-file $(srcdir)/digest.asn1 digest_asn1 || (rm -f digest_asn1_files ; exit 1) kx509_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/kx509.asn1 $(ASN1_COMPILE) --one-code-file $(srcdir)/kx509.asn1 kx509_asn1 || (rm -f kx509_asn1_files ; exit 1) +test_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1 + $(ASN1_COMPILE) --template --sequence=TESTSeqOf $(srcdir)/test.asn1 test_template_asn1 || (rm -f test_template_asn1_files ; exit 1) + test_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1 $(ASN1_COMPILE) --one-code-file --sequence=TESTSeqOf $(srcdir)/test.asn1 test_asn1 || (rm -f test_asn1_files ; exit 1) EXTRA_DIST = \ NTMakefile \ asn1_compile-version.rc \ libasn1-exports.def \ cms.asn1 \ cms.opt \ asn1_err.et \ canthandle.asn1 \ digest.asn1 \ krb5.asn1 \ krb5.opt \ kx509.asn1 \ pkcs12.asn1 \ pkcs8.asn1 \ pkcs9.asn1 \ pkinit.asn1 \ rfc2459.asn1 \ setchgpw2.asn1 \ test.asn1 \ test.gen \ version-script.map $(srcdir)/der-protos.h: cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -o der-protos.h $(dist_libasn1base_la_SOURCES) || rm -f der-protos.h $(srcdir)/der-private.h: cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p der-private.h $(dist_libasn1base_la_SOURCES) || rm -f der-private.h diff --git a/crypto/heimdal/lib/asn1/asn1-template.h b/crypto/heimdal/lib/asn1/asn1-template.h index 107706ce8340..5fd6b812630f 100644 --- a/crypto/heimdal/lib/asn1/asn1-template.h +++ b/crypto/heimdal/lib/asn1/asn1-template.h @@ -1,141 +1,143 @@ /* * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Portions Copyright (c) 2009 Apple Inc. 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. */ /* asn1 templates */ #ifndef __TEMPLATE_H__ #define __TEMPLATE_H__ /* tag: * 0..20 tag * 21 type * 22..23 class * 24..27 flags * 28..31 op */ /* parse: * 0..11 type * 12..23 unused * 24..27 flags * 28..31 op */ #define A1_OP_MASK (0xf0000000) #define A1_OP_TYPE (0x10000000) #define A1_OP_TYPE_EXTERN (0x20000000) #define A1_OP_TAG (0x30000000) #define A1_OP_PARSE (0x40000000) #define A1_OP_SEQOF (0x50000000) #define A1_OP_SETOF (0x60000000) #define A1_OP_BMEMBER (0x70000000) #define A1_OP_CHOICE (0x80000000) #define A1_FLAG_MASK (0x0f000000) #define A1_FLAG_OPTIONAL (0x01000000) #define A1_FLAG_IMPLICIT (0x02000000) #define A1_TAG_T(CLASS,TYPE,TAG) ((A1_OP_TAG) | (((CLASS) << 22) | ((TYPE) << 21) | (TAG))) #define A1_TAG_CLASS(x) (((x) >> 22) & 0x3) #define A1_TAG_TYPE(x) (((x) >> 21) & 0x1) #define A1_TAG_TAG(x) ((x) & 0x1fffff) #define A1_TAG_LEN(t) ((uintptr_t)(t)->ptr) #define A1_HEADER_LEN(t) ((uintptr_t)(t)->ptr) #define A1_PARSE_T(type) ((A1_OP_PARSE) | (type)) #define A1_PARSE_TYPE_MASK 0xfff #define A1_PARSE_TYPE(x) (A1_PARSE_TYPE_MASK & (x)) #define A1_PF_INDEFINTE 0x1 #define A1_PF_ALLOW_BER 0x2 #define A1_HF_PRESERVE 0x1 #define A1_HF_ELLIPSIS 0x2 #define A1_HBF_RFC1510 0x1 struct asn1_template { uint32_t tt; size_t offset; const void *ptr; }; typedef int (*asn1_type_decode)(const unsigned char *, size_t, void *, size_t *); typedef int (*asn1_type_encode)(unsigned char *, size_t, const void *, size_t *); typedef size_t (*asn1_type_length)(const void *); typedef void (*asn1_type_release)(void *); typedef int (*asn1_type_copy)(const void *, void *); struct asn1_type_func { asn1_type_encode encode; asn1_type_decode decode; asn1_type_length length; asn1_type_copy copy; asn1_type_release release; size_t size; }; struct template_of { unsigned int len; void *val; }; enum template_types { A1T_IMEMBER = 0, A1T_HEIM_INTEGER, A1T_INTEGER, + A1T_INTEGER64, A1T_UNSIGNED, + A1T_UNSIGNED64, A1T_GENERAL_STRING, A1T_OCTET_STRING, A1T_OCTET_STRING_BER, A1T_IA5_STRING, A1T_BMP_STRING, A1T_UNIVERSAL_STRING, A1T_PRINTABLE_STRING, A1T_VISIBLE_STRING, A1T_UTF8_STRING, A1T_GENERALIZED_TIME, A1T_UTC_TIME, A1T_HEIM_BIT_STRING, A1T_BOOLEAN, A1T_OID, A1T_TELETEX_STRING, A1T_NULL }; #endif diff --git a/crypto/heimdal/lib/asn1/asn1parse.c b/crypto/heimdal/lib/asn1/asn1parse.c index 0e04fabf6296..a305f4b0267b 100644 --- a/crypto/heimdal/lib/asn1/asn1parse.c +++ b/crypto/heimdal/lib/asn1/asn1parse.c @@ -1,2861 +1,2861 @@ /* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Using locations. */ #define YYLSP_NEEDED 0 /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { kw_ABSENT = 258, kw_ABSTRACT_SYNTAX = 259, kw_ALL = 260, kw_APPLICATION = 261, kw_AUTOMATIC = 262, kw_BEGIN = 263, kw_BIT = 264, kw_BMPString = 265, kw_BOOLEAN = 266, kw_BY = 267, kw_CHARACTER = 268, kw_CHOICE = 269, kw_CLASS = 270, kw_COMPONENT = 271, kw_COMPONENTS = 272, kw_CONSTRAINED = 273, kw_CONTAINING = 274, kw_DEFAULT = 275, kw_DEFINITIONS = 276, kw_EMBEDDED = 277, kw_ENCODED = 278, kw_END = 279, kw_ENUMERATED = 280, kw_EXCEPT = 281, kw_EXPLICIT = 282, kw_EXPORTS = 283, kw_EXTENSIBILITY = 284, kw_EXTERNAL = 285, kw_FALSE = 286, kw_FROM = 287, kw_GeneralString = 288, kw_GeneralizedTime = 289, kw_GraphicString = 290, kw_IA5String = 291, kw_IDENTIFIER = 292, kw_IMPLICIT = 293, kw_IMPLIED = 294, kw_IMPORTS = 295, kw_INCLUDES = 296, kw_INSTANCE = 297, kw_INTEGER = 298, kw_INTERSECTION = 299, kw_ISO646String = 300, kw_MAX = 301, kw_MIN = 302, kw_MINUS_INFINITY = 303, kw_NULL = 304, kw_NumericString = 305, kw_OBJECT = 306, kw_OCTET = 307, kw_OF = 308, kw_OPTIONAL = 309, kw_ObjectDescriptor = 310, kw_PATTERN = 311, kw_PDV = 312, kw_PLUS_INFINITY = 313, kw_PRESENT = 314, kw_PRIVATE = 315, kw_PrintableString = 316, kw_REAL = 317, kw_RELATIVE_OID = 318, kw_SEQUENCE = 319, kw_SET = 320, kw_SIZE = 321, kw_STRING = 322, kw_SYNTAX = 323, kw_T61String = 324, kw_TAGS = 325, kw_TRUE = 326, kw_TYPE_IDENTIFIER = 327, kw_TeletexString = 328, kw_UNION = 329, kw_UNIQUE = 330, kw_UNIVERSAL = 331, kw_UTCTime = 332, kw_UTF8String = 333, kw_UniversalString = 334, kw_VideotexString = 335, kw_VisibleString = 336, kw_WITH = 337, RANGE = 338, EEQUAL = 339, ELLIPSIS = 340, IDENTIFIER = 341, referencename = 342, STRING = 343, NUMBER = 344 }; #endif /* Tokens. */ #define kw_ABSENT 258 #define kw_ABSTRACT_SYNTAX 259 #define kw_ALL 260 #define kw_APPLICATION 261 #define kw_AUTOMATIC 262 #define kw_BEGIN 263 #define kw_BIT 264 #define kw_BMPString 265 #define kw_BOOLEAN 266 #define kw_BY 267 #define kw_CHARACTER 268 #define kw_CHOICE 269 #define kw_CLASS 270 #define kw_COMPONENT 271 #define kw_COMPONENTS 272 #define kw_CONSTRAINED 273 #define kw_CONTAINING 274 #define kw_DEFAULT 275 #define kw_DEFINITIONS 276 #define kw_EMBEDDED 277 #define kw_ENCODED 278 #define kw_END 279 #define kw_ENUMERATED 280 #define kw_EXCEPT 281 #define kw_EXPLICIT 282 #define kw_EXPORTS 283 #define kw_EXTENSIBILITY 284 #define kw_EXTERNAL 285 #define kw_FALSE 286 #define kw_FROM 287 #define kw_GeneralString 288 #define kw_GeneralizedTime 289 #define kw_GraphicString 290 #define kw_IA5String 291 #define kw_IDENTIFIER 292 #define kw_IMPLICIT 293 #define kw_IMPLIED 294 #define kw_IMPORTS 295 #define kw_INCLUDES 296 #define kw_INSTANCE 297 #define kw_INTEGER 298 #define kw_INTERSECTION 299 #define kw_ISO646String 300 #define kw_MAX 301 #define kw_MIN 302 #define kw_MINUS_INFINITY 303 #define kw_NULL 304 #define kw_NumericString 305 #define kw_OBJECT 306 #define kw_OCTET 307 #define kw_OF 308 #define kw_OPTIONAL 309 #define kw_ObjectDescriptor 310 #define kw_PATTERN 311 #define kw_PDV 312 #define kw_PLUS_INFINITY 313 #define kw_PRESENT 314 #define kw_PRIVATE 315 #define kw_PrintableString 316 #define kw_REAL 317 #define kw_RELATIVE_OID 318 #define kw_SEQUENCE 319 #define kw_SET 320 #define kw_SIZE 321 #define kw_STRING 322 #define kw_SYNTAX 323 #define kw_T61String 324 #define kw_TAGS 325 #define kw_TRUE 326 #define kw_TYPE_IDENTIFIER 327 #define kw_TeletexString 328 #define kw_UNION 329 #define kw_UNIQUE 330 #define kw_UNIVERSAL 331 #define kw_UTCTime 332 #define kw_UTF8String 333 #define kw_UniversalString 334 #define kw_VideotexString 335 #define kw_VisibleString 336 #define kw_WITH 337 #define RANGE 338 #define EEQUAL 339 #define ELLIPSIS 340 #define IDENTIFIER 341 #define referencename 342 #define STRING 343 #define NUMBER 344 /* Copy the first part of user declarations. */ #line 38 "asn1parse.y" #include #include #include #include #include "symbol.h" #include "lex.h" #include "gen_locl.h" #include "der.h" RCSID("$Id$"); static Type *new_type (Typetype t); static struct constraint_spec *new_constraint_spec(enum ctype); static Type *new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype); void yyerror (const 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); struct string_list { char *string; struct string_list *next; }; /* Declarations for Bison */ #define YYMALLOC malloc #define YYFREE free /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 1 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE #line 71 "asn1parse.y" { - int constant; + int64_t 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; struct constraint_spec *constraint_spec; } /* Line 193 of yacc.c. */ #line 322 "asn1parse.c" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ /* Line 216 of yacc.c. */ #line 335 "asn1parse.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int i) #else static int YYID (i) int i; #endif { return i; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss; YYSTYPE yyvs; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 6 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 203 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 98 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 69 /* YYNRULES -- Number of rules. */ #define YYNRULES 140 /* YYNRULES -- Number of states. */ #define YYNSTATES 220 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 344 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 92, 93, 2, 2, 91, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 96, 2, 97, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 94, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint16 yyprhs[] = { 0, 0, 3, 13, 16, 19, 22, 23, 26, 27, 31, 32, 36, 37, 39, 40, 42, 45, 50, 54, 57, 58, 60, 63, 65, 67, 71, 73, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 119, 125, 131, 135, 137, 140, 145, 147, 151, 155, 160, 165, 167, 170, 176, 179, 183, 185, 186, 189, 194, 198, 203, 208, 212, 216, 221, 223, 225, 227, 229, 231, 234, 238, 240, 242, 244, 247, 251, 257, 262, 266, 271, 272, 274, 276, 278, 279, 281, 283, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 312, 316, 319, 321, 324, 328, 330, 334, 339, 341, 342, 346, 347, 350, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381, 383, 385, 387, 389, 391 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { 99, 0, -1, 86, 152, 21, 100, 101, 84, 8, 102, 24, -1, 27, 70, -1, 38, 70, -1, 7, 70, -1, -1, 29, 39, -1, -1, 107, 103, 108, -1, -1, 40, 104, 90, -1, -1, 105, -1, -1, 106, -1, 105, 106, -1, 110, 32, 86, 152, -1, 28, 110, 90, -1, 28, 5, -1, -1, 109, -1, 109, 108, -1, 111, -1, 144, -1, 86, 91, 110, -1, 86, -1, 86, 84, 112, -1, 113, -1, 131, -1, 134, -1, 121, -1, 114, -1, 145, -1, 130, -1, 119, -1, 116, -1, 124, -1, 122, -1, 123, -1, 126, -1, 127, -1, 128, -1, 129, -1, 140, -1, 11, -1, 92, 156, 83, 156, 93, -1, 92, 156, 83, 46, 93, -1, 92, 47, 83, 156, 93, -1, 92, 156, 93, -1, 43, -1, 43, 115, -1, 43, 94, 117, 95, -1, 118, -1, 117, 91, 118, -1, 117, 91, 85, -1, 86, 92, 164, 93, -1, 25, 94, 120, 95, -1, 117, -1, 9, 67, -1, 9, 67, 94, 150, 95, -1, 51, 37, -1, 52, 67, 125, -1, 49, -1, -1, 66, 115, -1, 64, 94, 147, 95, -1, 64, 94, 95, -1, 64, 125, 53, 112, -1, 65, 94, 147, 95, -1, 65, 94, 95, -1, 65, 53, 112, -1, 14, 94, 147, 95, -1, 132, -1, 133, -1, 86, -1, 34, -1, 77, -1, 112, 135, -1, 92, 136, 93, -1, 137, -1, 138, -1, 139, -1, 19, 112, -1, 23, 12, 156, -1, 19, 112, 23, 12, 156, -1, 18, 12, 94, 95, -1, 141, 143, 112, -1, 96, 142, 89, 97, -1, -1, 76, -1, 6, -1, 60, -1, -1, 27, -1, 38, -1, 86, 112, 84, 156, -1, 146, -1, 33, -1, 73, -1, 78, -1, 61, -1, 81, -1, 36, -1, 10, -1, 79, -1, 149, -1, 147, 91, 149, -1, 147, 91, 85, -1, 86, 112, -1, 148, -1, 148, 54, -1, 148, 20, 156, -1, 151, -1, 150, 91, 151, -1, 86, 92, 89, 93, -1, 153, -1, -1, 94, 154, 95, -1, -1, 155, 154, -1, 86, 92, 89, 93, -1, 86, -1, 89, -1, 157, -1, 158, -1, 162, -1, 161, -1, 163, -1, 166, -1, 165, -1, 159, -1, 160, -1, 86, -1, 88, -1, 71, -1, 31, -1, 164, -1, 89, -1, 49, -1, 153, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 239, 239, 246, 247, 249, 251, 254, 256, 259, 260, 263, 264, 267, 268, 271, 272, 275, 287, 293, 294, 297, 298, 301, 302, 305, 311, 319, 329, 330, 331, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 350, 357, 367, 375, 383, 394, 399, 405, 413, 419, 424, 428, 441, 449, 452, 459, 467, 473, 482, 490, 491, 496, 502, 510, 519, 525, 533, 541, 548, 549, 552, 563, 568, 575, 591, 597, 600, 601, 604, 610, 618, 628, 634, 647, 656, 659, 663, 667, 674, 677, 681, 688, 699, 702, 707, 712, 717, 722, 727, 732, 737, 745, 751, 756, 767, 778, 784, 790, 798, 804, 811, 824, 825, 828, 835, 838, 849, 853, 864, 870, 871, 874, 875, 876, 877, 878, 881, 884, 887, 898, 906, 912, 920, 928, 931, 936 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "kw_ABSENT", "kw_ABSTRACT_SYNTAX", "kw_ALL", "kw_APPLICATION", "kw_AUTOMATIC", "kw_BEGIN", "kw_BIT", "kw_BMPString", "kw_BOOLEAN", "kw_BY", "kw_CHARACTER", "kw_CHOICE", "kw_CLASS", "kw_COMPONENT", "kw_COMPONENTS", "kw_CONSTRAINED", "kw_CONTAINING", "kw_DEFAULT", "kw_DEFINITIONS", "kw_EMBEDDED", "kw_ENCODED", "kw_END", "kw_ENUMERATED", "kw_EXCEPT", "kw_EXPLICIT", "kw_EXPORTS", "kw_EXTENSIBILITY", "kw_EXTERNAL", "kw_FALSE", "kw_FROM", "kw_GeneralString", "kw_GeneralizedTime", "kw_GraphicString", "kw_IA5String", "kw_IDENTIFIER", "kw_IMPLICIT", "kw_IMPLIED", "kw_IMPORTS", "kw_INCLUDES", "kw_INSTANCE", "kw_INTEGER", "kw_INTERSECTION", "kw_ISO646String", "kw_MAX", "kw_MIN", "kw_MINUS_INFINITY", "kw_NULL", "kw_NumericString", "kw_OBJECT", "kw_OCTET", "kw_OF", "kw_OPTIONAL", "kw_ObjectDescriptor", "kw_PATTERN", "kw_PDV", "kw_PLUS_INFINITY", "kw_PRESENT", "kw_PRIVATE", "kw_PrintableString", "kw_REAL", "kw_RELATIVE_OID", "kw_SEQUENCE", "kw_SET", "kw_SIZE", "kw_STRING", "kw_SYNTAX", "kw_T61String", "kw_TAGS", "kw_TRUE", "kw_TYPE_IDENTIFIER", "kw_TeletexString", "kw_UNION", "kw_UNIQUE", "kw_UNIVERSAL", "kw_UTCTime", "kw_UTF8String", "kw_UniversalString", "kw_VideotexString", "kw_VisibleString", "kw_WITH", "RANGE", "EEQUAL", "ELLIPSIS", "IDENTIFIER", "referencename", "STRING", "NUMBER", "';'", "','", "'('", "')'", "'{'", "'}'", "'['", "']'", "$accept", "ModuleDefinition", "TagDefault", "ExtensionDefault", "ModuleBody", "Imports", "SymbolsImported", "SymbolsFromModuleList", "SymbolsFromModule", "Exports", "AssignmentList", "Assignment", "referencenames", "TypeAssignment", "Type", "BuiltinType", "BooleanType", "range", "IntegerType", "NamedNumberList", "NamedNumber", "EnumeratedType", "Enumerations", "BitStringType", "ObjectIdentifierType", "OctetStringType", "NullType", "size", "SequenceType", "SequenceOfType", "SetType", "SetOfType", "ChoiceType", "ReferencedType", "DefinedType", "UsefulType", "ConstrainedType", "Constraint", "ConstraintSpec", "GeneralConstraint", "ContentsConstraint", "UserDefinedConstraint", "TaggedType", "Tag", "Class", "tagenv", "ValueAssignment", "CharacterStringType", "RestrictedCharactedStringType", "ComponentTypeList", "NamedType", "ComponentType", "NamedBitList", "NamedBit", "objid_opt", "objid", "objid_list", "objid_element", "Value", "BuiltinValue", "ReferencedValue", "DefinedValue", "Valuereference", "CharacterStringValue", "BooleanValue", "IntegerValue", "SignedNumber", "NullValue", "ObjectIdentifierValue", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 59, 44, 40, 41, 123, 125, 91, 93 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 98, 99, 100, 100, 100, 100, 101, 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 107, 107, 107, 108, 108, 109, 109, 110, 110, 111, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 114, 115, 115, 115, 115, 116, 116, 116, 117, 117, 117, 118, 119, 120, 121, 121, 122, 123, 124, 125, 125, 126, 126, 127, 128, 128, 129, 130, 131, 131, 132, 133, 133, 134, 135, 136, 137, 137, 138, 138, 138, 139, 140, 141, 142, 142, 142, 142, 143, 143, 143, 144, 145, 146, 146, 146, 146, 146, 146, 146, 146, 147, 147, 147, 148, 149, 149, 149, 150, 150, 151, 152, 152, 153, 154, 154, 155, 155, 155, 156, 156, 157, 157, 157, 157, 157, 158, 159, 160, 161, 162, 162, 163, 164, 165, 166 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 9, 2, 2, 2, 0, 2, 0, 3, 0, 3, 0, 1, 0, 1, 2, 4, 3, 2, 0, 1, 2, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 3, 1, 2, 4, 1, 3, 3, 4, 4, 1, 2, 5, 2, 3, 1, 0, 2, 4, 3, 4, 4, 3, 3, 4, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 2, 3, 5, 4, 3, 4, 0, 1, 1, 1, 0, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 2, 1, 2, 3, 1, 3, 4, 1, 0, 3, 0, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 0, 117, 0, 119, 0, 116, 1, 122, 123, 0, 119, 6, 0, 118, 120, 0, 0, 0, 8, 0, 5, 3, 4, 0, 0, 121, 7, 0, 20, 0, 0, 12, 19, 26, 0, 2, 14, 0, 0, 18, 0, 13, 15, 0, 0, 9, 21, 23, 24, 25, 11, 16, 0, 0, 104, 45, 0, 0, 98, 76, 103, 50, 63, 0, 0, 101, 64, 0, 99, 77, 100, 105, 102, 0, 75, 89, 0, 28, 32, 36, 35, 31, 38, 39, 37, 40, 41, 42, 43, 34, 29, 73, 74, 30, 44, 93, 33, 97, 22, 117, 59, 0, 0, 0, 0, 51, 61, 64, 0, 0, 0, 0, 0, 27, 91, 92, 90, 0, 0, 0, 78, 94, 95, 0, 17, 0, 0, 0, 110, 106, 0, 58, 53, 0, 136, 0, 139, 135, 133, 134, 138, 140, 0, 124, 125, 131, 132, 127, 126, 128, 137, 130, 129, 0, 62, 65, 67, 0, 0, 71, 70, 0, 0, 96, 0, 0, 0, 0, 80, 81, 82, 87, 0, 0, 113, 109, 0, 72, 0, 111, 0, 0, 57, 0, 0, 49, 52, 66, 68, 69, 88, 0, 83, 0, 79, 0, 0, 60, 108, 107, 112, 0, 55, 54, 0, 0, 0, 0, 0, 84, 0, 114, 56, 48, 47, 46, 86, 0, 115, 85 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 2, 18, 24, 30, 37, 40, 41, 42, 31, 45, 46, 43, 47, 76, 77, 78, 105, 79, 131, 132, 80, 133, 81, 82, 83, 84, 110, 85, 86, 87, 88, 89, 90, 91, 92, 93, 120, 167, 168, 169, 170, 94, 95, 117, 123, 48, 96, 97, 127, 128, 129, 173, 174, 4, 141, 9, 10, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -119 static const yytype_int16 yypact[] = { -43, -56, 47, -65, 29, -119, -119, -31, -119, -25, -65, 4, -1, -119, -119, 17, 20, 26, 50, 13, -119, -119, -119, 63, 24, -119, -119, 104, 8, -2, 89, 74, -119, 33, 25, -119, 34, 39, 34, -119, 37, 34, -119, 98, 58, -119, 39, -119, -119, -119, -119, -119, 52, 66, -119, -119, 51, 53, -119, -119, -119, -79, -119, 109, 81, -119, -60, -48, -119, -119, -119, -119, -119, 107, -119, 2, -74, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -18, -119, -119, -119, -56, 55, 65, 67, -12, 67, -119, -119, 86, 68, -70, 102, 107, -69, 69, -119, -119, -119, 73, 40, 10, -119, -119, -119, 107, -119, 71, 107, -47, -13, -119, 72, 75, -119, 70, -119, 80, -119, -119, -119, -119, -119, -119, -71, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -46, -119, -119, -119, -39, 107, 69, -119, -38, 76, -119, 155, 107, 157, 77, -119, -119, -119, 69, 82, -10, -119, 69, -22, -119, 40, -119, 87, 19, -119, 40, 9, -119, -119, -119, 69, -119, -119, 83, -19, 40, -119, 90, 71, -119, -119, -119, -119, 85, -119, -119, 88, 94, 96, 95, 163, -119, 99, -119, -119, -119, -119, -119, -119, 40, -119, -119 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { -119, -119, -119, -119, -119, -119, -119, -119, 141, -119, 137, -119, -15, -119, -72, -119, -119, 91, -119, 92, 14, -119, -119, -119, -119, -119, -119, 84, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -119, -82, -119, 18, -119, 5, 101, 1, 187, -119, -118, -119, -119, -119, -119, -119, -119, -119, 22, -119, -119 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -11 static const yytype_int16 yytable[] = { 163, 113, 5, 32, 208, 111, 108, 178, 114, 121, 118, 15, 184, 103, 34, 104, 126, 126, 119, 134, 122, 7, 185, 49, 8, 156, 160, 157, 164, 165, 161, 16, -10, 166, 109, 135, 29, 136, 3, 159, 134, 179, 17, 1, 176, 181, 112, 6, 177, 186, 11, 171, 176, 176, 175, 205, 187, 189, 136, 137, 200, 12, 115, 198, 126, 204, 206, 53, 54, 55, 13, 134, 56, 119, 138, 209, 139, 140, 116, 23, 137, 196, 3, 57, 33, 197, 188, 20, 19, 136, 21, 58, 59, 192, 60, 138, 22, 139, 140, 219, 5, 61, 26, 3, 202, 130, 25, 62, 27, 63, 64, 137, 28, 35, 36, 39, 53, 54, 55, 65, 33, 56, 66, 67, 38, 44, 138, 50, 139, 140, 52, 68, 57, 100, 3, 69, 70, 71, 99, 72, 58, 59, 73, 60, 74, 101, 106, 102, 107, 125, 61, 126, 108, 130, 75, 158, 62, 172, 63, 64, 103, 119, 162, 183, 180, 182, 181, 191, 65, 193, 194, 66, 67, 190, 195, 217, 140, 207, 212, 210, 68, 213, 51, 98, 69, 70, 71, 214, 72, 215, 216, 154, 218, 74, 199, 203, 153, 14, 0, 155, 124, 211, 201, 75 }; static const yytype_int16 yycheck[] = { 118, 73, 1, 5, 23, 53, 66, 20, 6, 27, 84, 7, 83, 92, 29, 94, 86, 86, 92, 31, 38, 86, 93, 38, 89, 95, 95, 109, 18, 19, 112, 27, 24, 23, 94, 47, 28, 49, 94, 111, 31, 54, 38, 86, 91, 91, 94, 0, 95, 95, 21, 123, 91, 91, 126, 46, 95, 95, 49, 71, 178, 92, 60, 85, 86, 183, 184, 9, 10, 11, 95, 31, 14, 92, 86, 193, 88, 89, 76, 29, 71, 91, 94, 25, 86, 95, 158, 70, 89, 49, 70, 33, 34, 165, 36, 86, 70, 88, 89, 217, 99, 43, 39, 94, 85, 86, 93, 49, 84, 51, 52, 71, 8, 24, 40, 90, 9, 10, 11, 61, 86, 14, 64, 65, 91, 86, 86, 90, 88, 89, 32, 73, 25, 67, 94, 77, 78, 79, 86, 81, 33, 34, 84, 36, 86, 94, 37, 94, 67, 94, 43, 86, 66, 86, 96, 53, 49, 86, 51, 52, 92, 92, 89, 83, 92, 95, 91, 12, 61, 12, 93, 64, 65, 97, 92, 12, 89, 94, 93, 89, 73, 93, 41, 46, 77, 78, 79, 93, 81, 93, 95, 107, 93, 86, 176, 181, 104, 10, -1, 108, 99, 196, 180, 96 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 86, 99, 94, 152, 153, 0, 86, 89, 154, 155, 21, 92, 95, 154, 7, 27, 38, 100, 89, 70, 70, 70, 29, 101, 93, 39, 84, 8, 28, 102, 107, 5, 86, 110, 24, 40, 103, 91, 90, 104, 105, 106, 110, 86, 108, 109, 111, 144, 110, 90, 106, 32, 9, 10, 11, 14, 25, 33, 34, 36, 43, 49, 51, 52, 61, 64, 65, 73, 77, 78, 79, 81, 84, 86, 96, 112, 113, 114, 116, 119, 121, 122, 123, 124, 126, 127, 128, 129, 130, 131, 132, 133, 134, 140, 141, 145, 146, 108, 86, 67, 94, 94, 92, 94, 115, 37, 67, 66, 94, 125, 53, 94, 112, 6, 60, 76, 142, 84, 92, 135, 27, 38, 143, 152, 94, 86, 147, 148, 149, 86, 117, 118, 120, 31, 47, 49, 71, 86, 88, 89, 153, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 117, 125, 115, 95, 147, 53, 112, 95, 147, 89, 156, 18, 19, 23, 136, 137, 138, 139, 112, 86, 150, 151, 112, 91, 95, 20, 54, 92, 91, 95, 83, 83, 93, 95, 95, 112, 95, 97, 12, 112, 12, 93, 92, 91, 95, 85, 149, 156, 164, 85, 118, 156, 46, 156, 94, 23, 156, 89, 151, 93, 93, 93, 93, 95, 12, 93, 156 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void yy_stack_print (bottom, top) yytype_int16 *bottom; yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); for (; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { fprintf (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); fprintf (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The look-ahead symbol. */ int yychar; /* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { int yystate; int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss = yyssa; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; YYSTYPE *yyvsp; #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a look-ahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a look-ahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } if (yyn == YYFINAL) YYACCEPT; /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: #line 241 "asn1parse.y" { checkundefined(); } break; case 4: #line 248 "asn1parse.y" { lex_error_message("implicit tagging is not supported"); } break; case 5: #line 250 "asn1parse.y" { lex_error_message("automatic tagging is not supported"); } break; case 7: #line 255 "asn1parse.y" { lex_error_message("no extensibility options supported"); } break; case 17: #line 276 "asn1parse.y" { struct string_list *sl; for(sl = (yyvsp[(1) - (4)].sl); sl != NULL; sl = sl->next) { Symbol *s = addsym(sl->string); s->stype = Stype; gen_template_import(s); } add_import((yyvsp[(3) - (4)].name)); } break; case 18: #line 288 "asn1parse.y" { struct string_list *sl; for(sl = (yyvsp[(2) - (3)].sl); sl != NULL; sl = sl->next) add_export(sl->string); } break; case 25: #line 306 "asn1parse.y" { (yyval.sl) = emalloc(sizeof(*(yyval.sl))); (yyval.sl)->string = (yyvsp[(1) - (3)].name); (yyval.sl)->next = (yyvsp[(3) - (3)].sl); } break; case 26: #line 312 "asn1parse.y" { (yyval.sl) = emalloc(sizeof(*(yyval.sl))); (yyval.sl)->string = (yyvsp[(1) - (1)].name); (yyval.sl)->next = NULL; } break; case 27: #line 320 "asn1parse.y" { Symbol *s = addsym ((yyvsp[(1) - (3)].name)); s->stype = Stype; s->type = (yyvsp[(3) - (3)].type); fix_labels(s); generate_type (s); } break; case 45: #line 351 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_Boolean, TE_EXPLICIT, new_type(TBoolean)); } break; case 46: #line 358 "asn1parse.y" { if((yyvsp[(2) - (5)].value)->type != integervalue) lex_error_message("Non-integer used in first part of range"); if((yyvsp[(2) - (5)].value)->type != integervalue) lex_error_message("Non-integer in second part of range"); (yyval.range) = ecalloc(1, sizeof(*(yyval.range))); (yyval.range)->min = (yyvsp[(2) - (5)].value)->u.integervalue; (yyval.range)->max = (yyvsp[(4) - (5)].value)->u.integervalue; } break; case 47: #line 368 "asn1parse.y" { if((yyvsp[(2) - (5)].value)->type != integervalue) lex_error_message("Non-integer in first part of range"); (yyval.range) = ecalloc(1, sizeof(*(yyval.range))); (yyval.range)->min = (yyvsp[(2) - (5)].value)->u.integervalue; - (yyval.range)->max = (yyvsp[(2) - (5)].value)->u.integervalue - 1; + (yyval.range)->max = INT_MAX; } break; case 48: #line 376 "asn1parse.y" { if((yyvsp[(4) - (5)].value)->type != integervalue) lex_error_message("Non-integer in second part of range"); (yyval.range) = ecalloc(1, sizeof(*(yyval.range))); - (yyval.range)->min = (yyvsp[(4) - (5)].value)->u.integervalue + 2; + (yyval.range)->min = INT_MIN; (yyval.range)->max = (yyvsp[(4) - (5)].value)->u.integervalue; } break; case 49: #line 384 "asn1parse.y" { if((yyvsp[(2) - (3)].value)->type != integervalue) lex_error_message("Non-integer used in limit"); (yyval.range) = ecalloc(1, sizeof(*(yyval.range))); (yyval.range)->min = (yyvsp[(2) - (3)].value)->u.integervalue; (yyval.range)->max = (yyvsp[(2) - (3)].value)->u.integervalue; } break; case 50: #line 395 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, new_type(TInteger)); } break; case 51: #line 400 "asn1parse.y" { (yyval.type) = new_type(TInteger); (yyval.type)->range = (yyvsp[(2) - (2)].range); (yyval.type) = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, (yyval.type)); } break; case 52: #line 406 "asn1parse.y" { (yyval.type) = new_type(TInteger); (yyval.type)->members = (yyvsp[(3) - (4)].members); (yyval.type) = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, (yyval.type)); } break; case 53: #line 414 "asn1parse.y" { (yyval.members) = emalloc(sizeof(*(yyval.members))); ASN1_TAILQ_INIT((yyval.members)); ASN1_TAILQ_INSERT_HEAD((yyval.members), (yyvsp[(1) - (1)].member), members); } break; case 54: #line 420 "asn1parse.y" { ASN1_TAILQ_INSERT_TAIL((yyvsp[(1) - (3)].members), (yyvsp[(3) - (3)].member), members); (yyval.members) = (yyvsp[(1) - (3)].members); } break; case 55: #line 425 "asn1parse.y" { (yyval.members) = (yyvsp[(1) - (3)].members); } break; case 56: #line 429 "asn1parse.y" { (yyval.member) = emalloc(sizeof(*(yyval.member))); (yyval.member)->name = (yyvsp[(1) - (4)].name); (yyval.member)->gen_name = estrdup((yyvsp[(1) - (4)].name)); output_name ((yyval.member)->gen_name); (yyval.member)->val = (yyvsp[(3) - (4)].constant); (yyval.member)->optional = 0; (yyval.member)->ellipsis = 0; (yyval.member)->type = NULL; } break; case 57: #line 442 "asn1parse.y" { (yyval.type) = new_type(TInteger); (yyval.type)->members = (yyvsp[(3) - (4)].members); (yyval.type) = new_tag(ASN1_C_UNIV, UT_Enumerated, TE_EXPLICIT, (yyval.type)); } break; case 59: #line 453 "asn1parse.y" { (yyval.type) = new_type(TBitString); (yyval.type)->members = emalloc(sizeof(*(yyval.type)->members)); ASN1_TAILQ_INIT((yyval.type)->members); (yyval.type) = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, (yyval.type)); } break; case 60: #line 460 "asn1parse.y" { (yyval.type) = new_type(TBitString); (yyval.type)->members = (yyvsp[(4) - (5)].members); (yyval.type) = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, (yyval.type)); } break; case 61: #line 468 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_OID, TE_EXPLICIT, new_type(TOID)); } break; case 62: #line 474 "asn1parse.y" { Type *t = new_type(TOctetString); t->range = (yyvsp[(3) - (3)].range); (yyval.type) = new_tag(ASN1_C_UNIV, UT_OctetString, TE_EXPLICIT, t); } break; case 63: #line 483 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_Null, TE_EXPLICIT, new_type(TNull)); } break; case 64: #line 490 "asn1parse.y" { (yyval.range) = NULL; } break; case 65: #line 492 "asn1parse.y" { (yyval.range) = (yyvsp[(2) - (2)].range); } break; case 66: #line 497 "asn1parse.y" { (yyval.type) = new_type(TSequence); (yyval.type)->members = (yyvsp[(3) - (4)].members); (yyval.type) = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, (yyval.type)); } break; case 67: #line 503 "asn1parse.y" { (yyval.type) = new_type(TSequence); (yyval.type)->members = NULL; (yyval.type) = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, (yyval.type)); } break; case 68: #line 511 "asn1parse.y" { (yyval.type) = new_type(TSequenceOf); (yyval.type)->range = (yyvsp[(2) - (4)].range); (yyval.type)->subtype = (yyvsp[(4) - (4)].type); (yyval.type) = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, (yyval.type)); } break; case 69: #line 520 "asn1parse.y" { (yyval.type) = new_type(TSet); (yyval.type)->members = (yyvsp[(3) - (4)].members); (yyval.type) = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, (yyval.type)); } break; case 70: #line 526 "asn1parse.y" { (yyval.type) = new_type(TSet); (yyval.type)->members = NULL; (yyval.type) = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, (yyval.type)); } break; case 71: #line 534 "asn1parse.y" { (yyval.type) = new_type(TSetOf); (yyval.type)->subtype = (yyvsp[(3) - (3)].type); (yyval.type) = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, (yyval.type)); } break; case 72: #line 542 "asn1parse.y" { (yyval.type) = new_type(TChoice); (yyval.type)->members = (yyvsp[(3) - (4)].members); } break; case 75: #line 553 "asn1parse.y" { Symbol *s = addsym((yyvsp[(1) - (1)].name)); (yyval.type) = new_type(TType); if(s->stype != Stype && s->stype != SUndefined) lex_error_message ("%s is not a type\n", (yyvsp[(1) - (1)].name)); else (yyval.type)->symbol = s; } break; case 76: #line 564 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_GeneralizedTime, TE_EXPLICIT, new_type(TGeneralizedTime)); } break; case 77: #line 569 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_UTCTime, TE_EXPLICIT, new_type(TUTCTime)); } break; case 78: #line 576 "asn1parse.y" { /* if (Constraint.type == contentConstrant) { assert(Constraint.u.constraint.type == octetstring|bitstring-w/o-NamedBitList); // remember to check type reference too if (Constraint.u.constraint.type) { assert((Constraint.u.constraint.type.length % 8) == 0); } } if (Constraint.u.constraint.encoding) { type == der-oid|ber-oid } */ } break; case 79: #line 592 "asn1parse.y" { (yyval.constraint_spec) = (yyvsp[(2) - (3)].constraint_spec); } break; case 83: #line 605 "asn1parse.y" { (yyval.constraint_spec) = new_constraint_spec(CT_CONTENTS); (yyval.constraint_spec)->u.content.type = (yyvsp[(2) - (2)].type); (yyval.constraint_spec)->u.content.encoding = NULL; } break; case 84: #line 611 "asn1parse.y" { if ((yyvsp[(3) - (3)].value)->type != objectidentifiervalue) lex_error_message("Non-OID used in ENCODED BY constraint"); (yyval.constraint_spec) = new_constraint_spec(CT_CONTENTS); (yyval.constraint_spec)->u.content.type = NULL; (yyval.constraint_spec)->u.content.encoding = (yyvsp[(3) - (3)].value); } break; case 85: #line 619 "asn1parse.y" { if ((yyvsp[(5) - (5)].value)->type != objectidentifiervalue) lex_error_message("Non-OID used in ENCODED BY constraint"); (yyval.constraint_spec) = new_constraint_spec(CT_CONTENTS); (yyval.constraint_spec)->u.content.type = (yyvsp[(2) - (5)].type); (yyval.constraint_spec)->u.content.encoding = (yyvsp[(5) - (5)].value); } break; case 86: #line 629 "asn1parse.y" { (yyval.constraint_spec) = new_constraint_spec(CT_USER); } break; case 87: #line 635 "asn1parse.y" { (yyval.type) = new_type(TTag); (yyval.type)->tag = (yyvsp[(1) - (3)].tag); (yyval.type)->tag.tagenv = (yyvsp[(2) - (3)].constant); if((yyvsp[(3) - (3)].type)->type == TTag && (yyvsp[(2) - (3)].constant) == TE_IMPLICIT) { (yyval.type)->subtype = (yyvsp[(3) - (3)].type)->subtype; free((yyvsp[(3) - (3)].type)); } else (yyval.type)->subtype = (yyvsp[(3) - (3)].type); } break; case 88: #line 648 "asn1parse.y" { (yyval.tag).tagclass = (yyvsp[(2) - (4)].constant); (yyval.tag).tagvalue = (yyvsp[(3) - (4)].constant); (yyval.tag).tagenv = TE_EXPLICIT; } break; case 89: #line 656 "asn1parse.y" { (yyval.constant) = ASN1_C_CONTEXT; } break; case 90: #line 660 "asn1parse.y" { (yyval.constant) = ASN1_C_UNIV; } break; case 91: #line 664 "asn1parse.y" { (yyval.constant) = ASN1_C_APPL; } break; case 92: #line 668 "asn1parse.y" { (yyval.constant) = ASN1_C_PRIVATE; } break; case 93: #line 674 "asn1parse.y" { (yyval.constant) = TE_EXPLICIT; } break; case 94: #line 678 "asn1parse.y" { (yyval.constant) = TE_EXPLICIT; } break; case 95: #line 682 "asn1parse.y" { (yyval.constant) = TE_IMPLICIT; } break; case 96: #line 689 "asn1parse.y" { Symbol *s; s = addsym ((yyvsp[(1) - (4)].name)); s->stype = SValue; s->value = (yyvsp[(4) - (4)].value); generate_constant (s); } break; case 98: #line 703 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_GeneralString, TE_EXPLICIT, new_type(TGeneralString)); } break; case 99: #line 708 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_TeletexString, TE_EXPLICIT, new_type(TTeletexString)); } break; case 100: #line 713 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_UTF8String, TE_EXPLICIT, new_type(TUTF8String)); } break; case 101: #line 718 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_PrintableString, TE_EXPLICIT, new_type(TPrintableString)); } break; case 102: #line 723 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_VisibleString, TE_EXPLICIT, new_type(TVisibleString)); } break; case 103: #line 728 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_IA5String, TE_EXPLICIT, new_type(TIA5String)); } break; case 104: #line 733 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_BMPString, TE_EXPLICIT, new_type(TBMPString)); } break; case 105: #line 738 "asn1parse.y" { (yyval.type) = new_tag(ASN1_C_UNIV, UT_UniversalString, TE_EXPLICIT, new_type(TUniversalString)); } break; case 106: #line 746 "asn1parse.y" { (yyval.members) = emalloc(sizeof(*(yyval.members))); ASN1_TAILQ_INIT((yyval.members)); ASN1_TAILQ_INSERT_HEAD((yyval.members), (yyvsp[(1) - (1)].member), members); } break; case 107: #line 752 "asn1parse.y" { ASN1_TAILQ_INSERT_TAIL((yyvsp[(1) - (3)].members), (yyvsp[(3) - (3)].member), members); (yyval.members) = (yyvsp[(1) - (3)].members); } break; case 108: #line 757 "asn1parse.y" { struct member *m = ecalloc(1, sizeof(*m)); m->name = estrdup("..."); m->gen_name = estrdup("asn1_ellipsis"); m->ellipsis = 1; ASN1_TAILQ_INSERT_TAIL((yyvsp[(1) - (3)].members), m, members); (yyval.members) = (yyvsp[(1) - (3)].members); } break; case 109: #line 768 "asn1parse.y" { (yyval.member) = emalloc(sizeof(*(yyval.member))); (yyval.member)->name = (yyvsp[(1) - (2)].name); (yyval.member)->gen_name = estrdup((yyvsp[(1) - (2)].name)); output_name ((yyval.member)->gen_name); (yyval.member)->type = (yyvsp[(2) - (2)].type); (yyval.member)->ellipsis = 0; } break; case 110: #line 779 "asn1parse.y" { (yyval.member) = (yyvsp[(1) - (1)].member); (yyval.member)->optional = 0; (yyval.member)->defval = NULL; } break; case 111: #line 785 "asn1parse.y" { (yyval.member) = (yyvsp[(1) - (2)].member); (yyval.member)->optional = 1; (yyval.member)->defval = NULL; } break; case 112: #line 791 "asn1parse.y" { (yyval.member) = (yyvsp[(1) - (3)].member); (yyval.member)->optional = 0; (yyval.member)->defval = (yyvsp[(3) - (3)].value); } break; case 113: #line 799 "asn1parse.y" { (yyval.members) = emalloc(sizeof(*(yyval.members))); ASN1_TAILQ_INIT((yyval.members)); ASN1_TAILQ_INSERT_HEAD((yyval.members), (yyvsp[(1) - (1)].member), members); } break; case 114: #line 805 "asn1parse.y" { ASN1_TAILQ_INSERT_TAIL((yyvsp[(1) - (3)].members), (yyvsp[(3) - (3)].member), members); (yyval.members) = (yyvsp[(1) - (3)].members); } break; case 115: #line 812 "asn1parse.y" { (yyval.member) = emalloc(sizeof(*(yyval.member))); (yyval.member)->name = (yyvsp[(1) - (4)].name); (yyval.member)->gen_name = estrdup((yyvsp[(1) - (4)].name)); output_name ((yyval.member)->gen_name); (yyval.member)->val = (yyvsp[(3) - (4)].constant); (yyval.member)->optional = 0; (yyval.member)->ellipsis = 0; (yyval.member)->type = NULL; } break; case 117: #line 825 "asn1parse.y" { (yyval.objid) = NULL; } break; case 118: #line 829 "asn1parse.y" { (yyval.objid) = (yyvsp[(2) - (3)].objid); } break; case 119: #line 835 "asn1parse.y" { (yyval.objid) = NULL; } break; case 120: #line 839 "asn1parse.y" { if ((yyvsp[(2) - (2)].objid)) { (yyval.objid) = (yyvsp[(2) - (2)].objid); add_oid_to_tail((yyvsp[(2) - (2)].objid), (yyvsp[(1) - (2)].objid)); } else { (yyval.objid) = (yyvsp[(1) - (2)].objid); } } break; case 121: #line 850 "asn1parse.y" { (yyval.objid) = new_objid((yyvsp[(1) - (4)].name), (yyvsp[(3) - (4)].constant)); } break; case 122: #line 854 "asn1parse.y" { Symbol *s = addsym((yyvsp[(1) - (1)].name)); if(s->stype != SValue || s->value->type != objectidentifiervalue) { lex_error_message("%s is not an object identifier\n", s->name); exit(1); } (yyval.objid) = s->value->u.objectidentifiervalue; } break; case 123: #line 865 "asn1parse.y" { (yyval.objid) = new_objid(NULL, (yyvsp[(1) - (1)].constant)); } break; case 133: #line 888 "asn1parse.y" { Symbol *s = addsym((yyvsp[(1) - (1)].name)); if(s->stype != SValue) lex_error_message ("%s is not a value\n", s->name); else (yyval.value) = s->value; } break; case 134: #line 899 "asn1parse.y" { (yyval.value) = emalloc(sizeof(*(yyval.value))); (yyval.value)->type = stringvalue; (yyval.value)->u.stringvalue = (yyvsp[(1) - (1)].name); } break; case 135: #line 907 "asn1parse.y" { (yyval.value) = emalloc(sizeof(*(yyval.value))); (yyval.value)->type = booleanvalue; (yyval.value)->u.booleanvalue = 0; } break; case 136: #line 913 "asn1parse.y" { (yyval.value) = emalloc(sizeof(*(yyval.value))); (yyval.value)->type = booleanvalue; (yyval.value)->u.booleanvalue = 0; } break; case 137: #line 921 "asn1parse.y" { (yyval.value) = emalloc(sizeof(*(yyval.value))); (yyval.value)->type = integervalue; (yyval.value)->u.integervalue = (yyvsp[(1) - (1)].constant); } break; case 139: #line 932 "asn1parse.y" { } break; case 140: #line 937 "asn1parse.y" { (yyval.value) = emalloc(sizeof(*(yyval.value))); (yyval.value)->type = objectidentifiervalue; (yyval.value)->u.objectidentifiervalue = (yyvsp[(1) - (1)].objid); } break; /* Line 1267 of yacc.c. */ #line 2553 "asn1parse.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (yymsg); } else { yyerror (YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEOF && yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } #line 944 "asn1parse.y" void yyerror (const char *s) { lex_error_message ("%s\n", s); } static Type * new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype) { 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 add_oid_to_tail(struct objid *head, struct objid *tail) { 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 struct constraint_spec * new_constraint_spec(enum ctype ct) { struct constraint_spec *c = ecalloc(1, sizeof(*c)); c->ctype = ct; return c; } 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) { if (asprintf(&m->label, "%s_%s", prefix, m->gen_name) < 0) errx(1, "malloc"); 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 = NULL; if (asprintf(&p, "choice_%s", s->gen_name) < 0 || p == NULL) errx(1, "malloc"); fix_labels2(s->type, p); free(p); } diff --git a/crypto/heimdal/lib/asn1/asn1parse.h b/crypto/heimdal/lib/asn1/asn1parse.h index 69b7d6dc1a4a..c1ced1df5a44 100644 --- a/crypto/heimdal/lib/asn1/asn1parse.h +++ b/crypto/heimdal/lib/asn1/asn1parse.h @@ -1,249 +1,249 @@ /* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { kw_ABSENT = 258, kw_ABSTRACT_SYNTAX = 259, kw_ALL = 260, kw_APPLICATION = 261, kw_AUTOMATIC = 262, kw_BEGIN = 263, kw_BIT = 264, kw_BMPString = 265, kw_BOOLEAN = 266, kw_BY = 267, kw_CHARACTER = 268, kw_CHOICE = 269, kw_CLASS = 270, kw_COMPONENT = 271, kw_COMPONENTS = 272, kw_CONSTRAINED = 273, kw_CONTAINING = 274, kw_DEFAULT = 275, kw_DEFINITIONS = 276, kw_EMBEDDED = 277, kw_ENCODED = 278, kw_END = 279, kw_ENUMERATED = 280, kw_EXCEPT = 281, kw_EXPLICIT = 282, kw_EXPORTS = 283, kw_EXTENSIBILITY = 284, kw_EXTERNAL = 285, kw_FALSE = 286, kw_FROM = 287, kw_GeneralString = 288, kw_GeneralizedTime = 289, kw_GraphicString = 290, kw_IA5String = 291, kw_IDENTIFIER = 292, kw_IMPLICIT = 293, kw_IMPLIED = 294, kw_IMPORTS = 295, kw_INCLUDES = 296, kw_INSTANCE = 297, kw_INTEGER = 298, kw_INTERSECTION = 299, kw_ISO646String = 300, kw_MAX = 301, kw_MIN = 302, kw_MINUS_INFINITY = 303, kw_NULL = 304, kw_NumericString = 305, kw_OBJECT = 306, kw_OCTET = 307, kw_OF = 308, kw_OPTIONAL = 309, kw_ObjectDescriptor = 310, kw_PATTERN = 311, kw_PDV = 312, kw_PLUS_INFINITY = 313, kw_PRESENT = 314, kw_PRIVATE = 315, kw_PrintableString = 316, kw_REAL = 317, kw_RELATIVE_OID = 318, kw_SEQUENCE = 319, kw_SET = 320, kw_SIZE = 321, kw_STRING = 322, kw_SYNTAX = 323, kw_T61String = 324, kw_TAGS = 325, kw_TRUE = 326, kw_TYPE_IDENTIFIER = 327, kw_TeletexString = 328, kw_UNION = 329, kw_UNIQUE = 330, kw_UNIVERSAL = 331, kw_UTCTime = 332, kw_UTF8String = 333, kw_UniversalString = 334, kw_VideotexString = 335, kw_VisibleString = 336, kw_WITH = 337, RANGE = 338, EEQUAL = 339, ELLIPSIS = 340, IDENTIFIER = 341, referencename = 342, STRING = 343, NUMBER = 344 }; #endif /* Tokens. */ #define kw_ABSENT 258 #define kw_ABSTRACT_SYNTAX 259 #define kw_ALL 260 #define kw_APPLICATION 261 #define kw_AUTOMATIC 262 #define kw_BEGIN 263 #define kw_BIT 264 #define kw_BMPString 265 #define kw_BOOLEAN 266 #define kw_BY 267 #define kw_CHARACTER 268 #define kw_CHOICE 269 #define kw_CLASS 270 #define kw_COMPONENT 271 #define kw_COMPONENTS 272 #define kw_CONSTRAINED 273 #define kw_CONTAINING 274 #define kw_DEFAULT 275 #define kw_DEFINITIONS 276 #define kw_EMBEDDED 277 #define kw_ENCODED 278 #define kw_END 279 #define kw_ENUMERATED 280 #define kw_EXCEPT 281 #define kw_EXPLICIT 282 #define kw_EXPORTS 283 #define kw_EXTENSIBILITY 284 #define kw_EXTERNAL 285 #define kw_FALSE 286 #define kw_FROM 287 #define kw_GeneralString 288 #define kw_GeneralizedTime 289 #define kw_GraphicString 290 #define kw_IA5String 291 #define kw_IDENTIFIER 292 #define kw_IMPLICIT 293 #define kw_IMPLIED 294 #define kw_IMPORTS 295 #define kw_INCLUDES 296 #define kw_INSTANCE 297 #define kw_INTEGER 298 #define kw_INTERSECTION 299 #define kw_ISO646String 300 #define kw_MAX 301 #define kw_MIN 302 #define kw_MINUS_INFINITY 303 #define kw_NULL 304 #define kw_NumericString 305 #define kw_OBJECT 306 #define kw_OCTET 307 #define kw_OF 308 #define kw_OPTIONAL 309 #define kw_ObjectDescriptor 310 #define kw_PATTERN 311 #define kw_PDV 312 #define kw_PLUS_INFINITY 313 #define kw_PRESENT 314 #define kw_PRIVATE 315 #define kw_PrintableString 316 #define kw_REAL 317 #define kw_RELATIVE_OID 318 #define kw_SEQUENCE 319 #define kw_SET 320 #define kw_SIZE 321 #define kw_STRING 322 #define kw_SYNTAX 323 #define kw_T61String 324 #define kw_TAGS 325 #define kw_TRUE 326 #define kw_TYPE_IDENTIFIER 327 #define kw_TeletexString 328 #define kw_UNION 329 #define kw_UNIQUE 330 #define kw_UNIVERSAL 331 #define kw_UTCTime 332 #define kw_UTF8String 333 #define kw_UniversalString 334 #define kw_VideotexString 335 #define kw_VisibleString 336 #define kw_WITH 337 #define RANGE 338 #define EEQUAL 339 #define ELLIPSIS 340 #define IDENTIFIER 341 #define referencename 342 #define STRING 343 #define NUMBER 344 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE #line 71 "asn1parse.y" { - int constant; + int64_t 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; struct constraint_spec *constraint_spec; } /* Line 1529 of yacc.c. */ #line 242 "asn1parse.h" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif extern YYSTYPE yylval; diff --git a/crypto/heimdal/lib/asn1/asn1parse.y b/crypto/heimdal/lib/asn1/asn1parse.y index e3bea6ce0ac9..b419676d3429 100644 --- a/crypto/heimdal/lib/asn1/asn1parse.y +++ b/crypto/heimdal/lib/asn1/asn1parse.y @@ -1,1037 +1,1037 @@ /* * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Portions Copyright (c) 2009 Apple Inc. 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. */ /* $Id$ */ %{ #include #include #include #include #include "symbol.h" #include "lex.h" #include "gen_locl.h" #include "der.h" RCSID("$Id$"); static Type *new_type (Typetype t); static struct constraint_spec *new_constraint_spec(enum ctype); static Type *new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype); void yyerror (const 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); struct string_list { char *string; struct string_list *next; }; /* Declarations for Bison */ #define YYMALLOC malloc #define YYFREE free %} %union { - int constant; + int64_t 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; struct constraint_spec *constraint_spec; } %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 %token RANGE %token EEQUAL %token ELLIPSIS %token IDENTIFIER referencename %token STRING %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 ConstrainedType %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 size %type referencenames %type Constraint %type ConstraintSpec %type GeneralConstraint %type ContentsConstraint %type UserDefinedConstraint %start ModuleDefinition %% ModuleDefinition: IDENTIFIER objid_opt kw_DEFINITIONS TagDefault ExtensionDefault EEQUAL kw_BEGIN ModuleBody kw_END { checkundefined(); } ; TagDefault : kw_EXPLICIT kw_TAGS | kw_IMPLICIT kw_TAGS { lex_error_message("implicit tagging is not supported"); } | kw_AUTOMATIC kw_TAGS { lex_error_message("automatic tagging is not supported"); } | /* empty */ ; ExtensionDefault: kw_EXTENSIBILITY kw_IMPLIED { lex_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; gen_template_import(s); } add_import($3); } ; Exports : kw_EXPORTS referencenames ';' { struct string_list *sl; for(sl = $2; sl != NULL; sl = sl->next) add_export(sl->string); } | kw_EXPORTS kw_ALL | /* empty */ ; AssignmentList : Assignment | Assignment AssignmentList ; Assignment : TypeAssignment | ValueAssignment ; referencenames : IDENTIFIER ',' referencenames { $$ = emalloc(sizeof(*$$)); $$->string = $1; $$->next = $3; } | IDENTIFIER { $$ = emalloc(sizeof(*$$)); $$->string = $1; $$->next = NULL; } ; TypeAssignment : IDENTIFIER EEQUAL Type { Symbol *s = addsym ($1); s->stype = Stype; s->type = $3; fix_labels(s); generate_type (s); } ; Type : BuiltinType | ReferencedType | ConstrainedType ; 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)); } ; range : '(' Value RANGE Value ')' { if($2->type != integervalue) lex_error_message("Non-integer used in first part of range"); if($2->type != integervalue) lex_error_message("Non-integer in second part of range"); $$ = ecalloc(1, sizeof(*$$)); $$->min = $2->u.integervalue; $$->max = $4->u.integervalue; } | '(' Value RANGE kw_MAX ')' { if($2->type != integervalue) lex_error_message("Non-integer in first part of range"); $$ = ecalloc(1, sizeof(*$$)); $$->min = $2->u.integervalue; - $$->max = $2->u.integervalue - 1; + $$->max = INT_MAX; } | '(' kw_MIN RANGE Value ')' { if($4->type != integervalue) lex_error_message("Non-integer in second part of range"); $$ = ecalloc(1, sizeof(*$$)); - $$->min = $4->u.integervalue + 2; + $$->min = INT_MIN; $$->max = $4->u.integervalue; } | '(' Value ')' { if($2->type != integervalue) lex_error_message("Non-integer used in limit"); $$ = ecalloc(1, sizeof(*$$)); $$->min = $2->u.integervalue; $$->max = $2->u.integervalue; } ; IntegerType : kw_INTEGER { $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, new_type(TInteger)); } | kw_INTEGER range { $$ = new_type(TInteger); $$->range = $2; $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$); } | kw_INTEGER '{' NamedNumberList '}' { $$ = new_type(TInteger); $$->members = $3; $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$); } ; 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 size { Type *t = new_type(TOctetString); t->range = $3; $$ = new_tag(ASN1_C_UNIV, UT_OctetString, TE_EXPLICIT, t); } ; NullType : kw_NULL { $$ = new_tag(ASN1_C_UNIV, UT_Null, TE_EXPLICIT, new_type(TNull)); } ; size : { $$ = NULL; } | kw_SIZE range { $$ = $2; } ; SequenceType : kw_SEQUENCE '{' /* ComponentTypeLists */ ComponentTypeList '}' { $$ = new_type(TSequence); $$->members = $3; $$ = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, $$); } | kw_SEQUENCE '{' '}' { $$ = new_type(TSequence); $$->members = NULL; $$ = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, $$); } ; SequenceOfType : kw_SEQUENCE size kw_OF Type { $$ = new_type(TSequenceOf); $$->range = $2; $$->subtype = $4; $$ = 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; } ; ReferencedType : DefinedType | UsefulType ; DefinedType : IDENTIFIER { Symbol *s = addsym($1); $$ = new_type(TType); if(s->stype != Stype && s->stype != SUndefined) lex_error_message ("%s is not a type\n", $1); else $$->symbol = s; } ; UsefulType : kw_GeneralizedTime { $$ = new_tag(ASN1_C_UNIV, UT_GeneralizedTime, TE_EXPLICIT, new_type(TGeneralizedTime)); } | kw_UTCTime { $$ = new_tag(ASN1_C_UNIV, UT_UTCTime, TE_EXPLICIT, new_type(TUTCTime)); } ; ConstrainedType : Type Constraint { /* if (Constraint.type == contentConstrant) { assert(Constraint.u.constraint.type == octetstring|bitstring-w/o-NamedBitList); // remember to check type reference too if (Constraint.u.constraint.type) { assert((Constraint.u.constraint.type.length % 8) == 0); } } if (Constraint.u.constraint.encoding) { type == der-oid|ber-oid } */ } ; Constraint : '(' ConstraintSpec ')' { $$ = $2; } ; ConstraintSpec : GeneralConstraint ; GeneralConstraint: ContentsConstraint | UserDefinedConstraint ; ContentsConstraint: kw_CONTAINING Type { $$ = new_constraint_spec(CT_CONTENTS); $$->u.content.type = $2; $$->u.content.encoding = NULL; } | kw_ENCODED kw_BY Value { if ($3->type != objectidentifiervalue) lex_error_message("Non-OID used in ENCODED BY constraint"); $$ = new_constraint_spec(CT_CONTENTS); $$->u.content.type = NULL; $$->u.content.encoding = $3; } | kw_CONTAINING Type kw_ENCODED kw_BY Value { if ($5->type != objectidentifiervalue) lex_error_message("Non-OID used in ENCODED BY constraint"); $$ = new_constraint_spec(CT_CONTENTS); $$->u.content.type = $2; $$->u.content.encoding = $5; } ; UserDefinedConstraint: kw_CONSTRAINED kw_BY '{' '}' { $$ = new_constraint_spec(CT_USER); } ; 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; } ; ValueAssignment : IDENTIFIER Type EEQUAL Value { 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_TeletexString { $$ = new_tag(ASN1_C_UNIV, UT_TeletexString, TE_EXPLICIT, new_type(TTeletexString)); } | 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_VisibleString { $$ = new_tag(ASN1_C_UNIV, UT_VisibleString, TE_EXPLICIT, new_type(TVisibleString)); } | 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 = 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; } ; 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) { lex_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) lex_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 yyerror (const char *s) { lex_error_message ("%s\n", s); } static Type * new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype) { 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 add_oid_to_tail(struct objid *head, struct objid *tail) { 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 struct constraint_spec * new_constraint_spec(enum ctype ct) { struct constraint_spec *c = ecalloc(1, sizeof(*c)); c->ctype = ct; return c; } 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) { if (asprintf(&m->label, "%s_%s", prefix, m->gen_name) < 0) errx(1, "malloc"); 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 = NULL; if (asprintf(&p, "choice_%s", s->gen_name) < 0 || p == NULL) errx(1, "malloc"); fix_labels2(s->type, p); free(p); } diff --git a/crypto/heimdal/lib/asn1/check-gen.c b/crypto/heimdal/lib/asn1/check-gen.c index e686f166cfa0..44699cab4356 100644 --- a/crypto/heimdal/lib/asn1/check-gen.c +++ b/crypto/heimdal/lib/asn1/check-gen.c @@ -1,1311 +1,1431 @@ /* * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Portions Copyright (c) 2009 Apple Inc. 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. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "check-common.h" RCSID("$Id$"); 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) \ do { if ((ac)->e != (bc)->e) return 1; } while(0) #define COMPARE_OPT_INTEGER(ac,bc,e) \ do { if (*(ac)->e != *(bc)->e) return 1; } while(0) #define COMPARE_MEM(ac,bc,e,len) \ do { if (memcmp((ac)->e, (bc)->e,len) != 0) return 1; } while(0) static int cmp_principal (void *a, void *b) { Principal *pa = a; Principal *pb = b; int i; COMPARE_STRING(pa,pb,realm); COMPARE_INTEGER(pa,pb,name.name_type); COMPARE_INTEGER(pa,pb,name.name_string.len); for (i = 0; i < pa->name.name_string.len; i++) COMPARE_STRING(pa,pb,name.name_string.val[i]); return 0; } static int test_principal (void) { struct test_case tests[] = { { NULL, 29, "\x30\x1b\xa0\x10\x30\x0e\xa0\x03\x02\x01\x01\xa1\x07\x30\x05\x1b" "\x03\x6c\x68\x61\xa1\x07\x1b\x05\x53\x55\x2e\x53\x45" }, { NULL, 35, "\x30\x21\xa0\x16\x30\x14\xa0\x03\x02\x01\x01\xa1\x0d\x30\x0b\x1b" "\x03\x6c\x68\x61\x1b\x04\x72\x6f\x6f\x74\xa1\x07\x1b\x05\x53\x55" "\x2e\x53\x45" }, { NULL, 54, "\x30\x34\xa0\x26\x30\x24\xa0\x03\x02\x01\x03\xa1\x1d\x30\x1b\x1b" "\x04\x68\x6f\x73\x74\x1b\x13\x6e\x75\x74\x63\x72\x61\x63\x6b\x65" "\x72\x2e\x65\x2e\x6b\x74\x68\x2e\x73\x65\xa1\x0a\x1b\x08\x45\x2e" "\x4b\x54\x48\x2e\x53\x45" } }; Principal values[] = { { { 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" } }; int i, ret; int ntests = sizeof(tests) / sizeof(*tests); for (i = 0; i < ntests; ++i) { tests[i].val = &values[i]; if (asprintf (&tests[i].name, "Principal %d", i) < 0) errx(1, "malloc"); if (tests[i].name == NULL) errx(1, "malloc"); } ret = generic_test (tests, ntests, sizeof(Principal), (generic_encode)encode_Principal, (generic_length)length_Principal, (generic_decode)decode_Principal, (generic_free)free_Principal, cmp_principal, NULL); for (i = 0; i < ntests; ++i) free (tests[i].name); return ret; } static int cmp_authenticator (void *a, void *b) { Authenticator *aa = a; Authenticator *ab = b; int i; COMPARE_INTEGER(aa,ab,authenticator_vno); COMPARE_STRING(aa,ab,crealm); COMPARE_INTEGER(aa,ab,cname.name_type); COMPARE_INTEGER(aa,ab,cname.name_string.len); for (i = 0; i < aa->cname.name_string.len; i++) COMPARE_STRING(aa,ab,cname.name_string.val[i]); return 0; } static int test_authenticator (void) { struct test_case tests[] = { { NULL, 63, "\x62\x3d\x30\x3b\xa0\x03\x02\x01\x05\xa1\x0a\x1b\x08" "\x45\x2e\x4b\x54\x48\x2e\x53\x45\xa2\x10\x30\x0e\xa0" "\x03\x02\x01\x01\xa1\x07\x30\x05\x1b\x03\x6c\x68\x61" "\xa4\x03\x02\x01\x0a\xa5\x11\x18\x0f\x31\x39\x37\x30" "\x30\x31\x30\x31\x30\x30\x30\x31\x33\x39\x5a" }, { NULL, 67, "\x62\x41\x30\x3f\xa0\x03\x02\x01\x05\xa1\x07\x1b\x05" "\x53\x55\x2e\x53\x45\xa2\x16\x30\x14\xa0\x03\x02\x01" "\x01\xa1\x0d\x30\x0b\x1b\x03\x6c\x68\x61\x1b\x04\x72" "\x6f\x6f\x74\xa4\x04\x02\x02\x01\x24\xa5\x11\x18\x0f" "\x31\x39\x37\x30\x30\x31\x30\x31\x30\x30\x31\x36\x33" "\x39\x5a" } }; Authenticator values[] = { { 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 } }; int i, ret; int ntests = sizeof(tests) / sizeof(*tests); for (i = 0; i < ntests; ++i) { tests[i].val = &values[i]; if (asprintf (&tests[i].name, "Authenticator %d", i) < 0) errx(1, "malloc"); if (tests[i].name == NULL) errx(1, "malloc"); } ret = generic_test (tests, ntests, sizeof(Authenticator), (generic_encode)encode_Authenticator, (generic_length)length_Authenticator, (generic_decode)decode_Authenticator, (generic_free)free_Authenticator, cmp_authenticator, (generic_copy)copy_Authenticator); for (i = 0; i < ntests; ++i) free(tests[i].name); return ret; } static int cmp_KRB_ERROR (void *a, void *b) { KRB_ERROR *aa = a; KRB_ERROR *ab = b; int i; 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 int test_krb_error (void) { struct test_case tests[] = { { NULL, 127, "\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, (generic_copy)copy_KRB_ERROR); } static int cmp_Name (void *a, void *b) { Name *aa = a; Name *ab = b; COMPARE_INTEGER(aa,ab,element); return 0; } static int test_Name (void) { struct test_case tests[] = { { NULL, 35, "\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, 35, "\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" } }; 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.data = "Love"; atv1[0].value.u.printableString.length = 4; 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.data = "STOCKHOLM"; atv1[1].value.u.printableString.length = 9; /* 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.data = "STOCKHOLM"; atv2[0].value.u.printableString.length = 9; 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.data = "Love"; atv2[1].value.u.printableString.length = 4; /* */ 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, (generic_copy)copy_Name); } 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" }, { NULL, 4, "\x03\x02\x05\xa0", "bitstring 2" }, { NULL, 5, "\x03\x03\x07\x00\x80", "bitstring 3" }, { NULL, 3, "\x03\x01\x00", "bitstring 4" } }; int ntests = sizeof(tests) / sizeof(*tests); KeyUsage ku1, ku2, ku3, ku4; memset(&ku1, 0, sizeof(ku1)); ku1.digitalSignature = 1; tests[0].val = &ku1; memset(&ku2, 0, sizeof(ku2)); ku2.digitalSignature = 1; ku2.keyEncipherment = 1; tests[1].val = &ku2; memset(&ku3, 0, sizeof(ku3)); ku3.decipherOnly = 1; tests[2].val = &ku3; memset(&ku4, 0, sizeof(ku4)); tests[3].val = &ku4; 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, (generic_copy)copy_KeyUsage); } static int cmp_TicketFlags (void *a, void *b) { TicketFlags *aa = a; TicketFlags *ab = b; return TicketFlags2int(*aa) != TicketFlags2int(*ab); } static int test_bit_string_rfc1510 (void) { struct test_case tests[] = { { NULL, 7, "\x03\x05\x00\x80\x00\x00\x00", "TF bitstring 1" }, { NULL, 7, "\x03\x05\x00\x40\x20\x00\x00", "TF bitstring 2" }, { NULL, 7, "\x03\x05\x00\x00\x20\x00\x00", "TF bitstring 3" }, { NULL, 7, "\x03\x05\x00\x00\x00\x00\x00", "TF bitstring 4" } }; int ntests = sizeof(tests) / sizeof(*tests); TicketFlags tf1, tf2, tf3, tf4; memset(&tf1, 0, sizeof(tf1)); tf1.reserved = 1; tests[0].val = &tf1; memset(&tf2, 0, sizeof(tf2)); tf2.forwardable = 1; tf2.pre_authent = 1; tests[1].val = &tf2; memset(&tf3, 0, sizeof(tf3)); tf3.pre_authent = 1; tests[2].val = &tf3; memset(&tf4, 0, sizeof(tf4)); tests[3].val = &tf4; return generic_test (tests, ntests, sizeof(TicketFlags), (generic_encode)encode_TicketFlags, (generic_length)length_TicketFlags, (generic_decode)decode_TicketFlags, (generic_free)free_TicketFlags, cmp_TicketFlags, (generic_copy)copy_TicketFlags); } static int cmp_KerberosTime (void *a, void *b) { KerberosTime *aa = a; KerberosTime *ab = b; return *aa != *ab; } static int test_time (void) { struct test_case tests[] = { { NULL, 17, "\x18\x0f\x31\x39\x37\x30\x30\x31\x30\x31\x30\x31\x31\x38\x33\x31" "\x5a", "time 1" }, { NULL, 17, "\x18\x0f\x32\x30\x30\x39\x30\x35\x32\x34\x30\x32\x30\x32\x34\x30" "\x5a" "time 2" } }; int ntests = sizeof(tests) / sizeof(*tests); KerberosTime times[] = { 4711, 1243130560 }; tests[0].val = ×[0]; tests[1].val = ×[1]; return generic_test (tests, ntests, sizeof(KerberosTime), (generic_encode)encode_KerberosTime, (generic_length)length_KerberosTime, (generic_decode)decode_KerberosTime, (generic_free)free_KerberosTime, cmp_KerberosTime, (generic_copy)copy_KerberosTime); } struct { const char *cert; size_t len; } certs[] = { { "\x30\x82\x02\x6c\x30\x82\x01\xd5\xa0\x03\x02\x01\x02\x02\x09\x00" "\x99\x32\xde\x61\x0e\x40\x19\x8a\x30\x0d\x06\x09\x2a\x86\x48\x86" "\xf7\x0d\x01\x01\x05\x05\x00\x30\x2a\x31\x1b\x30\x19\x06\x03\x55" "\x04\x03\x0c\x12\x68\x78\x35\x30\x39\x20\x54\x65\x73\x74\x20\x52" "\x6f\x6f\x74\x20\x43\x41\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13" "\x02\x53\x45\x30\x1e\x17\x0d\x30\x39\x30\x34\x32\x36\x32\x30\x32" "\x39\x34\x30\x5a\x17\x0d\x31\x39\x30\x34\x32\x34\x32\x30\x32\x39" "\x34\x30\x5a\x30\x2a\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x0c\x12" "\x68\x78\x35\x30\x39\x20\x54\x65\x73\x74\x20\x52\x6f\x6f\x74\x20" "\x43\x41\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x30" "\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05" "\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xb9\xd3\x1b\x67" "\x1c\xf7\x5e\x26\x81\x3b\x82\xff\x03\xa4\x43\xb5\xb2\x63\x0b\x89" "\x58\x43\xfe\x3d\xe0\x38\x7d\x93\x74\xbb\xad\x21\xa4\x29\xd9\x34" "\x79\xf3\x1c\x8c\x5a\xd6\xb0\xd7\x19\xea\xcc\xaf\xe0\xa8\x40\x02" "\x1d\x91\xf1\xac\x36\xb0\xfb\x08\xbd\xcc\x9a\xe1\xb7\x6e\xee\x0a" "\x69\xbf\x6d\x2b\xee\x20\x82\x61\x06\xf2\x18\xcc\x89\x11\x64\x7e" "\xb2\xff\x47\xd1\x3b\x52\x73\xeb\x5a\xc0\x03\xa6\x4b\xc7\x40\x7e" "\xbc\xe1\x0e\x65\x44\x3f\x40\x8b\x02\x82\x54\x04\xd9\xcc\x2c\x67" "\x01\xb6\x16\x82\xd8\x33\x53\x17\xd7\xde\x8d\x5d\x02\x03\x01\x00" "\x01\xa3\x81\x99\x30\x81\x96\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16" "\x04\x14\x6e\x48\x13\xdc\xbf\x8b\x95\x4c\x13\xf3\x1f\x97\x30\xdd" "\x27\x96\x59\x9b\x0e\x68\x30\x5a\x06\x03\x55\x1d\x23\x04\x53\x30" "\x51\x80\x14\x6e\x48\x13\xdc\xbf\x8b\x95\x4c\x13\xf3\x1f\x97\x30" "\xdd\x27\x96\x59\x9b\x0e\x68\xa1\x2e\xa4\x2c\x30\x2a\x31\x1b\x30" "\x19\x06\x03\x55\x04\x03\x0c\x12\x68\x78\x35\x30\x39\x20\x54\x65" "\x73\x74\x20\x52\x6f\x6f\x74\x20\x43\x41\x31\x0b\x30\x09\x06\x03" "\x55\x04\x06\x13\x02\x53\x45\x82\x09\x00\x99\x32\xde\x61\x0e\x40" "\x19\x8a\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff" "\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\xe6\x30\x0d\x06" "\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00" "\x52\x9b\xe4\x0e\xee\xc2\x5d\xb7\xf1\xba\x47\xe3\xfe\xaf\x3d\x51" "\x10\xfd\xe8\x0d\x14\x58\x05\x36\xa7\xeb\xd8\x05\xe5\x27\x6f\x51" "\xb8\xec\x90\xd9\x03\xe1\xbc\x9c\x93\x38\x21\x5c\xaf\x4e\x6c\x7b" "\x6c\x65\xa9\x92\xcd\x94\xef\xa8\xae\x90\x12\x14\x78\x2d\xa3\x15" "\xaa\x42\xf1\xd9\x44\x64\x2c\x3c\xc0\xbd\x3a\x48\xd8\x80\x45\x8b" "\xd1\x79\x82\xe0\x0f\xdf\x08\x3c\x60\x21\x6f\x31\x47\x98\xae\x2f" "\xcb\xb1\xa1\xb9\xc1\xa3\x71\x5e\x4a\xc2\x67\xdf\x66\x0a\x51\xb5" "\xad\x60\x05\xdb\x02\xd4\x1a\xd2\xb9\x4e\x01\x08\x2b\xc3\x57\xaf", 624 }, { "\x30\x82\x02\x54\x30\x82\x01\xbd\xa0\x03\x02\x01\x02\x02\x01\x08" "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30" "\x2a\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x0c\x12\x68\x78\x35\x30" "\x39\x20\x54\x65\x73\x74\x20\x52\x6f\x6f\x74\x20\x43\x41\x31\x0b" "\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x30\x1e\x17\x0d\x30" "\x39\x30\x34\x32\x36\x32\x30\x32\x39\x34\x30\x5a\x17\x0d\x31\x39" "\x30\x34\x32\x34\x32\x30\x32\x39\x34\x30\x5a\x30\x1b\x31\x0b\x30" "\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x0c\x30\x0a\x06\x03" "\x55\x04\x03\x0c\x03\x6b\x64\x63\x30\x81\x9f\x30\x0d\x06\x09\x2a" "\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81" "\x89\x02\x81\x81\x00\xd2\x41\x7a\xf8\x4b\x55\xb2\xaf\x11\xf9\x43" "\x9b\x43\x81\x09\x3b\x9a\x94\xcf\x00\xf4\x85\x75\x92\xd7\x2a\xa5" "\x11\xf1\xa8\x50\x6e\xc6\x84\x74\x24\x17\xda\x84\xc8\x03\x37\xb2" "\x20\xf3\xba\xb5\x59\x36\x21\x4d\xab\x70\xe2\xc3\x09\x93\x68\x14" "\x12\x79\xc5\xbb\x9e\x1b\x4a\xf0\xc6\x24\x59\x25\xc3\x1c\xa8\x70" "\x66\x5b\x3e\x41\x8e\xe3\x25\x71\x9a\x94\xa0\x5b\x46\x91\x6f\xdd" "\x58\x14\xec\x89\xe5\x8c\x96\xc5\x38\x60\xe4\xab\xf2\x75\xee\x6e" "\x62\xfc\xe1\xbd\x03\x47\xff\xc4\xbe\x0f\xca\x70\x73\xe3\x74\x58" "\x3a\x2f\x04\x2d\x39\x02\x03\x01\x00\x01\xa3\x81\x98\x30\x81\x95" "\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x0b\x06\x03\x55" "\x1d\x0f\x04\x04\x03\x02\x05\xe0\x30\x12\x06\x03\x55\x1d\x25\x04" "\x0b\x30\x09\x06\x07\x2b\x06\x01\x05\x02\x03\x05\x30\x1d\x06\x03" "\x55\x1d\x0e\x04\x16\x04\x14\x3a\xd3\x73\xff\xab\xdb\x7d\x8d\xc6" "\x3a\xa2\x26\x3e\xae\x78\x95\x80\xc9\xe6\x31\x30\x48\x06\x03\x55" "\x1d\x11\x04\x41\x30\x3f\xa0\x3d\x06\x06\x2b\x06\x01\x05\x02\x02" "\xa0\x33\x30\x31\xa0\x0d\x1b\x0b\x54\x45\x53\x54\x2e\x48\x35\x4c" "\x2e\x53\x45\xa1\x20\x30\x1e\xa0\x03\x02\x01\x01\xa1\x17\x30\x15" "\x1b\x06\x6b\x72\x62\x74\x67\x74\x1b\x0b\x54\x45\x53\x54\x2e\x48" "\x35\x4c\x2e\x53\x45\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01" "\x01\x05\x05\x00\x03\x81\x81\x00\x83\xf4\x14\xa7\x6e\x59\xff\x80" "\x64\xe7\xfa\xcf\x13\x80\x86\xe1\xed\x02\x38\xad\x96\x72\x25\xe5" "\x06\x7a\x9a\xbc\x24\x74\xa9\x75\x55\xb2\x49\x80\x69\x45\x95\x4a" "\x4c\x76\xa9\xe3\x4e\x49\xd3\xc2\x69\x5a\x95\x03\xeb\xba\x72\x23" "\x9c\xfd\x3d\x8b\xc6\x07\x82\x3b\xf4\xf3\xef\x6c\x2e\x9e\x0b\xac" "\x9e\x6c\xbb\x37\x4a\xa1\x9e\x73\xd1\xdc\x97\x61\xba\xfc\xd3\x49" "\xa6\xc2\x4c\x55\x2e\x06\x37\x76\xb5\xef\x57\xe7\x57\x58\x8a\x71" "\x63\xf3\xeb\xe7\x55\x68\x0d\xf6\x46\x4c\xfb\xf9\x43\xbb\x0c\x92" "\x4f\x4e\x22\x7b\x63\xe8\x4f\x9c", 600 } }; static int test_cert(void) { Certificate c, c2; size_t size; size_t i; int ret; for (i = 0; i < sizeof(certs)/sizeof(certs[0]); i++) { ret = decode_Certificate((unsigned char *)certs[i].cert, certs[i].len, &c, &size); if (ret) return ret; ret = copy_Certificate(&c, &c2); free_Certificate(&c); if (ret) return ret; free_Certificate(&c2); } return 0; } static int cmp_TESTLargeTag (void *a, void *b) { TESTLargeTag *aa = a; TESTLargeTag *ab = b; COMPARE_INTEGER(aa,ab,foo); COMPARE_INTEGER(aa,ab,bar); return 0; } static int test_large_tag (void) { struct test_case tests[] = { { NULL, 15, "\x30\x0d\xbf\x7f\x03\x02\x01\x01\xbf\x81\x00\x03\x02\x01\x02", "large tag 1" } }; int ntests = sizeof(tests) / sizeof(*tests); TESTLargeTag lt1; memset(<1, 0, sizeof(lt1)); lt1.foo = 1; lt1.bar = 2; 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, (generic_copy)copy_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; TESTuint32 values[] = {0, 127, 128, 256, 512, 0, 127, 128, 256, 512 }; TESTuint32 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_TESTuint32(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 +check_tag_length64(void) +{ + struct test_data td[] = { + { 1, 3, 3, "\x02\x01\x00"}, + { 1, 7, 7, "\x02\x05\x01\xff\xff\xff\xff"}, + { 1, 7, 7, "\x02\x05\x02\x00\x00\x00\x00"}, + { 1, 9, 9, "\x02\x07\x7f\xff\xff\xff\xff\xff\xff"}, + { 1, 10, 10, "\x02\x08\x00\x80\x00\x00\x00\x00\x00\x00"}, + { 1, 10, 10, "\x02\x08\x7f\xff\xff\xff\xff\xff\xff\xff"}, + { 1, 11, 11, "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff"}, + { 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; + TESTuint64 values[] = {0, 8589934591LL, 8589934592LL, + 36028797018963967LL, 36028797018963968LL, + 9223372036854775807LL, 18446744073709551615ULL, + 0, 127, 128, 256, 512 }; + TESTuint64 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_TESTuint64(buf, td[i].len, &u, &sz); + if (ret) { + if (td[i].ok) { + printf("failed with tag len test %d\n", i); + printf("ret = %d\n", ret); + 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); + printf("sz = %d\n", sz); + failed = 1; + } + if (values[i] != u) { + printf("wrong value for tag test %d\n", i); + printf("Expected value: %lld\nActual value: %lld\n", values[i], u); + failed = 1; + } + } + map_free(page, "test", "decode"); + } + return failed; +} + +static int +check_tag_length64s(void) +{ + struct test_data td[] = { + { 1, 3, 3, "\x02\x01\x00"}, + { 1, 7, 7, "\x02\x05\xfe\x00\x00\x00\x01"}, + { 1, 7, 7, "\x02\x05\xfe\x00\x00\x00\x00"}, + { 1, 9, 9, "\x02\x07\x80\x00\x00\x00\x00\x00\x01"}, + { 1, 9, 9, "\x02\x07\x80\x00\x00\x00\x00\x00\x00"}, + { 1, 10, 10, "\x02\x08\x80\x00\x00\x00\x00\x00\x00\x01"}, + { 1, 9, 9, "\x02\x07\x80\x00\x00\x00\x00\x00\x01"}, + { 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; + TESTint64 values[] = {0, -8589934591LL, -8589934592LL, + -36028797018963967LL, -36028797018963968LL, + -9223372036854775807LL, -36028797018963967LL, + 0, 127, 128, 256, 512 }; + TESTint64 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_TESTint64(buf, td[i].len, &u, &sz); + if (ret) { + if (td[i].ok) { + printf("failed with tag len test %d\n", i); + printf("ret = %d\n", ret); + 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); + printf("sz = %d\n", sz); + failed = 1; + } + if (values[i] != u) { + printf("wrong value for tag test %d\n", i); + printf("Expected value: %lld\nActual value: %lld\n", values[i], u); + 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, (generic_copy)copy_TESTChoice1); 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, (generic_copy)copy_TESTChoice2); return ret; } static int cmp_TESTImplicit (void *a, void *b) { TESTImplicit *aa = a; TESTImplicit *ab = b; COMPARE_INTEGER(aa,ab,ti1); COMPARE_INTEGER(aa,ab,ti2.foo); COMPARE_INTEGER(aa,ab,ti3); return 0; } /* UNIV CONS Sequence 14 CONTEXT PRIM 0 1 00 CONTEXT CONS 1 6 CONTEXT CONS 127 3 UNIV PRIM Integer 1 02 CONTEXT PRIM 2 1 03 */ static int test_implicit (void) { struct test_case tests[] = { { NULL, 16, "\x30\x0e\x80\x01\x00\xa1\x06\xbf" "\x7f\x03\x02\x01\x02\x82\x01\x03", "implicit 1" } }; int ret = 0, ntests = sizeof(tests) / sizeof(*tests); TESTImplicit c0; memset(&c0, 0, sizeof(c0)); c0.ti1 = 0; c0.ti2.foo = 2; c0.ti3 = 3; tests[0].val = &c0; ret += generic_test (tests, ntests, sizeof(TESTImplicit), (generic_encode)encode_TESTImplicit, (generic_length)length_TESTImplicit, (generic_decode)decode_TESTImplicit, (generic_free)free_TESTImplicit, cmp_TESTImplicit, (generic_copy)copy_TESTImplicit); #ifdef IMPLICIT_TAGGING_WORKS ret += generic_test (tests, ntests, sizeof(TESTImplicit2), (generic_encode)encode_TESTImplicit2, (generic_length)length_TESTImplicit2, (generic_decode)decode_TESTImplicit2, (generic_free)free_TESTImplicit2, cmp_TESTImplicit, NULL); #endif /* IMPLICIT_TAGGING_WORKS */ return ret; } static int cmp_TESTAlloc (void *a, void *b) { TESTAlloc *aa = a; TESTAlloc *ab = b; IF_OPT_COMPARE(aa,ab,tagless) { COMPARE_INTEGER(aa,ab,tagless->ai); } COMPARE_INTEGER(aa,ab,three); IF_OPT_COMPARE(aa,ab,tagless2) { COMPARE_OPT_OCTECT_STRING(aa, ab, tagless2); } return 0; } /* UNIV CONS Sequence 12 UNIV CONS Sequence 5 CONTEXT CONS 0 3 UNIV PRIM Integer 1 01 CONTEXT CONS 1 3 UNIV PRIM Integer 1 03 UNIV CONS Sequence 5 CONTEXT CONS 1 3 UNIV PRIM Integer 1 03 UNIV CONS Sequence 8 CONTEXT CONS 1 3 UNIV PRIM Integer 1 04 UNIV PRIM Integer 1 05 */ static int test_taglessalloc (void) { struct test_case tests[] = { { NULL, 14, "\x30\x0c\x30\x05\xa0\x03\x02\x01\x01\xa1\x03\x02\x01\x03", "alloc 1" }, { NULL, 7, "\x30\x05\xa1\x03\x02\x01\x03", "alloc 2" }, { NULL, 10, "\x30\x08\xa1\x03\x02\x01\x04\x02\x01\x05", "alloc 3" } }; int ret = 0, ntests = sizeof(tests) / sizeof(*tests); TESTAlloc c1, c2, c3; heim_any any3; memset(&c1, 0, sizeof(c1)); c1.tagless = ecalloc(1, sizeof(*c1.tagless)); c1.tagless->ai = 1; c1.three = 3; tests[0].val = &c1; memset(&c2, 0, sizeof(c2)); c2.tagless = NULL; c2.three = 3; tests[1].val = &c2; memset(&c3, 0, sizeof(c3)); c3.tagless = NULL; c3.three = 4; c3.tagless2 = &any3; any3.data = "\x02\x01\x05"; any3.length = 3; tests[2].val = &c3; ret += generic_test (tests, ntests, sizeof(TESTAlloc), (generic_encode)encode_TESTAlloc, (generic_length)length_TESTAlloc, (generic_decode)decode_TESTAlloc, (generic_free)free_TESTAlloc, cmp_TESTAlloc, (generic_copy)copy_TESTAlloc); free(c1.tagless); return ret; } static int cmp_TESTOptional (void *a, void *b) { TESTOptional *aa = a; TESTOptional *ab = b; IF_OPT_COMPARE(aa,ab,zero) { COMPARE_OPT_INTEGER(aa,ab,zero); } IF_OPT_COMPARE(aa,ab,one) { COMPARE_OPT_INTEGER(aa,ab,one); } return 0; } /* UNIV CONS Sequence 5 CONTEXT CONS 0 3 UNIV PRIM Integer 1 00 UNIV CONS Sequence 5 CONTEXT CONS 1 3 UNIV PRIM Integer 1 03 UNIV CONS Sequence 10 CONTEXT CONS 0 3 UNIV PRIM Integer 1 00 CONTEXT CONS 1 3 UNIV PRIM Integer 1 01 */ static int test_optional (void) { struct test_case tests[] = { { NULL, 2, "\x30\x00", "optional 0" }, { NULL, 7, "\x30\x05\xa0\x03\x02\x01\x00", "optional 1" }, { NULL, 7, "\x30\x05\xa1\x03\x02\x01\x01", "optional 2" }, { NULL, 12, "\x30\x0a\xa0\x03\x02\x01\x00\xa1\x03\x02\x01\x01", "optional 3" } }; int ret = 0, ntests = sizeof(tests) / sizeof(*tests); TESTOptional c0, c1, c2, c3; int zero = 0; int one = 1; c0.zero = NULL; c0.one = NULL; tests[0].val = &c0; c1.zero = &zero; c1.one = NULL; tests[1].val = &c1; c2.zero = NULL; c2.one = &one; tests[2].val = &c2; c3.zero = &zero; c3.one = &one; tests[3].val = &c3; ret += generic_test (tests, ntests, sizeof(TESTOptional), (generic_encode)encode_TESTOptional, (generic_length)length_TESTOptional, (generic_decode)decode_TESTOptional, (generic_free)free_TESTOptional, cmp_TESTOptional, (generic_copy)copy_TESTOptional); 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"} }; int ntests = sizeof(tests) / sizeof(*tests); return generic_decode_fail(tests, ntests, sizeof(TESTLargeTag), (generic_decode)decode_TESTLargeTag); } 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 too short"} }; int ntests = sizeof(tests) / sizeof(*tests); return generic_decode_fail(tests, ntests, sizeof(TESTSeq), (generic_decode)decode_TESTSeq); } static int check_fail_choice(void) { struct test_case tests[] = { {NULL, 6, "\xa1\x02\x02\x01\x01", "choice one too short"}, {NULL, 6, "\xa1\x03\x02\x02\x01", "choice one too short inner"} }; int ntests = sizeof(tests) / sizeof(*tests); return generic_decode_fail(tests, ntests, sizeof(TESTChoice1), (generic_decode)decode_TESTChoice1); } static int check_seq(void) { TESTSeqOf seq; TESTInteger i; int ret; seq.val = NULL; seq.len = 0; ret = add_TESTSeqOf(&seq, &i); if (ret) { printf("failed adding\n"); goto out; } ret = add_TESTSeqOf(&seq, &i); if (ret) { printf("failed adding\n"); goto out; } ret = add_TESTSeqOf(&seq, &i); if (ret) { printf("failed adding\n"); goto out; } ret = add_TESTSeqOf(&seq, &i); if (ret) { printf("failed adding\n"); goto out; } ret = remove_TESTSeqOf(&seq, seq.len - 1); if (ret) { printf("failed removing\n"); goto out; } ret = remove_TESTSeqOf(&seq, 2); if (ret) { printf("failed removing\n"); goto out; } ret = remove_TESTSeqOf(&seq, 0); if (ret) { printf("failed removing\n"); goto out; } ret = remove_TESTSeqOf(&seq, 0); if (ret) { printf("failed removing\n"); goto out; } ret = remove_TESTSeqOf(&seq, 0); if (ret == 0) { printf("can remove from empty list"); return 1; } if (seq.len != 0) { printf("seq not empty!"); return 1; } free_TESTSeqOf(&seq); ret = 0; out: return ret; } #define test_seq_of(type, ok, ptr) \ { \ heim_octet_string os; \ size_t size; \ type decode; \ ASN1_MALLOC_ENCODE(type, os.data, os.length, ptr, &size, ret); \ if (ret) \ return ret; \ if (os.length != size) \ abort(); \ ret = decode_##type(os.data, os.length, &decode, &size); \ free(os.data); \ if (ret) { \ if (ok) \ return 1; \ } else { \ free_##type(&decode); \ if (!ok) \ return 1; \ if (size != 0) \ return 1; \ } \ return 0; \ } static int check_seq_of_size(void) { #if 0 /* template */ TESTInteger integers[4] = { 1, 2, 3, 4 }; int ret; { TESTSeqSizeOf1 ssof1f1 = { 1, integers }; TESTSeqSizeOf1 ssof1ok1 = { 2, integers }; TESTSeqSizeOf1 ssof1f2 = { 3, integers }; test_seq_of(TESTSeqSizeOf1, 0, &ssof1f1); test_seq_of(TESTSeqSizeOf1, 1, &ssof1ok1); test_seq_of(TESTSeqSizeOf1, 0, &ssof1f2); } { TESTSeqSizeOf2 ssof2f1 = { 0, NULL }; TESTSeqSizeOf2 ssof2ok1 = { 1, integers }; TESTSeqSizeOf2 ssof2ok2 = { 2, integers }; TESTSeqSizeOf2 ssof2f2 = { 3, integers }; test_seq_of(TESTSeqSizeOf2, 0, &ssof2f1); test_seq_of(TESTSeqSizeOf2, 1, &ssof2ok1); test_seq_of(TESTSeqSizeOf2, 1, &ssof2ok2); test_seq_of(TESTSeqSizeOf2, 0, &ssof2f2); } { TESTSeqSizeOf3 ssof3f1 = { 0, NULL }; TESTSeqSizeOf3 ssof3ok1 = { 1, integers }; TESTSeqSizeOf3 ssof3ok2 = { 2, integers }; test_seq_of(TESTSeqSizeOf3, 0, &ssof3f1); test_seq_of(TESTSeqSizeOf3, 1, &ssof3ok1); test_seq_of(TESTSeqSizeOf3, 1, &ssof3ok2); } { TESTSeqSizeOf4 ssof4ok1 = { 0, NULL }; TESTSeqSizeOf4 ssof4ok2 = { 1, integers }; TESTSeqSizeOf4 ssof4ok3 = { 2, integers }; TESTSeqSizeOf4 ssof4f1 = { 3, integers }; test_seq_of(TESTSeqSizeOf4, 1, &ssof4ok1); test_seq_of(TESTSeqSizeOf4, 1, &ssof4ok2); test_seq_of(TESTSeqSizeOf4, 1, &ssof4ok3); test_seq_of(TESTSeqSizeOf4, 0, &ssof4f1); } #endif return 0; } static int check_TESTMechTypeList(void) { TESTMechTypeList tl; unsigned oid1[] = { 1, 2, 840, 48018, 1, 2, 2}; unsigned oid2[] = { 1, 2, 840, 113554, 1, 2, 2}; unsigned oid3[] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 30}; unsigned oid4[] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10}; TESTMechType array[] = {{ 7, oid1 }, { 7, oid2 }, { 10, oid3 }, { 10, oid4 }}; size_t size, len; void *ptr; int ret; tl.len = 4; tl.val = array; ASN1_MALLOC_ENCODE(TESTMechTypeList, ptr, len, &tl, &size, ret); if (ret) errx(1, "TESTMechTypeList: %d", ret); if (len != size) abort(); return 0; } int main(int argc, char **argv) { int ret = 0; ret += test_principal (); ret += test_authenticator(); ret += test_krb_error(); ret += test_Name(); ret += test_bit_string(); ret += test_bit_string_rfc1510(); ret += test_time(); ret += test_cert(); ret += check_tag_length(); + ret += check_tag_length64(); + ret += check_tag_length64s(); ret += test_large_tag(); ret += test_choice(); ret += test_implicit(); ret += test_taglessalloc(); ret += test_optional(); ret += check_fail_largetag(); ret += check_fail_sequence(); ret += check_fail_choice(); ret += check_seq(); ret += check_seq_of_size(); ret += check_TESTMechTypeList(); return ret; } diff --git a/crypto/heimdal/lib/asn1/der-protos.h b/crypto/heimdal/lib/asn1/der-protos.h index 3b3d81d175fb..9ebc78538a9e 100644 --- a/crypto/heimdal/lib/asn1/der-protos.h +++ b/crypto/heimdal/lib/asn1/der-protos.h @@ -1,628 +1,678 @@ /* This is a generated file */ #ifndef __der_protos_h__ #define __der_protos_h__ #include #ifdef __cplusplus extern "C" { #endif int copy_heim_any ( const heim_any */*from*/, heim_any */*to*/); int copy_heim_any_set ( const heim_any_set */*from*/, heim_any_set */*to*/); int decode_heim_any ( const unsigned char */*p*/, size_t /*len*/, heim_any */*data*/, size_t */*size*/); int decode_heim_any_set ( const unsigned char */*p*/, size_t /*len*/, heim_any_set */*data*/, size_t */*size*/); int der_copy_bit_string ( const heim_bit_string */*from*/, heim_bit_string */*to*/); int der_copy_bmp_string ( const heim_bmp_string */*from*/, heim_bmp_string */*to*/); int der_copy_general_string ( const heim_general_string */*from*/, heim_general_string */*to*/); int der_copy_generalized_time ( const time_t */*from*/, time_t */*to*/); int der_copy_heim_integer ( const heim_integer */*from*/, heim_integer */*to*/); int der_copy_ia5_string ( const heim_ia5_string */*from*/, heim_ia5_string */*to*/); int der_copy_integer ( const int */*from*/, int */*to*/); +int +der_copy_integer64 ( + const int64_t */*from*/, + int64_t */*to*/); + int der_copy_octet_string ( const heim_octet_string */*from*/, heim_octet_string */*to*/); int der_copy_oid ( const heim_oid */*from*/, heim_oid */*to*/); int der_copy_printable_string ( const heim_printable_string */*from*/, heim_printable_string */*to*/); int der_copy_universal_string ( const heim_universal_string */*from*/, heim_universal_string */*to*/); int der_copy_unsigned ( const unsigned */*from*/, unsigned */*to*/); +int +der_copy_unsigned64 ( + const uint64_t */*from*/, + uint64_t */*to*/); + int der_copy_utctime ( const time_t */*from*/, time_t */*to*/); int der_copy_utf8string ( const heim_utf8_string */*from*/, heim_utf8_string */*to*/); int der_copy_visible_string ( const heim_visible_string */*from*/, heim_visible_string */*to*/); void der_free_bit_string (heim_bit_string */*k*/); void der_free_bmp_string (heim_bmp_string */*k*/); void der_free_general_string (heim_general_string */*str*/); void der_free_generalized_time (time_t */*t*/); void der_free_heim_integer (heim_integer */*k*/); void der_free_ia5_string (heim_ia5_string */*str*/); void der_free_integer (int */*i*/); +void +der_free_integer64 (int64_t */*i*/); + void der_free_octet_string (heim_octet_string */*k*/); void der_free_oid (heim_oid */*k*/); void der_free_printable_string (heim_printable_string */*str*/); void der_free_universal_string (heim_universal_string */*k*/); void der_free_unsigned (unsigned */*u*/); +void +der_free_unsigned64 (uint64_t */*u*/); + void der_free_utctime (time_t */*t*/); void der_free_utf8string (heim_utf8_string */*str*/); void der_free_visible_string (heim_visible_string */*str*/); int der_get_bit_string ( const unsigned char */*p*/, size_t /*len*/, heim_bit_string */*data*/, size_t */*size*/); int der_get_bmp_string ( const unsigned char */*p*/, size_t /*len*/, heim_bmp_string */*data*/, size_t */*size*/); int der_get_boolean ( const unsigned char */*p*/, size_t /*len*/, int */*data*/, size_t */*size*/); const char * der_get_class_name (unsigned /*num*/); int der_get_class_num (const char */*name*/); int der_get_general_string ( const unsigned char */*p*/, size_t /*len*/, heim_general_string */*str*/, size_t */*size*/); int der_get_generalized_time ( const unsigned char */*p*/, size_t /*len*/, time_t */*data*/, size_t */*size*/); int der_get_heim_integer ( const unsigned char */*p*/, size_t /*len*/, heim_integer */*data*/, 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_integer ( const unsigned char */*p*/, size_t /*len*/, int */*ret*/, size_t */*size*/); +int +der_get_integer64 ( + const unsigned char */*p*/, + size_t /*len*/, + int64_t */*ret*/, + size_t */*size*/); + int der_get_length ( const unsigned char */*p*/, size_t /*len*/, size_t */*val*/, 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_octet_string_ber ( const unsigned char */*p*/, size_t /*len*/, heim_octet_string */*data*/, size_t */*size*/); int der_get_oid ( const unsigned char */*p*/, size_t /*len*/, heim_oid */*data*/, 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_tag ( const unsigned char */*p*/, size_t /*len*/, Der_class */*class*/, Der_type */*type*/, unsigned int */*tag*/, size_t */*size*/); const char * der_get_tag_name (unsigned /*num*/); int der_get_tag_num (const char */*name*/); const char * der_get_type_name (unsigned /*num*/); int der_get_type_num (const char */*name*/); int der_get_universal_string ( const unsigned char */*p*/, size_t /*len*/, heim_universal_string */*data*/, size_t */*size*/); int der_get_unsigned ( const unsigned char */*p*/, size_t /*len*/, unsigned */*ret*/, size_t */*size*/); +int +der_get_unsigned64 ( + const unsigned char */*p*/, + size_t /*len*/, + uint64_t */*ret*/, + size_t */*size*/); + int der_get_utctime ( const unsigned char */*p*/, size_t /*len*/, time_t */*data*/, size_t */*size*/); int der_get_utf8string ( const unsigned char */*p*/, size_t /*len*/, heim_utf8_string */*str*/, size_t */*size*/); int der_get_visible_string ( const unsigned char */*p*/, size_t /*len*/, heim_visible_string */*str*/, size_t */*size*/); int der_heim_bit_string_cmp ( const heim_bit_string */*p*/, const heim_bit_string */*q*/); int der_heim_bmp_string_cmp ( const heim_bmp_string */*p*/, const heim_bmp_string */*q*/); int der_heim_integer_cmp ( const heim_integer */*p*/, const heim_integer */*q*/); int der_heim_octet_string_cmp ( const heim_octet_string */*p*/, const heim_octet_string */*q*/); int der_heim_oid_cmp ( const heim_oid */*p*/, const heim_oid */*q*/); int der_heim_universal_string_cmp ( const heim_universal_string */*p*/, const heim_universal_string */*q*/); int der_ia5_string_cmp ( const heim_ia5_string */*p*/, const heim_ia5_string */*q*/); size_t der_length_bit_string (const heim_bit_string */*k*/); size_t der_length_bmp_string (const heim_bmp_string */*data*/); size_t der_length_boolean (const int */*k*/); size_t der_length_enumerated (const unsigned */*data*/); size_t der_length_general_string (const heim_general_string */*data*/); size_t der_length_generalized_time (const time_t */*t*/); size_t der_length_heim_integer (const heim_integer */*k*/); size_t der_length_ia5_string (const heim_ia5_string */*data*/); size_t der_length_integer (const int */*data*/); +size_t +der_length_integer64 (const int64_t */*data*/); + size_t der_length_len (size_t /*len*/); size_t der_length_octet_string (const heim_octet_string */*k*/); size_t der_length_oid (const heim_oid */*k*/); size_t der_length_printable_string (const heim_printable_string */*data*/); size_t der_length_tag (unsigned int /*tag*/); size_t der_length_universal_string (const heim_universal_string */*data*/); size_t der_length_unsigned (const unsigned */*data*/); +size_t +der_length_unsigned64 (const uint64_t */*data*/); + size_t der_length_utctime (const time_t */*t*/); size_t der_length_utf8string (const heim_utf8_string */*data*/); size_t der_length_visible_string (const heim_visible_string */*data*/); int der_match_tag ( const unsigned char */*p*/, size_t /*len*/, Der_class /*class*/, Der_type /*type*/, unsigned int /*tag*/, size_t */*size*/); int der_match_tag2 ( const unsigned char */*p*/, size_t /*len*/, Der_class /*class*/, Der_type */*type*/, 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*/, unsigned int /*tag*/, size_t */*length_ret*/, size_t */*size*/); int der_parse_heim_oid ( const char */*str*/, const char */*sep*/, heim_oid */*data*/); int der_parse_hex_heim_integer ( const char */*p*/, heim_integer */*data*/); int der_print_heim_oid ( const heim_oid */*oid*/, char /*delim*/, char **/*str*/); int der_print_hex_heim_integer ( const heim_integer */*data*/, char **/*p*/); int der_printable_string_cmp ( const heim_printable_string */*p*/, const heim_printable_string */*q*/); int der_put_bit_string ( unsigned char */*p*/, size_t /*len*/, const heim_bit_string */*data*/, size_t */*size*/); int der_put_bmp_string ( unsigned char */*p*/, size_t /*len*/, const heim_bmp_string */*data*/, size_t */*size*/); int der_put_boolean ( unsigned char */*p*/, size_t /*len*/, const int */*data*/, size_t */*size*/); int der_put_general_string ( unsigned char */*p*/, size_t /*len*/, const heim_general_string */*str*/, size_t */*size*/); int der_put_generalized_time ( unsigned char */*p*/, size_t /*len*/, const time_t */*data*/, size_t */*size*/); int der_put_heim_integer ( unsigned char */*p*/, size_t /*len*/, const heim_integer */*data*/, size_t */*size*/); int der_put_ia5_string ( unsigned char */*p*/, size_t /*len*/, const heim_ia5_string */*str*/, size_t */*size*/); int der_put_integer ( unsigned char */*p*/, size_t /*len*/, const int */*v*/, size_t */*size*/); +int +der_put_integer64 ( + unsigned char */*p*/, + size_t /*len*/, + const int64_t */*v*/, + size_t */*size*/); + int der_put_length ( unsigned char */*p*/, size_t /*len*/, size_t /*val*/, size_t */*size*/); int der_put_length_and_tag ( unsigned char */*p*/, size_t /*len*/, size_t /*len_val*/, Der_class /*class*/, Der_type /*type*/, unsigned int /*tag*/, size_t */*size*/); int der_put_octet_string ( unsigned char */*p*/, size_t /*len*/, const heim_octet_string */*data*/, size_t */*size*/); int der_put_oid ( unsigned char */*p*/, size_t /*len*/, const heim_oid */*data*/, size_t */*size*/); int der_put_printable_string ( unsigned char */*p*/, size_t /*len*/, const heim_printable_string */*str*/, size_t */*size*/); int der_put_tag ( unsigned char */*p*/, size_t /*len*/, Der_class /*class*/, Der_type /*type*/, unsigned int /*tag*/, size_t */*size*/); int der_put_universal_string ( unsigned char */*p*/, size_t /*len*/, const heim_universal_string */*data*/, size_t */*size*/); int der_put_unsigned ( unsigned char */*p*/, size_t /*len*/, const unsigned */*v*/, size_t */*size*/); +int +der_put_unsigned64 ( + unsigned char */*p*/, + size_t /*len*/, + const uint64_t */*v*/, + size_t */*size*/); + int der_put_utctime ( unsigned char */*p*/, size_t /*len*/, const time_t */*data*/, size_t */*size*/); int der_put_utf8string ( unsigned char */*p*/, size_t /*len*/, const heim_utf8_string */*str*/, size_t */*size*/); int der_put_visible_string ( unsigned char */*p*/, size_t /*len*/, const heim_visible_string */*str*/, size_t */*size*/); int encode_heim_any ( unsigned char */*p*/, size_t /*len*/, const heim_any */*data*/, size_t */*size*/); int encode_heim_any_set ( unsigned char */*p*/, size_t /*len*/, const heim_any_set */*data*/, size_t */*size*/); void free_heim_any (heim_any */*data*/); void free_heim_any_set (heim_any_set */*data*/); int heim_any_cmp ( const heim_any_set */*p*/, const heim_any_set */*q*/); size_t length_heim_any (const heim_any */*data*/); size_t length_heim_any_set (const heim_any */*data*/); #ifdef __cplusplus } #endif #endif /* __der_protos_h__ */ diff --git a/crypto/heimdal/lib/asn1/der_copy.c b/crypto/heimdal/lib/asn1/der_copy.c index abaaf8e5d740..4faf87014280 100644 --- a/crypto/heimdal/lib/asn1/der_copy.c +++ b/crypto/heimdal/lib/asn1/der_copy.c @@ -1,185 +1,199 @@ /* * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Portions Copyright (c) 2009 Apple Inc. 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" RCSID("$Id$"); int der_copy_general_string (const heim_general_string *from, heim_general_string *to) { *to = strdup(*from); if(*to == NULL) return ENOMEM; return 0; } int der_copy_integer (const int *from, int *to) { *to = *from; return 0; } +int +der_copy_integer64 (const int64_t *from, int64_t *to) +{ + *to = *from; + return 0; +} + int der_copy_unsigned (const unsigned *from, unsigned *to) { *to = *from; return 0; } +int +der_copy_unsigned64 (const uint64_t *from, uint64_t *to) +{ + *to = *from; + return 0; +} + int der_copy_generalized_time (const time_t *from, time_t *to) { *to = *from; return 0; } int der_copy_utctime (const time_t *from, time_t *to) { *to = *from; return 0; } int der_copy_utf8string (const heim_utf8_string *from, heim_utf8_string *to) { return der_copy_general_string(from, to); } int der_copy_printable_string (const heim_printable_string *from, heim_printable_string *to) { to->length = from->length; to->data = malloc(to->length + 1); if(to->data == NULL) return ENOMEM; memcpy(to->data, from->data, to->length); ((char *)to->data)[to->length] = '\0'; return 0; } int der_copy_ia5_string (const heim_ia5_string *from, heim_ia5_string *to) { return der_copy_printable_string(from, to); } int der_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 der_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 der_copy_visible_string (const heim_visible_string *from, heim_visible_string *to) { return der_copy_general_string(from, to); } int der_copy_octet_string (const heim_octet_string *from, heim_octet_string *to) { to->length = from->length; if (from->data == NULL) { to->data = NULL; return 0; } to->data = malloc(to->length); if (to->length != 0 && to->data == NULL) return ENOMEM; memcpy(to->data, from->data, to->length); return 0; } int der_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); to->negative = from->negative; return 0; } int der_copy_oid (const heim_oid *from, heim_oid *to) { to->length = from->length; to->components = malloc(to->length * sizeof(*to->components)); if (to->length != 0 && to->components == NULL) return ENOMEM; memcpy(to->components, from->components, to->length * sizeof(*to->components)); return 0; } int der_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/crypto/heimdal/lib/asn1/der_free.c b/crypto/heimdal/lib/asn1/der_free.c index 4bae5fc2338f..1584cfcb299e 100644 --- a/crypto/heimdal/lib/asn1/der_free.c +++ b/crypto/heimdal/lib/asn1/der_free.c @@ -1,144 +1,156 @@ /* * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Portions Copyright (c) 2009 Apple Inc. 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" RCSID("$Id$"); void der_free_general_string (heim_general_string *str) { free(*str); *str = NULL; } void der_free_integer (int *i) { *i = 0; } +void +der_free_integer64 (int64_t *i) +{ + *i = 0; +} + void der_free_unsigned (unsigned *u) { *u = 0; } +void +der_free_unsigned64 (uint64_t *u) +{ + *u = 0; +} + void der_free_generalized_time(time_t *t) { *t = 0; } void der_free_utctime(time_t *t) { *t = 0; } void der_free_utf8string (heim_utf8_string *str) { free(*str); *str = NULL; } void der_free_printable_string (heim_printable_string *str) { der_free_octet_string(str); } void der_free_ia5_string (heim_ia5_string *str) { der_free_octet_string(str); } void der_free_bmp_string (heim_bmp_string *k) { free(k->data); k->data = NULL; k->length = 0; } void der_free_universal_string (heim_universal_string *k) { free(k->data); k->data = NULL; k->length = 0; } void der_free_visible_string (heim_visible_string *str) { free(*str); *str = NULL; } void der_free_octet_string (heim_octet_string *k) { free(k->data); k->data = NULL; k->length = 0; } void der_free_heim_integer (heim_integer *k) { free(k->data); k->data = NULL; k->length = 0; } void der_free_oid (heim_oid *k) { free(k->components); k->components = NULL; k->length = 0; } void der_free_bit_string (heim_bit_string *k) { free(k->data); k->data = NULL; k->length = 0; } diff --git a/crypto/heimdal/lib/asn1/der_get.c b/crypto/heimdal/lib/asn1/der_get.c index 3112da86f93b..8a456d4d983d 100644 --- a/crypto/heimdal/lib/asn1/der_get.c +++ b/crypto/heimdal/lib/asn1/der_get.c @@ -1,647 +1,686 @@ /* * Copyright (c) 1997 - 2007 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" /* * All decoding functions take a pointer `p' to first position in * which to read, from the left, `len' which means the maximum number * of characters we are able to read, `ret' were the value will be * returned and `size' where the number of used bytes is stored. * Either 0 or an error code is returned. */ 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) + if (len == sizeof(val) + 1 && p[0] == 0) ; - else if (len > sizeof(unsigned)) + else if (len > sizeof(val)) + return ASN1_OVERRUN; + + while (len--) + val = val * 256 + *p++; + *ret = val; + if(size) *size = oldlen; + return 0; +} + +int +der_get_unsigned64 (const unsigned char *p, size_t len, + uint64_t *ret, size_t *size) +{ + uint64_t val = 0; + size_t oldlen = len; + + if (len == sizeof(val) + 1 && p[0] == 0) + ; + else if (len > sizeof(val)) return ASN1_OVERRUN; while (len--) val = val * 256 + *p++; *ret = val; if(size) *size = oldlen; return 0; } int 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)) + if (len > sizeof(val)) + return ASN1_OVERRUN; + + if (len > 0) { + val = (signed char)*p++; + while (--len) + val = val * 256 + *p++; + } + *ret = val; + if(size) *size = oldlen; + return 0; +} + +int +der_get_integer64 (const unsigned char *p, size_t len, + int64_t *ret, size_t *size) +{ + int64_t val = 0; + size_t oldlen = len; + + if (len > sizeof(val)) return ASN1_OVERRUN; if (len > 0) { val = (signed char)*p++; while (--len) val = val * 256 + *p++; } *ret = val; if(size) *size = oldlen; return 0; } int der_get_length (const unsigned char *p, size_t len, size_t *val, size_t *size) { size_t v; if (len <= 0) return ASN1_OVERRUN; --len; v = *p++; if (v < 128) { *val = v; if(size) *size = 1; } else { int e; size_t l; unsigned tmp; if(v == 0x80){ *val = ASN1_INDEFINITE; if(size) *size = 1; return 0; } v &= 0x7F; if (len < v) return ASN1_OVERRUN; e = der_get_unsigned (p, v, &tmp, &l); if(e) return e; *val = tmp; if(size) *size = l + 1; } 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) { const unsigned char *p1; char *s; p1 = memchr(p, 0, len); if (p1 != NULL) { /* * Allow trailing NULs. We allow this since MIT Kerberos sends * an strings in the NEED_PREAUTH case that includes a * trailing NUL. */ while ((size_t)(p1 - p) < len && *p1 == '\0') p1++; if ((size_t)(p1 - p) != len) return ASN1_BAD_CHARACTER; } if (len > len + 1) return ASN1_BAD_LENGTH; s = malloc (len + 1); if (s == NULL) return ENOMEM; memcpy (s, p, len); s[len] = '\0'; *str = s; if(size) *size = 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) { str->length = len; str->data = malloc(len + 1); if (str->data == NULL) return ENOMEM; memcpy(str->data, p, len); ((char *)str->data)[len] = '\0'; if(size) *size = len; return 0; } int der_get_ia5_string(const unsigned char *p, size_t len, heim_ia5_string *str, size_t *size) { return der_get_printable_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; if (data->length > UINT_MAX/sizeof(data->data[0])) return ERANGE; 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; /* check for NUL in the middle of the string */ if (data->data[i] == 0 && i != (data->length - 1)) { free(data->data); data->data = NULL; data->length = 0; return ASN1_BAD_CHARACTER; } } 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; if (data->length > UINT_MAX/sizeof(data->data[0])) return ERANGE; 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; /* check for NUL in the middle of the string */ if (data->data[i] == 0 && i != (data->length - 1)) { free(data->data); data->data = NULL; data->length = 0; return ASN1_BAD_CHARACTER; } } if (size) *size = len; return 0; } int der_get_visible_string (const unsigned char *p, size_t len, heim_visible_string *str, size_t *size) { return der_get_general_string(p, len, str, size); } int der_get_octet_string (const unsigned char *p, size_t len, heim_octet_string *data, size_t *size) { data->length = len; data->data = malloc(len); if (data->data == NULL && data->length != 0) return ENOMEM; memcpy (data->data, p, len); if(size) *size = len; return 0; } int der_get_octet_string_ber (const unsigned char *p, size_t len, heim_octet_string *data, size_t *size) { int e; Der_type type; Der_class class; unsigned int tag, depth = 0; size_t l, datalen, oldlen = len; data->length = 0; data->data = NULL; while (len) { e = der_get_tag (p, len, &class, &type, &tag, &l); if (e) goto out; if (class != ASN1_C_UNIV) { e = ASN1_BAD_ID; goto out; } if (type == PRIM && tag == UT_EndOfContent) { if (depth == 0) break; depth--; } if (tag != UT_OctetString) { e = ASN1_BAD_ID; goto out; } p += l; len -= l; e = der_get_length (p, len, &datalen, &l); if (e) goto out; p += l; len -= l; if (datalen > len) return ASN1_OVERRUN; if (type == PRIM) { void *ptr; ptr = realloc(data->data, data->length + datalen); if (ptr == NULL) { e = ENOMEM; goto out; } data->data = ptr; memcpy(((unsigned char *)data->data) + data->length, p, datalen); data->length += datalen; } else depth++; p += datalen; len -= datalen; } if (depth != 0) return ASN1_INDEF_OVERRUN; if(size) *size = oldlen - len; return 0; out: free(data->data); data->data = NULL; data->length = 0; return e; } 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) { unsigned char *q; int carry = 1; data->negative = 1; data->length = len; if (p[0] == 0xff) { p++; data->length--; } data->data = malloc(data->length); if (data->data == NULL) { data->length = 0; if (size) *size = 0; return ENOMEM; } q = &((unsigned char*)data->data)[data->length - 1]; p += data->length - 1; while (q >= (unsigned char*)data->data) { *q = *p ^ 0xff; if (carry) carry = !++*q; p--; q--; } } else { data->negative = 0; data->length = len; if (p[0] == 0) { p++; data->length--; } data->data = malloc(data->length); if (data->data == NULL && data->length != 0) { data->length = 0; if (size) *size = 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 = _der_timegm (&tm); return 0; } static int der_get_time (const unsigned char *p, size_t len, time_t *data, size_t *size) { char *times; int e; if (len > len + 1 || len == 0) return ASN1_BAD_LENGTH; times = malloc(len + 1); if (times == NULL) return ENOMEM; memcpy(times, p, len); times[len] = '\0'; e = generalizedtime2time(times, data); free (times); if(size) *size = len; 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) { size_t n; size_t oldlen = len; if (len < 1) return ASN1_OVERRUN; if (len > len + 1) return ASN1_BAD_LENGTH; if (len + 1 > UINT_MAX/sizeof(data->components[0])) return ERANGE; data->components = malloc((len + 1) * sizeof(data->components[0])); if (data->components == NULL) return ENOMEM; data->components[0] = (*p) / 40; data->components[1] = (*p) % 40; --len; ++p; for (n = 2; len > 0; ++n) { unsigned u = 0, u1; do { --len; u1 = u * 128 + (*p++ % 128); /* check that we don't overflow the element */ if (u1 < u) { der_free_oid(data); return ASN1_OVERRUN; } u = u1; } while (len > 0 && p[-1] & 0x80); data->components[n] = u; } if (n > 2 && p[-1] & 0x80) { der_free_oid (data); return ASN1_OVERRUN; } data->length = n; if (size) *size = oldlen; return 0; } int der_get_tag (const unsigned char *p, size_t len, Der_class *class, Der_type *type, 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; 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, unsigned int tag, size_t *size) { Der_type thistype; int e; e = der_match_tag2(p, len, class, &thistype, tag, size); if (e) return e; if (thistype != type) return ASN1_BAD_ID; return 0; } int der_match_tag2 (const unsigned char *p, size_t len, Der_class class, Der_type *type, unsigned int tag, size_t *size) { size_t l; Der_class thisclass; unsigned int thistag; int e; e = der_get_tag (p, len, &thisclass, type, &thistag, &l); if (e) return e; if (class != thisclass) return ASN1_BAD_ID; if(tag > thistag) return ASN1_MISPLACED_FIELD; if(tag < thistag) return ASN1_MISSING_FIELD; if(size) *size = l; return 0; } int der_match_tag_and_length (const unsigned char *p, size_t len, Der_class class, Der_type *type, unsigned int tag, size_t *length_ret, size_t *size) { size_t l, ret = 0; int e; e = der_match_tag2 (p, len, class, type, tag, &l); if (e) return e; p += l; len -= l; ret += l; e = der_get_length (p, len, length_ret, &l); if (e) return e; if(size) *size = ret + l; 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 _heim_fix_dce(size_t reallen, size_t *len) { if(reallen == ASN1_INDEFINITE) return 1; if(*len < reallen) return -1; *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; /* check if any of the three upper bits are set * any of them will cause a interger overrun */ if ((len - 1) >> (sizeof(len) * 8 - 3)) return ASN1_OVERRUN; data->length = (len - 1) * 8; data->data = malloc(len - 1); if (data->data == NULL && (len - 1) != 0) return ENOMEM; /* copy data is there is data to copy */ if (len - 1 != 0) { memcpy (data->data, p + 1, len - 1); data->length -= p[0]; } if(size) *size = len; return 0; } diff --git a/crypto/heimdal/lib/asn1/der_length.c b/crypto/heimdal/lib/asn1/der_length.c index db82025861ea..684ba9bc6f32 100644 --- a/crypto/heimdal/lib/asn1/der_length.c +++ b/crypto/heimdal/lib/asn1/der_length.c @@ -1,248 +1,305 @@ /* * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Portions Copyright (c) 2009 Apple Inc. 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" RCSID("$Id$"); 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; } +size_t +_heim_len_unsigned64 (uint64_t 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; +} + size_t _heim_len_int (int val) { unsigned char q; size_t ret = 0; if (val >= 0) { do { q = val % 256; ret++; val /= 256; } while(val); if(q >= 128) ret++; } else { val = ~val; do { q = ~(val % 256); ret++; val /= 256; } while(val); if(q < 128) ret++; } return ret; } +size_t +_heim_len_int64 (int64_t val) +{ + unsigned char q; + size_t ret = 0; + + if (val >= 0) { + do { + q = val % 256; + ret++; + val /= 256; + } while(val); + if(q >= 128) + ret++; + } else { + val = ~val; + do { + q = ~(val % 256); + ret++; + val /= 256; + } while(val); + if(q < 128) + ret++; + } + return ret; +} + static size_t len_oid (const heim_oid *oid) { size_t ret = 1; size_t n; for (n = 2; n < oid->length; ++n) { unsigned u = oid->components[n]; do { ++ret; u /= 128; } while(u > 0); } return ret; } size_t der_length_len (size_t len) { if (len < 128) return 1; else { int ret = 0; do { ++ret; len /= 256; } while (len); return ret + 1; } } size_t der_length_tag(unsigned int tag) { size_t len = 0; if(tag <= 30) return 1; while(tag) { tag /= 128; len++; } return len + 1; } size_t der_length_integer (const int *data) { return _heim_len_int (*data); } +size_t +der_length_integer64 (const int64_t *data) +{ + return _heim_len_int64 (*data); +} + size_t der_length_unsigned (const unsigned *data) { return _heim_len_unsigned(*data); } +size_t +der_length_unsigned64 (const uint64_t *data) +{ + return _heim_len_unsigned64(*data); +} + size_t der_length_enumerated (const unsigned *data) { return _heim_len_int (*data); } size_t der_length_general_string (const heim_general_string *data) { return strlen(*data); } size_t der_length_utf8string (const heim_utf8_string *data) { return strlen(*data); } size_t der_length_printable_string (const heim_printable_string *data) { return data->length; } size_t der_length_ia5_string (const heim_ia5_string *data) { return data->length; } size_t der_length_bmp_string (const heim_bmp_string *data) { return data->length * 2; } size_t der_length_universal_string (const heim_universal_string *data) { return data->length * 4; } size_t der_length_visible_string (const heim_visible_string *data) { return strlen(*data); } size_t der_length_octet_string (const heim_octet_string *k) { return k->length; } size_t der_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 der_length_oid (const heim_oid *k) { return len_oid (k); } size_t der_length_generalized_time (const time_t *t) { heim_octet_string k; size_t ret; _heim_time2generalizedtime (*t, &k, 1); ret = k.length; free(k.data); return ret; } size_t der_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 der_length_boolean (const int *k) { return 1; } size_t der_length_bit_string (const heim_bit_string *k) { return (k->length + 7) / 8 + 1; } diff --git a/crypto/heimdal/lib/asn1/der_put.c b/crypto/heimdal/lib/asn1/der_put.c index 0b276d1ebdce..0ccb181c0b39 100644 --- a/crypto/heimdal/lib/asn1/der_put.c +++ b/crypto/heimdal/lib/asn1/der_put.c @@ -1,479 +1,551 @@ /* * 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" RCSID("$Id$"); /* * All encoding functions take a pointer `p' to first position in * which to write, from the right, `len' which means the maximum * number of characters we are able to write. The function returns * the number of characters written in `size' (if non-NULL). * The return value is 0 or an error. */ 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) { *p-- = val % 256; val /= 256; --len; } if (val != 0) return ASN1_OVERFLOW; else { if(p[1] >= 128) { if(len < 1) return ASN1_OVERFLOW; *p-- = 0; } *size = base - p; return 0; } } else if (len < 1) return ASN1_OVERFLOW; else { *p = 0; *size = 1; return 0; } } +int +der_put_unsigned64 (unsigned char *p, size_t len, const uint64_t *v, size_t *size) +{ + unsigned char *base = p; + uint64_t val = *v; + + if (val) { + while (len > 0 && val) { + *p-- = val % 256; + val /= 256; + --len; + } + if (val != 0) + return ASN1_OVERFLOW; + else { + if(p[1] >= 128) { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = 0; + } + *size = base - p; + return 0; + } + } else if (len < 1) + return ASN1_OVERFLOW; + else { + *p = 0; + *size = 1; + return 0; + } +} + int 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 { if(len < 1) return ASN1_OVERFLOW; *p-- = val % 256; len--; val /= 256; } while(val); if(p[1] >= 128) { if(len < 1) return ASN1_OVERFLOW; *p-- = 0; len--; } } else { val = ~val; do { if(len < 1) return ASN1_OVERFLOW; *p-- = ~(val % 256); len--; val /= 256; } while(val); if(p[1] < 128) { if(len < 1) return ASN1_OVERFLOW; *p-- = 0xff; len--; } } *size = base - p; return 0; } +int +der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size) +{ + unsigned char *base = p; + int64_t val = *v; + + if(val >= 0) { + do { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = val % 256; + len--; + val /= 256; + } while(val); + if(p[1] >= 128) { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = 0; + len--; + } + } else { + val = ~val; + do { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = ~(val % 256); + len--; + val /= 256; + } while(val); + if(p[1] < 128) { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = 0xff; + len--; + } + } + *size = base - p; + return 0; +} + int 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; } else { size_t l = 0; while(val > 0) { if(len < 2) return ASN1_OVERFLOW; *p-- = val % 256; val /= 256; len--; l++; } *p = 0x80 | l; if(size) *size = l + 1; } return 0; } int der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size) { if(len < 1) return ASN1_OVERFLOW; if(*data != 0) *p = 0xff; else *p = 0; *size = 1; return 0; } int der_put_general_string (unsigned char *p, size_t len, const heim_general_string *str, size_t *size) { size_t slen = strlen(*str); if (len < slen) return ASN1_OVERFLOW; p -= slen; memcpy (p+1, *str, slen); *size = slen; 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_octet_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_octet_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; 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; 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_visible_string (unsigned char *p, size_t len, const heim_visible_string *str, size_t *size) { return der_put_general_string(p, len, str, size); } int der_put_octet_string (unsigned char *p, size_t len, const heim_octet_string *data, size_t *size) { if (len < data->length) return ASN1_OVERFLOW; p -= data->length; memcpy (p+1, data->data, data->length); *size = data->length; 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) { unsigned char *base = p; int n; for (n = data->length - 1; n >= 2; --n) { unsigned u = data->components[n]; if (len < 1) return ASN1_OVERFLOW; *p-- = u % 128; u /= 128; --len; while (u > 0) { if (len < 1) return ASN1_OVERFLOW; *p-- = 128 + u % 128; u /= 128; --len; } } if (len < 1) return ASN1_OVERFLOW; *p-- = 40 * data->components[0] + data->components[1]; *size = base - p; return 0; } int der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, unsigned int tag, size_t *size) { 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, unsigned int tag, size_t *size) { size_t ret = 0; size_t l; int e; e = der_put_length (p, len, len_val, &l); if(e) return e; p -= l; len -= l; ret += l; e = der_put_tag (p, len, class, type, tag, &l); if(e) return e; ret += l; *size = ret; return 0; } int _heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep) { struct tm tm; const size_t len = gtimep ? 15 : 13; s->data = malloc(len + 1); if (s->data == NULL) return ENOMEM; s->length = len; if (_der_gmtime(t, &tm) == NULL) return ASN1_BAD_TIMEFORMAT; 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 der_put_bit_string (unsigned char *p, size_t len, const heim_bit_string *data, size_t *size) { size_t data_size = (data->length + 7) / 8; if (len < data_size + 1) return ASN1_OVERFLOW; p -= 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/crypto/heimdal/lib/asn1/gen.c b/crypto/heimdal/lib/asn1/gen.c index 2194b329ce1d..76a893c5ade7 100644 --- a/crypto/heimdal/lib/asn1/gen.c +++ b/crypto/heimdal/lib/asn1/gen.c @@ -1,1054 +1,1056 @@ /* * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Portions Copyright (c) 2009 Apple Inc. 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 "gen_locl.h" RCSID("$Id$"); FILE *privheaderfile, *headerfile, *codefile, *logfile, *templatefile; #define STEM "asn1" static const char *orig_filename; static char *privheader, *header, *template; static const char *headerbase = STEM; /* * list of all IMPORTs */ struct import { const char *module; struct import *next; }; static struct import *imports = NULL; void add_import (const char *module) { struct import *tmp = emalloc (sizeof(*tmp)); tmp->module = module; tmp->next = imports; imports = tmp; fprintf (headerfile, "#include <%s_asn1.h>\n", module); } /* * List of all exported symbols */ struct sexport { const char *name; int defined; struct sexport *next; }; static struct sexport *exports = NULL; void add_export (const char *name) { struct sexport *tmp = emalloc (sizeof(*tmp)); tmp->name = name; tmp->next = exports; exports = tmp; } int is_export(const char *name) { struct sexport *tmp; if (exports == NULL) /* no export list, all exported */ return 1; for (tmp = exports; tmp != NULL; tmp = tmp->next) { if (strcmp(tmp->name, name) == 0) { tmp->defined = 1; return 1; } } return 0; } const char * get_filename (void) { return orig_filename; } void init_generate (const char *filename, const char *base) { char *fn = NULL; orig_filename = filename; if (base != NULL) { headerbase = strdup(base); if (headerbase == NULL) errx(1, "strdup"); } /* public header file */ if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL) errx(1, "malloc"); if (asprintf(&fn, "%s.hx", headerbase) < 0 || fn == NULL) errx(1, "malloc"); headerfile = fopen (fn, "w"); if (headerfile == NULL) err (1, "open %s", fn); free(fn); fn = NULL; /* private header file */ if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL) errx(1, "malloc"); if (asprintf(&fn, "%s-priv.hx", headerbase) < 0 || fn == NULL) errx(1, "malloc"); privheaderfile = fopen (fn, "w"); if (privheaderfile == NULL) err (1, "open %s", fn); free(fn); fn = NULL; /* template file */ if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL) errx(1, "malloc"); fprintf (headerfile, "/* Generated from %s */\n" "/* Do not edit */\n\n", filename); fprintf (headerfile, "#ifndef __%s_h__\n" "#define __%s_h__\n\n", headerbase, headerbase); fprintf (headerfile, "#include \n" "#include \n\n"); 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" " void *data;\n" "} heim_octet_string;\n\n"); fprintf (headerfile, "typedef char *heim_general_string;\n\n" ); fprintf (headerfile, "typedef char *heim_utf8_string;\n\n" ); fprintf (headerfile, "typedef struct heim_octet_string heim_printable_string;\n\n" ); fprintf (headerfile, "typedef struct heim_octet_string 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 char *heim_visible_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"); fprintf (headerfile, "typedef struct heim_octet_string heim_any;\n" "typedef struct heim_octet_string heim_any_set;\n\n"); fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n" " do { \\\n" " (BL) = length_##T((S)); \\\n" " (B) = malloc((BL)); \\\n" " if((B) == NULL) { \\\n" " (R) = ENOMEM; \\\n" " } else { \\\n" " (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n" " (S), (L)); \\\n" " if((R) != 0) { \\\n" " free((B)); \\\n" " (B) = NULL; \\\n" " } \\\n" " } \\\n" " } while (0)\n\n", headerfile); fputs("#ifdef _WIN32\n" "#ifndef ASN1_LIB\n" "#define ASN1EXP __declspec(dllimport)\n" "#else\n" "#define ASN1EXP\n" "#endif\n" "#define ASN1CALL __stdcall\n" "#else\n" "#define ASN1EXP\n" "#define ASN1CALL\n" "#endif\n", headerfile); fprintf (headerfile, "struct units;\n\n"); fprintf (headerfile, "#endif\n\n"); if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL) errx(1, "malloc"); logfile = fopen(fn, "w"); if (logfile == NULL) err (1, "open %s", fn); /* if one code file, write into the one codefile */ if (one_code_file) return; templatefile = fopen (template, "w"); if (templatefile == NULL) err (1, "open %s", template); fprintf (templatefile, "/* Generated from %s */\n" "/* Do not edit */\n\n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n", filename); fprintf (templatefile, "#include <%s>\n" "#include <%s>\n" "#include \n" "#include \n" "#include \n", header, privheader); } void close_generate (void) { fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase); if (headerfile) fclose (headerfile); if (privheaderfile) fclose (privheaderfile); if (templatefile) fclose (templatefile); if (logfile) fprintf (logfile, "\n"); fclose (logfile); } void gen_assign_defval(const char *var, struct value *val) { switch(val->type) { case stringvalue: fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue); break; case integervalue: - fprintf(codefile, "%s = %d;\n", var, val->u.integervalue); + fprintf(codefile, "%s = %" PRId64 ";\n", var, val->u.integervalue); break; case booleanvalue: if(val->u.booleanvalue) fprintf(codefile, "%s = TRUE;\n", var); else fprintf(codefile, "%s = FALSE;\n", var); break; default: abort(); } } void 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); + fprintf(codefile, "if(%s != %" PRId64 ")\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(); } } void generate_header_of_codefile(const char *name) { char *filename = NULL; if (codefile != NULL) abort(); if (asprintf (&filename, "%s_%s.x", STEM, name) < 0 || filename == NULL) errx(1, "malloc"); codefile = fopen (filename, "w"); if (codefile == NULL) err (1, "fopen %s", filename); fprintf(logfile, "%s ", filename); free(filename); filename = NULL; fprintf (codefile, "/* Generated from %s */\n" "/* Do not edit */\n\n" "#define ASN1_LIB\n\n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n", orig_filename); fprintf (codefile, "#include <%s>\n" "#include <%s>\n", header, privheader); fprintf (codefile, "#include \n" "#include \n" "#include \n" "#include \n" "#include \n\n"); } 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", + fprintf (headerfile, "enum { %s = %" PRId64 " };\n\n", s->gen_name, s->value->u.integervalue); break; case nullvalue: break; case stringvalue: break; case objectidentifiervalue: { struct objid *o, **list; unsigned int i, len; char *gen_upper; if (!one_code_file) generate_header_of_codefile(s->gen_name); len = 0; for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next) len++; if (len == 0) { printf("s->gen_name: %s",s->gen_name); fflush(stdout); break; } 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 ; i > 0; i--) { o = list[i - 1]; fprintf(headerfile, "%s(%d) ", o->label ? o->label : "label-less", o->value); } fprintf (codefile, "static unsigned oid_%s_variable_num[%d] = {", s->gen_name, len); for (i = len ; i > 0; i--) { fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : ""); } fprintf(codefile, "};\n"); fprintf (codefile, "const heim_oid asn1_oid_%s = " "{ %d, oid_%s_variable_num };\n\n", s->gen_name, len, s->gen_name); free(list); /* header file */ gen_upper = strdup(s->gen_name); len = strlen(gen_upper); for (i = 0; i < len; i++) gen_upper[i] = toupper((int)s->gen_name[i]); fprintf (headerfile, "} */\n"); fprintf (headerfile, "extern ASN1EXP const heim_oid asn1_oid_%s;\n" "#define ASN1_OID_%s (&asn1_oid_%s)\n\n", s->gen_name, gen_upper, s->gen_name); free(gen_upper); if (!one_code_file) close_codefile(); break; } default: abort(); } } int is_primitive_type(int type) { switch(type) { case TInteger: case TBoolean: case TOctetString: case TBitString: case TEnumerated: case TGeneralizedTime: case TGeneralString: case TTeletexString: case TOID: case TUTCTime: case TUTF8String: case TPrintableString: case TIA5String: case TBMPString: case TUniversalString: case TVisibleString: case TNull: return 1; default: return 0; } } static void space(int level) { while(level-- > 0) fprintf(headerfile, " "); } static const 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)", + fprintf (headerfile, " (%" PRId64 "..%" PRId64 ")", 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 TTeletexString: fprintf (headerfile, "TeletexString"); 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 TVisibleString: space(level); fprintf (headerfile, "VisibleString"); break; case TOID : space(level); fprintf(headerfile, "OBJECT IDENTIFIER"); break; case TNull: space(level); fprintf (headerfile, "NULL"); break; default: abort (); } } static void getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name) { if (typedefp) *newbasename = strdup(name); else { if (name[0] == '*') name++; if (asprintf(newbasename, "%s_%s", basename, name) < 0) errx(1, "malloc"); } if (*newbasename == NULL) err(1, "malloc"); } static void define_type (int level, const char *name, const char *basename, Type *t, int typedefp, int preservep) { char *newbasename = NULL; 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) { + } else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) { + fprintf (headerfile, "int64_t %s;\n", name); + } else if (t->range->min >= 0 && t->range->max > UINT_MAX) { + fprintf (headerfile, "uint64_t %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) { + } else if (t->range->min >= 0 && t->range->max <= UINT_MAX) { fprintf (headerfile, "unsigned int %s;\n", name); } else - errx(1, "%s: unsupported range %d -> %d", + errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64 "", 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; i.constraint = NULL; space(level); if(ASN1_TAILQ_EMPTY(t->members)) fprintf (headerfile, "heim_bit_string %s;\n", name); else { int pos = 0; getnewbasename(&newbasename, typedefp, basename, name); fprintf (headerfile, "struct %s {\n", newbasename); ASN1_TAILQ_FOREACH(m, t->members, members) { char *n = NULL; /* pad unused */ while (pos < m->val) { if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) errx(1, "malloc"); define_type (level + 1, n, newbasename, &i, FALSE, FALSE); free(n); pos++; } n = NULL; if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL) errx(1, "malloc"); define_type (level + 1, n, newbasename, &i, FALSE, FALSE); free (n); n = NULL; pos++; } /* pad to 32 elements */ while (pos < 32) { char *n = NULL; if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) errx(1, "malloc"); define_type (level + 1, n, newbasename, &i, FALSE, FALSE); free(n); pos++; } 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; getnewbasename(&newbasename, typedefp, basename, name); space(level); fprintf (headerfile, "struct %s {\n", newbasename); 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 = NULL; if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL) errx(1, "malloc"); define_type (level + 1, n, newbasename, m->type, FALSE, FALSE); free (n); } else define_type (level + 1, m->gen_name, newbasename, m->type, FALSE, FALSE); } space(level); fprintf (headerfile, "} %s;\n", name); break; } case TSetOf: case TSequenceOf: { Type i; struct range range = { 0, INT_MAX }; getnewbasename(&newbasename, typedefp, basename, name); i.type = TInteger; i.range = ⦥ i.members = NULL; i.constraint = NULL; space(level); fprintf (headerfile, "struct %s {\n", newbasename); define_type (level + 1, "len", newbasename, &i, FALSE, FALSE); define_type (level + 1, "*val", newbasename, 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 TTeletexString: space(level); fprintf (headerfile, "heim_general_string %s;\n", name); break; case TTag: define_type (level, name, basename, t->subtype, typedefp, preservep); break; case TChoice: { int first = 1; Member *m; getnewbasename(&newbasename, typedefp, basename, name); space(level); fprintf (headerfile, "struct %s {\n", newbasename); 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 = NULL; if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL) errx(1, "malloc"); define_type (level + 2, n, newbasename, m->type, FALSE, FALSE); free (n); } else define_type (level + 2, m->gen_name, newbasename, 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 TVisibleString: space(level); fprintf (headerfile, "heim_visible_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 (); } if (newbasename) free(newbasename); } 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->gen_name, s->type, TRUE, preservep); fprintf (headerfile, "\n"); } void generate_type (const Symbol *s) { FILE *h; const char * exp; if (!one_code_file) generate_header_of_codefile(s->gen_name); generate_type_header (s); if (template_flag) generate_template(s); if (template_flag == 0 || is_template_compat(s) == 0) { generate_type_encode (s); generate_type_decode (s); generate_type_free (s); generate_type_length (s); generate_type_copy (s); } generate_type_seq (s); generate_glue (s->type, s->gen_name); /* generate prototypes */ if (is_export(s->name)) { h = headerfile; exp = "ASN1EXP "; } else { h = privheaderfile; exp = ""; } fprintf (h, "%sint ASN1CALL " "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n", exp, s->gen_name, s->gen_name); fprintf (h, "%sint ASN1CALL " "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n", exp, s->gen_name, s->gen_name); fprintf (h, "%ssize_t ASN1CALL length_%s(const %s *);\n", exp, s->gen_name, s->gen_name); fprintf (h, "%sint ASN1CALL copy_%s (const %s *, %s *);\n", exp, s->gen_name, s->gen_name, s->gen_name); fprintf (h, "%svoid ASN1CALL free_%s (%s *);\n", exp, s->gen_name, s->gen_name); fprintf(h, "\n\n"); if (!one_code_file) { fprintf(codefile, "\n\n"); close_codefile(); } } diff --git a/crypto/heimdal/lib/asn1/gen_decode.c b/crypto/heimdal/lib/asn1/gen_decode.c index bf2d93b806df..c821ee1481a7 100644 --- a/crypto/heimdal/lib/asn1/gen_decode.c +++ b/crypto/heimdal/lib/asn1/gen_decode.c @@ -1,731 +1,733 @@ /* * Copyright (c) 1997 - 2006 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 "gen_locl.h" #include "lex.h" RCSID("$Id$"); static void decode_primitive (const char *typename, const char *name, const char *forwstr) { #if 0 fprintf (codefile, "e = decode_%s(p, len, %s, &l);\n" "%s;\n", typename, 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 void find_tag (const Type *t, Der_class *cl, Der_type *ty, unsigned *tag) { switch (t->type) { case TBitString: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_BitString; break; 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 TTeletexString: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_TeletexString; 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: if ((t->symbol->stype == Stype && t->symbol->type == NULL) || t->symbol->stype == SUndefined) { lex_error_message("%s is imported or still undefined, " " can't generate tag checking data in CHOICE " "without this information", t->symbol->name); exit(1); } find_tag(t->symbol->type, cl, ty, tag); return; 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; case TVisibleString: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_VisibleString; break; default: abort(); } } static void range_check(const char *name, const char *length, const char *forwstr, struct range *r) { if (r->min == r->max + 2 || r->min < r->max) fprintf (codefile, - "if ((%s)->%s > %d) {\n" + "if ((%s)->%s > %" PRId64 ") {\n" "e = ASN1_MAX_CONSTRAINT; %s;\n" "}\n", name, length, r->max, forwstr); if (r->min - 1 == r->max || r->min < r->max) fprintf (codefile, - "if ((%s)->%s < %d) {\n" + "if ((%s)->%s < %" PRId64 ") {\n" "e = ASN1_MIN_CONSTRAINT; %s;\n" "}\n", name, length, r->min, forwstr); if (r->max == r->min) fprintf (codefile, - "if ((%s)->%s != %d) {\n" + "if ((%s)->%s != %" PRId64 ") {\n" "e = ASN1_EXACT_CONSTRAINT; %s;\n" "}\n", name, length, r->min, forwstr); } static int decode_type (const char *name, const Type *t, int optional, const char *forwstr, const char *tmpstr, const char *dertype, unsigned int depth) { 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 TInteger: if(t->members) { fprintf(codefile, "{\n" "int enumint;\n"); decode_primitive ("integer", "&enumint", forwstr); fprintf(codefile, "*%s = enumint;\n" "}\n", name); } else if (t->range == NULL) { decode_primitive ("heim_integer", name, forwstr); - } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { + } else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) { + decode_primitive ("integer64", name, forwstr); + } else if (t->range->min >= 0 && t->range->max > UINT_MAX) { + decode_primitive ("unsigned64", 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) { + } else if (t->range->min >= 0 && t->range->max <= UINT_MAX) { decode_primitive ("unsigned", name, forwstr); } else - errx(1, "%s: unsupported range %d -> %d", + errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64, name, t->range->min, t->range->max); break; case TBoolean: decode_primitive ("boolean", name, forwstr); break; case TEnumerated: decode_primitive ("enumerated", name, forwstr); break; case TOctetString: if (dertype) { fprintf(codefile, "if (%s == CONS) {\n", dertype); decode_primitive("octet_string_ber", name, forwstr); fprintf(codefile, "} else {\n"); } decode_primitive ("octet_string", name, forwstr); if (dertype) fprintf(codefile, "}\n"); if (t->range) range_check(name, "length", forwstr, t->range); break; case TBitString: { Member *m; int pos = 0; 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--; ret++;\n" "if (len < 1) break;\n"); pos += 8; } fprintf (codefile, "(%s)->%s = (*p >> %d) & 1;\n", name, m->gen_name, 7 - m->val % 8); } fprintf(codefile, "} while(0);\n"); fprintf (codefile, "p += len; ret += len;\n"); break; } case TSequence: { Member *m; if (t->members == NULL) break; ASN1_TAILQ_FOREACH(m, t->members, members) { char *s = NULL; if (m->ellipsis) continue; if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL) errx(1, "malloc"); decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL, depth + 1); free (s); } 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)); if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || 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, m->gen_name, NULL, depth + 1); 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; if (asprintf (&s, "%s->%s", name, m->gen_name) < 0 || 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 = NULL; char *sname = NULL; fprintf (codefile, "{\n" "size_t %s_origlen = len;\n" "size_t %s_oldret = ret;\n" "size_t %s_olen = 0;\n" "void *%s_tmp;\n" "ret = 0;\n" "(%s)->len = 0;\n" "(%s)->val = NULL;\n", tmpstr, tmpstr, tmpstr, tmpstr, name, name); fprintf (codefile, "while(ret < %s_origlen) {\n" "size_t %s_nlen = %s_olen + sizeof(*((%s)->val));\n" "if (%s_olen > %s_nlen) { e = ASN1_OVERFLOW; %s; }\n" "%s_olen = %s_nlen;\n" "%s_tmp = realloc((%s)->val, %s_olen);\n" "if (%s_tmp == NULL) { e = ENOMEM; %s; }\n" "(%s)->val = %s_tmp;\n", tmpstr, tmpstr, tmpstr, name, tmpstr, tmpstr, forwstr, tmpstr, tmpstr, tmpstr, name, tmpstr, tmpstr, forwstr, name, tmpstr); if (asprintf (&n, "&(%s)->val[(%s)->len]", name, name) < 0 || n == NULL) errx(1, "malloc"); if (asprintf (&sname, "%s_s_of", tmpstr) < 0 || sname == NULL) errx(1, "malloc"); decode_type (n, t->subtype, 0, forwstr, sname, NULL, depth + 1); fprintf (codefile, "(%s)->len++;\n" "len = %s_origlen - ret;\n" "}\n" "ret += %s_oldret;\n" "}\n", name, tmpstr, tmpstr); if (t->range) range_check(name, "len", forwstr, t->range); free (n); free (sname); break; } case TGeneralizedTime: decode_primitive ("generalized_time", name, forwstr); break; case TGeneralString: decode_primitive ("general_string", name, forwstr); break; case TTeletexString: decode_primitive ("general_string", name, forwstr); break; case TTag:{ char *tname = NULL, *typestring = NULL; char *ide = NULL; if (asprintf(&typestring, "%s_type", tmpstr) < 0 || typestring == NULL) errx(1, "malloc"); fprintf(codefile, "{\n" "size_t %s_datalen, %s_oldlen;\n" "Der_type %s;\n", tmpstr, tmpstr, typestring); if(support_ber) fprintf(codefile, "int is_indefinite%u;\n", depth); fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, &%s, %s, " "&%s_datalen, &l);\n", classname(t->tag.tagclass), typestring, valuename(t->tag.tagclass, t->tag.tagvalue), tmpstr); /* XXX hardcode for now */ if (support_ber && t->subtype->type == TOctetString) { ide = typestring; } else { fprintf(codefile, "if (e == 0 && %s != %s) { e = ASN1_BAD_ID; }\n", typestring, is_primitive_type(t->subtype->type) ? "PRIM" : "CONS"); } 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" "%s_oldlen = len;\n", tmpstr); if(support_ber) fprintf (codefile, "if((is_indefinite%u = _heim_fix_dce(%s_datalen, &len)) < 0)\n" "{ e = ASN1_BAD_FORMAT; %s; }\n" "if (is_indefinite%u) { if (len < 2) { e = ASN1_OVERRUN; %s; } len -= 2; }", depth, tmpstr, forwstr, depth, forwstr); else fprintf(codefile, "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n" "len = %s_datalen;\n", tmpstr, forwstr, tmpstr); if (asprintf (&tname, "%s_Tag", tmpstr) < 0 || tname == NULL) errx(1, "malloc"); decode_type (name, t->subtype, 0, forwstr, tname, ide, depth + 1); if(support_ber) fprintf(codefile, "if(is_indefinite%u){\n" "len += 2;\n" "e = der_match_tag_and_length(p, len, " "(Der_class)0, &%s, UT_EndOfContent, " "&%s_datalen, &l);\n" "if(e) %s;\n" "p += l; len -= l; ret += l;\n" "if (%s != (Der_type)0) { e = ASN1_BAD_ID; %s; }\n" "} else \n", depth, typestring, tmpstr, forwstr, typestring, forwstr); fprintf(codefile, "len = %s_oldlen - %s_datalen;\n", tmpstr, tmpstr); if(optional) fprintf(codefile, "}\n"); fprintf(codefile, "}\n"); free(tname); free(typestring); 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 = NULL; 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)); fprintf(codefile, "(%s)->element = %s;\n", name, m->label); if (asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL) errx(1, "malloc"); decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL, depth + 1); free(s); fprintf(codefile, "}\n"); els = "else "; } if (have_ellipsis) { fprintf(codefile, "else {\n" "(%s)->element = %s;\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" "p += len;\n" "ret += len;\n" "len = 0;\n" "}\n", name, have_ellipsis->label, name, have_ellipsis->gen_name, name, have_ellipsis->gen_name, forwstr, name, have_ellipsis->gen_name, name, have_ellipsis->gen_name); } 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, 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 TVisibleString: decode_primitive ("visible_string", name, forwstr); break; case TNull: fprintf (codefile, "/* NULL */\n"); break; case TOID: decode_primitive ("oid", name, forwstr); break; default : abort (); } return 0; } void generate_type_decode (const Symbol *s) { int preserve = preserve_type(s->name) ? TRUE : FALSE; fprintf (codefile, "int ASN1CALL\n" "decode_%s(const unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE," " size_t len HEIMDAL_UNUSED_ATTRIBUTE, %s *data, size_t *size)\n" "{\n", s->gen_name, s->gen_name); switch (s->type->type) { case TInteger: case TBoolean: case TOctetString: case TOID: case TGeneralizedTime: case TGeneralString: case TTeletexString: case TUTF8String: case TPrintableString: case TIA5String: case TBMPString: case TUniversalString: case TVisibleString: case TUTCTime: case TNull: case TEnumerated: case TBitString: case TSequence: case TSequenceOf: case TSet: case TSetOf: case TTag: case TType: case TChoice: fprintf (codefile, "size_t ret = 0;\n" "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n" "int e HEIMDAL_UNUSED_ATTRIBUTE;\n"); if (preserve) fprintf (codefile, "const unsigned char *begin = p;\n"); fprintf (codefile, "\n"); fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */ decode_type ("data", s->type, 0, "goto fail", "Top", NULL, 1); if (preserve) fprintf (codefile, "data->_save.data = calloc(1, ret);\n" "if (data->_save.data == NULL) { \n" "e = ENOMEM; goto fail; \n" "}\n" "data->_save.length = ret;\n" "memcpy(data->_save.data, begin, ret);\n"); fprintf (codefile, "if(size) *size = ret;\n" "return 0;\n"); fprintf (codefile, "fail:\n" "free_%s(data);\n" "return e;\n", s->gen_name); break; default: abort (); } fprintf (codefile, "}\n\n"); } diff --git a/crypto/heimdal/lib/asn1/gen_encode.c b/crypto/heimdal/lib/asn1/gen_encode.c index 1bd47484d83a..ac43b6a0d364 100644 --- a/crypto/heimdal/lib/asn1/gen_encode.c +++ b/crypto/heimdal/lib/asn1/gen_encode.c @@ -1,550 +1,552 @@ /* * Copyright (c) 1997 - 2006 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 "gen_locl.h" RCSID("$Id$"); static void encode_primitive (const char *typename, const char *name) { fprintf (codefile, "e = der_put_%s(p, len, %s, &l);\n" "if (e) return e;\np -= l; len -= l; ret += l;\n\n", typename, name); } 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; const 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, const char *tmpstr) { int constructed = 1; switch (t->type) { case TType: #if 0 encode_type (name, t->symbol->type); #endif fprintf (codefile, "e = encode_%s(p, len, %s, &l);\n" "if (e) return e;\np -= l; len -= l; ret += l;\n\n", t->symbol->gen_name, name); break; case TInteger: if(t->members) { fprintf(codefile, "{\n" "int enumint = (int)*%s;\n", name); encode_primitive ("integer", "&enumint"); fprintf(codefile, "}\n;"); } else if (t->range == NULL) { encode_primitive ("heim_integer", name); - } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { + } else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) { + encode_primitive ("integer64", name); + } else if (t->range->min >= 0 && t->range->max > UINT_MAX) { + encode_primitive ("unsigned64", 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) { + } else if (t->range->min >= 0 && t->range->max <= UINT_MAX) { encode_primitive ("unsigned", name); } else - errx(1, "%s: unsupported range %d -> %d", + errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64, name, t->range->min, t->range->max); constructed = 0; break; case TBoolean: encode_primitive ("boolean", name); constructed = 0; break; case TOctetString: encode_primitive ("octet_string", name); constructed = 0; break; case TBitString: { Member *m; int pos; 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 rest = 0;\n" "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. * * I hate ASN.1 (and DER), but I hate it even more when everybody * has to screw it up differently. */ pos = ASN1_TAILQ_LAST(t->members, memhead)->val; if (rfc1510_bitstring) { if (pos < 31) pos = 31; } 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"); if (!rfc1510_bitstring) fprintf (codefile, "if (!bit_set) {\n" "rest = 0;\n" "while(c) { \n" "if (c & 1) break;\n" "c = c >> 1;\n" "rest++;\n" "}\n" "bit_set = 1;\n" "}\n" "}\n"); fprintf (codefile, "c = 0;\n"); pos -= 8; } fprintf (codefile, "if((%s)->%s) {\n" "c |= 1<<%d;\n", name, m->gen_name, 7 - m->val % 8); fprintf (codefile, "}\n"); } 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"); if (!rfc1510_bitstring) fprintf (codefile, "if (!bit_set) {\n" "rest = 0;\n" "if(c) { \n" "while(c) { \n" "if (c & 1) break;\n" "c = c >> 1;\n" "rest++;\n" "}\n" "}\n" "}\n" "}\n"); fprintf (codefile, "if (len < 1) return ASN1_OVERFLOW;\n" "*p-- = %s;\n" "len -= 1;\n" "ret += 1;\n" "}\n\n", rfc1510_bitstring ? "0" : "rest"); constructed = 0; break; } case TEnumerated : { encode_primitive ("enumerated", name); constructed = 0; break; } case TSet: case TSequence: { Member *m; if (t->members == NULL) break; ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) { char *s = NULL; if (m->ellipsis) continue; if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL) errx(1, "malloc"); fprintf(codefile, "/* %s */\n", m->name); if (m->optional) fprintf (codefile, "if(%s) ", s); else if(m->defval) gen_compare_defval(s + 1, m->defval); fprintf (codefile, "{\n"); fprintf (codefile, "size_t %s_oldret HEIMDAL_UNUSED_ATTRIBUTE = ret;\n", tmpstr); fprintf (codefile, "ret = 0;\n"); encode_type (s, m->type, m->gen_name); fprintf (codefile, "ret += %s_oldret;\n", tmpstr); fprintf (codefile, "}\n"); free (s); } break; } case TSetOf: { fprintf(codefile, "{\n" "struct heim_octet_string *val;\n" "size_t elen = 0, totallen = 0;\n" "int eret = 0;\n"); fprintf(codefile, "if ((%s)->len > UINT_MAX/sizeof(val[0]))\n" "return ERANGE;\n", name); 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 < (int)(%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 < (int)(%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, "for(i = (int)(%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: { char *sname = NULL; char *n = NULL; fprintf (codefile, "for(i = (int)(%s)->len - 1; i >= 0; --i) {\n" "size_t %s_for_oldret = ret;\n" "ret = 0;\n", name, tmpstr); if (asprintf (&n, "&(%s)->val[i]", name) < 0 || n == NULL) errx(1, "malloc"); if (asprintf (&sname, "%s_S_Of", tmpstr) < 0 || sname == NULL) errx(1, "malloc"); encode_type (n, t->subtype, sname); fprintf (codefile, "ret += %s_for_oldret;\n" "}\n", tmpstr); free (n); free (sname); break; } case TGeneralizedTime: encode_primitive ("generalized_time", name); constructed = 0; break; case TGeneralString: encode_primitive ("general_string", name); constructed = 0; break; case TTeletexString: encode_primitive ("general_string", name); constructed = 0; break; case TTag: { char *tname = NULL; int c; if (asprintf (&tname, "%s_tag", tmpstr) < 0 || tname == NULL) errx(1, "malloc"); c = encode_type (name, t->subtype, tname); 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)); free (tname); break; } case TChoice:{ Member *m, *have_ellipsis = NULL; char *s = NULL; if (t->members == NULL) break; fprintf(codefile, "\n"); if (asprintf (&s, "(%s)", name) < 0 || s == NULL) errx(1, "malloc"); fprintf(codefile, "switch(%s->element) {\n", s); ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) { char *s2 = NULL; if (m->ellipsis) { have_ellipsis = m; continue; } fprintf (codefile, "case %s: {", m->label); if (asprintf(&s2, "%s(%s)->u.%s", m->optional ? "" : "&", s, m->gen_name) < 0 || s2 == NULL) errx(1, "malloc"); if (m->optional) fprintf (codefile, "if(%s) {\n", s2); fprintf (codefile, "size_t %s_oldret = ret;\n", tmpstr); fprintf (codefile, "ret = 0;\n"); constructed = encode_type (s2, m->type, m->gen_name); fprintf (codefile, "ret += %s_oldret;\n", tmpstr); 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 TVisibleString: encode_primitive ("visible_string", name); constructed = 0; break; case TNull: fprintf (codefile, "/* NULL */\n"); constructed = 0; break; default: abort (); } return constructed; } void generate_type_encode (const Symbol *s) { fprintf (codefile, "int ASN1CALL\n" "encode_%s(unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE, size_t len HEIMDAL_UNUSED_ATTRIBUTE," " const %s *data, size_t *size)\n" "{\n", s->gen_name, s->gen_name); switch (s->type->type) { case TInteger: case TBoolean: case TOctetString: case TGeneralizedTime: case TGeneralString: case TTeletexString: case TUTCTime: case TUTF8String: case TPrintableString: case TIA5String: case TBMPString: case TUniversalString: case TVisibleString: case TNull: case TBitString: case TEnumerated: case TOID: case TSequence: case TSequenceOf: case TSet: case TSetOf: case TTag: case TType: case TChoice: fprintf (codefile, "size_t ret HEIMDAL_UNUSED_ATTRIBUTE = 0;\n" "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n" "int i HEIMDAL_UNUSED_ATTRIBUTE, e HEIMDAL_UNUSED_ATTRIBUTE;\n\n"); encode_type("data", s->type, "Top"); fprintf (codefile, "*size = ret;\n" "return 0;\n"); break; default: abort (); } fprintf (codefile, "}\n\n"); } diff --git a/crypto/heimdal/lib/asn1/gen_length.c b/crypto/heimdal/lib/asn1/gen_length.c index 20b5adfe5d02..f12246e676ec 100644 --- a/crypto/heimdal/lib/asn1/gen_length.c +++ b/crypto/heimdal/lib/asn1/gen_length.c @@ -1,279 +1,281 @@ /* * 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 "gen_locl.h" RCSID("$Id$"); static void length_primitive (const char *typename, const char *name, const char *variable) { fprintf (codefile, "%s += der_length_%s(%s);\n", variable, typename, name); } /* XXX same as der_length_tag */ 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, const char *tmpstr) { switch (t->type) { case TType: #if 0 length_type (name, t->symbol->type); #endif fprintf (codefile, "%s += length_%s(%s);\n", variable, t->symbol->gen_name, name); break; case TInteger: if(t->members) { fprintf(codefile, "{\n" "int enumint = *%s;\n", name); length_primitive ("integer", "&enumint", variable); fprintf(codefile, "}\n"); } else if (t->range == NULL) { length_primitive ("heim_integer", name, variable); - } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { + } else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) { + length_primitive ("integer64", name, variable); + } else if (t->range->min >= 0 && t->range->max > UINT_MAX) { + length_primitive ("unsigned64", 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) { + } else if (t->range->min >= 0 && t->range->max <= UINT_MAX) { length_primitive ("unsigned", name, variable); } else - errx(1, "%s: unsupported range %d -> %d", + errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64, name, t->range->min, t->range->max); break; case TBoolean: fprintf (codefile, "%s += 1;\n", variable); break; case TEnumerated : length_primitive ("enumerated", name, variable); break; case TOctetString: length_primitive ("octet_string", name, variable); break; case TBitString: { 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 TSet: case TSequence: case TChoice: { Member *m, *have_ellipsis = NULL; if (t->members == NULL) break; if(t->type == TChoice) fprintf (codefile, "switch((%s)->element) {\n", 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); if (asprintf (&s, "%s(%s)->%s%s", m->optional ? "" : "&", name, t->type == TChoice ? "u." : "", m->gen_name) < 0 || 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" "size_t %s_oldret = %s;\n" "%s = 0;\n", tmpstr, variable, variable); length_type (s, m->type, "ret", m->gen_name); fprintf (codefile, "ret += %s_oldret;\n", tmpstr); fprintf (codefile, "}\n"); 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 */ } break; } case TSetOf: case TSequenceOf: { char *n = NULL; char *sname = NULL; fprintf (codefile, "{\n" "size_t %s_oldret = %s;\n" "int i;\n" "%s = 0;\n", tmpstr, variable, variable); fprintf (codefile, "for(i = (%s)->len - 1; i >= 0; --i){\n", name); fprintf (codefile, "size_t %s_for_oldret = %s;\n" "%s = 0;\n", tmpstr, variable, variable); if (asprintf (&n, "&(%s)->val[i]", name) < 0 || n == NULL) errx(1, "malloc"); if (asprintf (&sname, "%s_S_Of", tmpstr) < 0 || sname == NULL) errx(1, "malloc"); length_type(n, t->subtype, variable, sname); fprintf (codefile, "%s += %s_for_oldret;\n", variable, tmpstr); fprintf (codefile, "}\n"); fprintf (codefile, "%s += %s_oldret;\n" "}\n", variable, tmpstr); free(n); free(sname); break; } case TGeneralizedTime: length_primitive ("generalized_time", name, variable); break; case TGeneralString: length_primitive ("general_string", name, variable); break; case TTeletexString: 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 TVisibleString: length_primitive ("visible_string", name, variable); break; case TNull: fprintf (codefile, "/* NULL */\n"); break; case TTag:{ char *tname = NULL; if (asprintf(&tname, "%s_tag", tmpstr) < 0 || tname == NULL) errx(1, "malloc"); length_type (name, t->subtype, variable, tname); fprintf (codefile, "ret += %lu + der_length_len (ret);\n", (unsigned long)length_tag(t->tag.tagvalue)); free(tname); break; } case TOID: length_primitive ("oid", name, variable); break; default : abort (); } return 0; } void generate_type_length (const Symbol *s) { fprintf (codefile, "size_t ASN1CALL\n" "length_%s(const %s *data)\n" "{\n" "size_t ret = 0;\n", s->gen_name, s->gen_name); length_type ("data", s->type, "ret", "Top"); fprintf (codefile, "return ret;\n}\n\n"); } diff --git a/crypto/heimdal/lib/asn1/gen_template.c b/crypto/heimdal/lib/asn1/gen_template.c index edd68e122380..15bf7d30c498 100644 --- a/crypto/heimdal/lib/asn1/gen_template.c +++ b/crypto/heimdal/lib/asn1/gen_template.c @@ -1,918 +1,922 @@ /* * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Portions Copyright (c) 2009 Apple Inc. 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 "gen_locl.h" static const char *symbol_name(const char *, const Type *); static void generate_template_type(const char *, const char **, const char *, const char *, const char *, Type *, int, int, int); static const char * ttype_symbol(const char *basename, const Type *t) { return t->symbol->gen_name; } static const char * integer_symbol(const char *basename, const Type *t) { if (t->members) return "int"; /* XXX enum foo */ else if (t->range == NULL) return "heim_integer"; - else if (t->range->min == INT_MIN && t->range->max == INT_MAX) + else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) + return "int64_t"; + else if (t->range->min >= 0 && t->range->max > UINT_MAX) + return "uint64_t"; + else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX) return "int"; - else if (t->range->min == 0 && t->range->max == UINT_MAX) - return "unsigned"; - else if (t->range->min == 0 && t->range->max == INT_MAX) + else if (t->range->min >= 0 && t->range->max <= UINT_MAX) return "unsigned"; else { abort(); UNREACHABLE(return NULL); } } static const char * boolean_symbol(const char *basename, const Type *t) { return "int"; } static const char * octetstring_symbol(const char *basename, const Type *t) { return "heim_octet_string"; } static const char * sequence_symbol(const char *basename, const Type *t) { return basename; } static const char * time_symbol(const char *basename, const Type *t) { return "time_t"; } static const char * tag_symbol(const char *basename, const Type *t) { return symbol_name(basename, t->subtype); } static const char * generalstring_symbol(const char *basename, const Type *t) { return "heim_general_string"; } static const char * printablestring_symbol(const char *basename, const Type *t) { return "heim_printable_string"; } static const char * ia5string_symbol(const char *basename, const Type *t) { return "heim_ia5_string"; } static const char * visiblestring_symbol(const char *basename, const Type *t) { return "heim_visible_string"; } static const char * utf8string_symbol(const char *basename, const Type *t) { return "heim_utf8_string"; } static const char * bmpstring_symbol(const char *basename, const Type *t) { return "heim_bmp_string"; } static const char * universalstring_symbol(const char *basename, const Type *t) { return "heim_universal_string"; } static const char * oid_symbol(const char *basename, const Type *t) { return "heim_oid"; } static const char * bitstring_symbol(const char *basename, const Type *t) { if (t->members) return basename; return "heim_bit_string"; } struct { enum typetype type; const char *(*symbol_name)(const char *, const Type *); int is_struct; } types[] = { { TBMPString, bmpstring_symbol, 0 }, { TBitString, bitstring_symbol, 0 }, { TBoolean, boolean_symbol, 0 }, { TGeneralString, generalstring_symbol, 0 }, { TGeneralizedTime, time_symbol, 0 }, { TIA5String, ia5string_symbol, 0 }, { TInteger, integer_symbol, 0 }, { TOID, oid_symbol, 0 }, { TOctetString, octetstring_symbol, 0 }, { TPrintableString, printablestring_symbol, 0 }, { TSequence, sequence_symbol, 1 }, { TSequenceOf, tag_symbol, 1 }, { TSetOf, tag_symbol, 1 }, { TTag, tag_symbol, 1 }, { TType, ttype_symbol, 1 }, { TUTCTime, time_symbol, 0 }, { TUniversalString, universalstring_symbol, 0 }, { TVisibleString, visiblestring_symbol, 0 }, { TUTF8String, utf8string_symbol, 0 }, { TChoice, sequence_symbol, 1 }, { TNull, integer_symbol, 1 } }; static FILE * get_code_file(void) { if (!one_code_file) return templatefile; return codefile; } static int is_supported_type_p(const Type *t) { size_t i; for (i = 0; i < sizeof(types)/sizeof(types[0]); i++) if (t->type == types[i].type) return 1; return 0; } int is_template_compat (const Symbol *s) { return is_supported_type_p(s->type); } static const char * symbol_name(const char *basename, const Type *t) { size_t i; for (i = 0; i < sizeof(types)/sizeof(types[0]); i++) if (t->type == types[i].type) return (types[i].symbol_name)(basename, t); printf("unknown der type: %d\n", t->type); exit(1); } static char * partial_offset(const char *basetype, const char *name, int need_offset) { char *str; if (name == NULL || need_offset == 0) return strdup("0"); if (asprintf(&str, "offsetof(struct %s, %s)", basetype, name) < 0 || str == NULL) errx(1, "malloc"); return str; } struct template { char *line; char *tt; char *offset; char *ptr; ASN1_TAILQ_ENTRY(template) members; }; ASN1_TAILQ_HEAD(templatehead, template); struct tlist { char *name; char *header; struct templatehead template; ASN1_TAILQ_ENTRY(tlist) tmembers; }; ASN1_TAILQ_HEAD(tlisthead, tlist); static void tlist_header(struct tlist *, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); static struct template * add_line(struct templatehead *, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); static int tlist_cmp(const struct tlist *, const struct tlist *); static void add_line_pointer(struct templatehead *, const char *, const char *, const char *, ...) __attribute__((__format__(__printf__, 4, 5))); static struct tlisthead tlistmaster = ASN1_TAILQ_HEAD_INITIALIZER(tlistmaster); static unsigned long numdups = 0; static struct tlist * tlist_new(const char *name) { struct tlist *tl = calloc(1, sizeof(*tl)); tl->name = strdup(name); ASN1_TAILQ_INIT(&tl->template); return tl; } static void tlist_header(struct tlist *t, const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (vasprintf(&t->header, fmt, ap) < 0 || t->header == NULL) errx(1, "malloc"); va_end(ap); } static unsigned long tlist_count(struct tlist *tl) { unsigned int count = 0; struct template *q; ASN1_TAILQ_FOREACH(q, &tl->template, members) { count++; } return count; } static void tlist_add(struct tlist *tl) { ASN1_TAILQ_INSERT_TAIL(&tlistmaster, tl, tmembers); } static void tlist_print(struct tlist *tl) { struct template *q; unsigned int i = 1; FILE *f = get_code_file(); fprintf(f, "static const struct asn1_template asn1_%s[] = {\n", tl->name); fprintf(f, "/* 0 */ %s,\n", tl->header); ASN1_TAILQ_FOREACH(q, &tl->template, members) { int last = (ASN1_TAILQ_LAST(&tl->template, templatehead) == q); fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ","); } fprintf(f, "};\n"); } static struct tlist * tlist_find_by_name(const char *name) { struct tlist *ql; ASN1_TAILQ_FOREACH(ql, &tlistmaster, tmembers) { if (strcmp(ql->name, name) == 0) return ql; } return NULL; } static int tlist_cmp_name(const char *tname, const char *qname) { struct tlist *tl = tlist_find_by_name(tname); struct tlist *ql = tlist_find_by_name(qname); return tlist_cmp(tl, ql); } static int tlist_cmp(const struct tlist *tl, const struct tlist *ql) { int ret; struct template *t, *q; ret = strcmp(tl->header, ql->header); if (ret) return ret; q = ASN1_TAILQ_FIRST(&ql->template); ASN1_TAILQ_FOREACH(t, &tl->template, members) { if (q == NULL) return 1; if (t->ptr == NULL || q->ptr == NULL) { ret = strcmp(t->line, q->line); if (ret) return ret; } else { ret = strcmp(t->tt, q->tt); if (ret) return ret; ret = strcmp(t->offset, q->offset); if (ret) return ret; if ((ret = strcmp(t->ptr, q->ptr)) != 0 || (ret = tlist_cmp_name(t->ptr, q->ptr)) != 0) return ret; } q = ASN1_TAILQ_NEXT(q, members); } if (q != NULL) return -1; return 0; } static const char * tlist_find_dup(const struct tlist *tl) { struct tlist *ql; ASN1_TAILQ_FOREACH(ql, &tlistmaster, tmembers) { if (tlist_cmp(ql, tl) == 0) { numdups++; return ql->name; } } return NULL; } /* * */ static struct template * add_line(struct templatehead *t, const char *fmt, ...) { struct template *q = calloc(1, sizeof(*q)); va_list ap; va_start(ap, fmt); if (vasprintf(&q->line, fmt, ap) < 0 || q->line == NULL) errx(1, "malloc"); va_end(ap); ASN1_TAILQ_INSERT_TAIL(t, q, members); return q; } static void add_line_pointer(struct templatehead *t, const char *ptr, const char *offset, const char *ttfmt, ...) { struct template *q; va_list ap; char *tt = NULL; va_start(ap, ttfmt); if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL) errx(1, "malloc"); va_end(ap); q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr); q->tt = tt; q->offset = strdup(offset); q->ptr = strdup(ptr); } static int use_extern(const Symbol *s) { if (s->type == NULL) return 1; return 0; } static int is_struct(Type *t, int isstruct) { size_t i; if (t->type == TType) return 0; if (t->type == TSequence || t->type == TSet || t->type == TChoice) return 1; if (t->type == TTag) return is_struct(t->subtype, isstruct); for (i = 0; i < sizeof(types)/sizeof(types[0]); i++) { if (t->type == types[i].type) { if (types[i].is_struct == 0) return 0; else break; } } return isstruct; } static const Type * compact_tag(const Type *t) { while (t->type == TTag) t = t->subtype; return t; } static void template_members(struct templatehead *temp, const char *basetype, const char *name, const Type *t, int optional, int isstruct, int need_offset) { char *poffset = NULL; if (optional && t->type != TTag && t->type != TType) errx(1, "%s...%s is optional and not a (TTag or TType)", basetype, name); poffset = partial_offset(basetype, name, need_offset); switch (t->type) { case TType: if (use_extern(t->symbol)) { add_line(temp, "{ A1_OP_TYPE_EXTERN %s, %s, &asn1_extern_%s}", optional ? "|A1_FLAG_OPTIONAL" : "", poffset, t->symbol->gen_name); } else { add_line_pointer(temp, t->symbol->gen_name, poffset, "A1_OP_TYPE %s", optional ? "|A1_FLAG_OPTIONAL" : ""); } break; case TInteger: { char *itype = NULL; if (t->members) itype = "IMEMBER"; else if (t->range == NULL) itype = "HEIM_INTEGER"; - else if (t->range->min == INT_MIN && t->range->max == INT_MAX) + else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) + itype = "INTEGER64"; + else if (t->range->min >= 0 && t->range->max > UINT_MAX) + itype = "UNSIGNED64"; + else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX) itype = "INTEGER"; - else if (t->range->min == 0 && t->range->max == UINT_MAX) - itype = "UNSIGNED"; - else if (t->range->min == 0 && t->range->max == INT_MAX) + else if (t->range->min >= 0 && t->range->max <= UINT_MAX) itype = "UNSIGNED"; else - errx(1, "%s: unsupported range %d -> %d", + errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64, name, t->range->min, t->range->max); add_line(temp, "{ A1_PARSE_T(A1T_%s), %s, NULL }", itype, poffset); break; } case TGeneralString: add_line(temp, "{ A1_PARSE_T(A1T_GENERAL_STRING), %s, NULL }", poffset); break; case TTeletexString: add_line(temp, "{ A1_PARSE_T(A1T_TELETEX_STRING), %s, NULL }", poffset); break; case TPrintableString: add_line(temp, "{ A1_PARSE_T(A1T_PRINTABLE_STRING), %s, NULL }", poffset); break; case TOctetString: add_line(temp, "{ A1_PARSE_T(A1T_OCTET_STRING), %s, NULL }", poffset); break; case TIA5String: add_line(temp, "{ A1_PARSE_T(A1T_IA5_STRING), %s, NULL }", poffset); break; case TBMPString: add_line(temp, "{ A1_PARSE_T(A1T_BMP_STRING), %s, NULL }", poffset); break; case TUniversalString: add_line(temp, "{ A1_PARSE_T(A1T_UNIVERSAL_STRING), %s, NULL }", poffset); break; case TVisibleString: add_line(temp, "{ A1_PARSE_T(A1T_VISIBLE_STRING), %s, NULL }", poffset); break; case TUTF8String: add_line(temp, "{ A1_PARSE_T(A1T_UTF8_STRING), %s, NULL }", poffset); break; case TGeneralizedTime: add_line(temp, "{ A1_PARSE_T(A1T_GENERALIZED_TIME), %s, NULL }", poffset); break; case TUTCTime: add_line(temp, "{ A1_PARSE_T(A1T_UTC_TIME), %s, NULL }", poffset); break; case TBoolean: add_line(temp, "{ A1_PARSE_T(A1T_BOOLEAN), %s, NULL }", poffset); break; case TOID: add_line(temp, "{ A1_PARSE_T(A1T_OID), %s, NULL }", poffset); break; case TNull: break; case TBitString: { struct templatehead template = ASN1_TAILQ_HEAD_INITIALIZER(template); struct template *q; Member *m; size_t count = 0, i; char *bname = NULL; FILE *f = get_code_file(); if (ASN1_TAILQ_EMPTY(t->members)) { add_line(temp, "{ A1_PARSE_T(A1T_HEIM_BIT_STRING), %s, NULL }", poffset); break; } if (asprintf(&bname, "bmember_%s_%p", name ? name : "", t) < 0 || bname == NULL) errx(1, "malloc"); output_name(bname); ASN1_TAILQ_FOREACH(m, t->members, members) { add_line(&template, "{ 0, %d, 0 } /* %s */", m->val, m->gen_name); } ASN1_TAILQ_FOREACH(q, &template, members) { count++; } fprintf(f, "static const struct asn1_template asn1_%s_%s[] = {\n", basetype, bname); fprintf(f, "/* 0 */ { 0%s, sizeof(%s), ((void *)%lu) },\n", rfc1510_bitstring ? "|A1_HBF_RFC1510" : "", basetype, (unsigned long)count); i = 1; ASN1_TAILQ_FOREACH(q, &template, members) { int last = (ASN1_TAILQ_LAST(&template, templatehead) == q); fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ","); } fprintf(f, "};\n"); add_line(temp, "{ A1_OP_BMEMBER, %s, asn1_%s_%s }", poffset, basetype, bname); free(bname); break; } case TSequence: { Member *m; ASN1_TAILQ_FOREACH(m, t->members, members) { char *newbasename = NULL; if (m->ellipsis) continue; if (name) { if (asprintf(&newbasename, "%s_%s", basetype, name) < 0) errx(1, "malloc"); } else newbasename = strdup(basetype); if (newbasename == NULL) errx(1, "malloc"); template_members(temp, newbasename, m->gen_name, m->type, m->optional, isstruct, 1); free(newbasename); } break; } case TTag: { char *tname = NULL, *elname = NULL; const char *sename, *dupname; int subtype_is_struct = is_struct(t->subtype, isstruct); if (subtype_is_struct) sename = basetype; else sename = symbol_name(basetype, t->subtype); if (asprintf(&tname, "tag_%s_%p", name ? name : "", t) < 0 || tname == NULL) errx(1, "malloc"); output_name(tname); if (asprintf(&elname, "%s_%s", basetype, tname) < 0 || elname == NULL) errx(1, "malloc"); generate_template_type(elname, &dupname, NULL, sename, name, t->subtype, 0, subtype_is_struct, 0); add_line_pointer(temp, dupname, poffset, "A1_TAG_T(%s,%s,%s)%s", classname(t->tag.tagclass), is_primitive_type(t->subtype->type) ? "PRIM" : "CONS", valuename(t->tag.tagclass, t->tag.tagvalue), optional ? "|A1_FLAG_OPTIONAL" : ""); free(tname); free(elname); break; } case TSetOf: case TSequenceOf: { const char *type = NULL, *tname, *dupname; char *sename = NULL, *elname = NULL; int subtype_is_struct = is_struct(t->subtype, 0); if (name && subtype_is_struct) { tname = "seofTstruct"; if (asprintf(&sename, "%s_%s_val", basetype, name) < 0) errx(1, "malloc"); } else if (subtype_is_struct) { tname = "seofTstruct"; if (asprintf(&sename, "%s_val", symbol_name(basetype, t->subtype)) < 0) errx(1, "malloc"); } else { if (name) tname = name; else tname = "seofTstruct"; sename = strdup(symbol_name(basetype, t->subtype)); } if (sename == NULL) errx(1, "malloc"); if (t->type == TSetOf) type = "A1_OP_SETOF"; else if (t->type == TSequenceOf) type = "A1_OP_SEQOF"; else abort(); if (asprintf(&elname, "%s_%s_%p", basetype, tname, t) < 0 || elname == NULL) errx(1, "malloc"); generate_template_type(elname, &dupname, NULL, sename, NULL, t->subtype, 0, subtype_is_struct, need_offset); add_line(temp, "{ %s, %s, asn1_%s }", type, poffset, dupname); free(sename); break; } case TChoice: { struct templatehead template = ASN1_TAILQ_HEAD_INITIALIZER(template); struct template *q; size_t count = 0, i; char *tname = NULL; FILE *f = get_code_file(); Member *m; int ellipsis = 0; char *e; if (asprintf(&tname, "asn1_choice_%s_%s%x", basetype, name ? name : "", (unsigned int)(uintptr_t)t) < 0 || tname == NULL) errx(1, "malloc"); ASN1_TAILQ_FOREACH(m, t->members, members) { const char *dupname; char *elname = NULL; char *newbasename = NULL; int subtype_is_struct; if (m->ellipsis) { ellipsis = 1; continue; } subtype_is_struct = is_struct(m->type, 0); if (asprintf(&elname, "%s_choice_%s", basetype, m->gen_name) < 0 || elname == NULL) errx(1, "malloc"); if (subtype_is_struct) { if (asprintf(&newbasename, "%s_%s", basetype, m->gen_name) < 0) errx(1, "malloc"); } else newbasename = strdup(basetype); if (newbasename == NULL) errx(1, "malloc"); generate_template_type(elname, &dupname, NULL, symbol_name(newbasename, m->type), NULL, m->type, 0, subtype_is_struct, 1); add_line(&template, "{ %s, offsetof(%s%s, u.%s), asn1_%s }", m->label, isstruct ? "struct " : "", basetype, m->gen_name, dupname); free(elname); free(newbasename); } e = NULL; if (ellipsis) { if (asprintf(&e, "offsetof(%s%s, u.asn1_ellipsis)", isstruct ? "struct " : "", basetype) < 0 || e == NULL) errx(1, "malloc"); } ASN1_TAILQ_FOREACH(q, &template, members) { count++; } fprintf(f, "static const struct asn1_template %s[] = {\n", tname); fprintf(f, "/* 0 */ { %s, offsetof(%s%s, element), ((void *)%lu) },\n", e ? e : "0", isstruct ? "struct " : "", basetype, (unsigned long)count); i = 1; ASN1_TAILQ_FOREACH(q, &template, members) { int last = (ASN1_TAILQ_LAST(&template, templatehead) == q); fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ","); } fprintf(f, "};\n"); add_line(temp, "{ A1_OP_CHOICE, %s, %s }", poffset, tname); free(e); free(tname); break; } default: abort (); } if (poffset) free(poffset); } static void gen_extern_stubs(FILE *f, const char *name) { fprintf(f, "static const struct asn1_type_func asn1_extern_%s = {\n" "\t(asn1_type_encode)encode_%s,\n" "\t(asn1_type_decode)decode_%s,\n" "\t(asn1_type_length)length_%s,\n" "\t(asn1_type_copy)copy_%s,\n" "\t(asn1_type_release)free_%s,\n" "\tsizeof(%s)\n" "};\n", name, name, name, name, name, name, name); } void gen_template_import(const Symbol *s) { FILE *f = get_code_file(); if (template_flag == 0) return; gen_extern_stubs(f, s->gen_name); } static void generate_template_type(const char *varname, const char **dupname, const char *symname, const char *basetype, const char *name, Type *type, int optional, int isstruct, int need_offset) { struct tlist *tl; const char *dup; int have_ellipsis = 0; tl = tlist_new(varname); template_members(&tl->template, basetype, name, type, optional, isstruct, need_offset); /* if its a sequence or set type, check if there is a ellipsis */ if (type->type == TSequence || type->type == TSet) { Member *m; ASN1_TAILQ_FOREACH(m, type->members, members) { if (m->ellipsis) have_ellipsis = 1; } } if (ASN1_TAILQ_EMPTY(&tl->template) && compact_tag(type)->type != TNull) errx(1, "Tag %s...%s with no content ?", basetype, name ? name : ""); tlist_header(tl, "{ 0%s%s, sizeof(%s%s), ((void *)%lu) }", (symname && preserve_type(symname)) ? "|A1_HF_PRESERVE" : "", have_ellipsis ? "|A1_HF_ELLIPSIS" : "", isstruct ? "struct " : "", basetype, tlist_count(tl)); dup = tlist_find_dup(tl); if (dup) { if (strcmp(dup, tl->name) == 0) errx(1, "found dup of ourself"); *dupname = dup; } else { *dupname = tl->name; tlist_print(tl); tlist_add(tl); } } void generate_template(const Symbol *s) { FILE *f = get_code_file(); const char *dupname; if (use_extern(s)) { gen_extern_stubs(f, s->gen_name); return; } generate_template_type(s->gen_name, &dupname, s->name, s->gen_name, NULL, s->type, 0, 0, 1); fprintf(f, "\n" "int\n" "decode_%s(const unsigned char *p, size_t len, %s *data, size_t *size)\n" "{\n" " return _asn1_decode_top(asn1_%s, 0|%s, p, len, data, size);\n" "}\n" "\n", s->gen_name, s->gen_name, dupname, support_ber ? "A1_PF_ALLOW_BER" : "0"); fprintf(f, "\n" "int\n" "encode_%s(unsigned char *p, size_t len, const %s *data, size_t *size)\n" "{\n" " return _asn1_encode(asn1_%s, p, len, data, size);\n" "}\n" "\n", s->gen_name, s->gen_name, dupname); fprintf(f, "\n" "size_t\n" "length_%s(const %s *data)\n" "{\n" " return _asn1_length(asn1_%s, data);\n" "}\n" "\n", s->gen_name, s->gen_name, dupname); fprintf(f, "\n" "void\n" "free_%s(%s *data)\n" "{\n" " _asn1_free(asn1_%s, data);\n" "}\n" "\n", s->gen_name, s->gen_name, dupname); fprintf(f, "\n" "int\n" "copy_%s(const %s *from, %s *to)\n" "{\n" " return _asn1_copy_top(asn1_%s, from, to);\n" "}\n" "\n", s->gen_name, s->gen_name, s->gen_name, dupname); } diff --git a/crypto/heimdal/lib/asn1/lex.l b/crypto/heimdal/lib/asn1/lex.l index 2d32020266c8..e72e5d9bebe1 100644 --- a/crypto/heimdal/lib/asn1/lex.l +++ b/crypto/heimdal/lib/asn1/lex.l @@ -1,300 +1,300 @@ %{ /* * 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. */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #undef ECHO #include "symbol.h" #include "asn1parse.h" #include "lex.h" #include "gen_locl.h" static unsigned lineno = 1; #undef ECHO static void unterminated(const char *, unsigned); %} /* This is for broken old lexes (solaris 10 and hpux) */ %e 2000 %p 5000 %a 5000 %n 1000 %o 10000 %% 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; } -- { int c, start_lineno = lineno; int f = 0; while((c = input()) != EOF) { if(f && c == '-') break; if(c == '-') { f = 1; continue; } if(c == '\n') { lineno++; break; } f = 0; } if(c == EOF) unterminated("comment", start_lineno); } \/\* { int c, start_lineno = lineno; int level = 1; int seen_star = 0; int seen_slash = 0; while((c = input()) != EOF) { if(c == '/') { if(seen_star) { if(--level == 0) break; seen_star = 0; continue; } seen_slash = 1; continue; } if(seen_star && c == '/') { if(--level == 0) break; seen_star = 0; continue; } if(c == '*') { if(seen_slash) { level++; seen_star = seen_slash = 0; continue; } seen_star = 1; continue; } seen_star = seen_slash = 0; if(c == '\n') { lineno++; continue; } } if(c == EOF) unterminated("comment", start_lineno); } "\"" { 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) unterminated("string", start_lineno); *p++ = '\0'; fprintf(stderr, "string -- %s\n", buf); yylval.name = estrdup(buf); return STRING; } -?0x[0-9A-Fa-f]+|-?[0-9]+ { char *e, *y = yytext; - yylval.constant = strtol((const char *)yytext, + yylval.constant = strtoll((const char *)yytext, &e, 0); if(e == y) lex_error_message("malformed constant (%s)", yytext); else return NUMBER; } [A-Za-z][-A-Za-z0-9_]* { yylval.name = estrdup ((const char *)yytext); return IDENTIFIER; } [ \t] ; \n { ++lineno; } \.\.\. { return ELLIPSIS; } \.\. { return RANGE; } . { lex_error_message("Ignoring char(%c)\n", *yytext); } %% #ifndef yywrap /* XXX */ int yywrap () { return 1; } #endif void lex_error_message (const char *format, ...) { va_list args; va_start (args, format); fprintf (stderr, "%s:%d: ", get_filename(), lineno); vfprintf (stderr, format, args); va_end (args); error_flag++; } static void unterminated(const char *type, unsigned start_lineno) { lex_error_message("unterminated %s, possibly started on line %d\n", type, start_lineno); } diff --git a/crypto/heimdal/lib/asn1/symbol.h b/crypto/heimdal/lib/asn1/symbol.h index a39c8f46512d..3a2d91bc90dd 100644 --- a/crypto/heimdal/lib/asn1/symbol.h +++ b/crypto/heimdal/lib/asn1/symbol.h @@ -1,162 +1,166 @@ /* * 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. */ /* $Id$ */ #ifndef _SYMBOL_H #define _SYMBOL_H #include "asn1_queue.h" enum typetype { TBitString, TBoolean, TChoice, TEnumerated, TGeneralString, TTeletexString, TGeneralizedTime, TIA5String, TInteger, TNull, TOID, TOctetString, TPrintableString, TSequence, TSequenceOf, TSet, TSetOf, TTag, TType, TUTCTime, TUTF8String, TBMPString, TUniversalString, TVisibleString }; typedef enum typetype Typetype; struct type; struct value { enum { booleanvalue, nullvalue, integervalue, stringvalue, objectidentifiervalue } type; union { int booleanvalue; - int integervalue; + int64_t integervalue; char *stringvalue; struct objid *objectidentifiervalue; } u; }; struct member { 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; + /* + * We can't represent unsigned 64-bit ranges because max might be + * negative... + */ + int64_t min; + int64_t max; }; enum ctype { CT_CONTENTS, CT_USER } ; struct constraint_spec; struct type { Typetype type; struct memhead *members; struct symbol *symbol; struct type *subtype; struct tagtype tag; struct range *range; struct constraint_spec *constraint; }; typedef struct type Type; struct constraint_spec { enum ctype ctype; union { struct { Type *type; struct value *encoding; } content; } u; }; struct objid { const char *label; int value; struct objid *next; }; struct symbol { char *name; char *gen_name; enum { SUndefined, SValue, Stype } stype; struct value *value; Type *type; }; typedef struct symbol Symbol; void initsym (void); Symbol *addsym (char *); void output_name (char *); int checkundefined(void); #endif diff --git a/crypto/heimdal/lib/asn1/template.c b/crypto/heimdal/lib/asn1/template.c index 3e0b6932357e..bc76d4151051 100644 --- a/crypto/heimdal/lib/asn1/template.c +++ b/crypto/heimdal/lib/asn1/template.c @@ -1,1119 +1,1121 @@ /* * Copyright (c) 2009 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Portions Copyright (c) 2009 Apple Inc. 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 #if 0 #define ABORT_ON_ERROR() abort() #else #define ABORT_ON_ERROR() do { } while(0) #endif #define DPOC(data,offset) ((const void *)(((const unsigned char *)data) + offset)) #define DPO(data,offset) ((void *)(((unsigned char *)data) + offset)) static struct asn1_type_func prim[] = { #define el(name, type) { \ (asn1_type_encode)der_put_##name, \ (asn1_type_decode)der_get_##name, \ (asn1_type_length)der_length_##name, \ (asn1_type_copy)der_copy_##name, \ (asn1_type_release)der_free_##name, \ sizeof(type) \ } #define elber(name, type) { \ (asn1_type_encode)der_put_##name, \ (asn1_type_decode)der_get_##name##_ber, \ (asn1_type_length)der_length_##name, \ (asn1_type_copy)der_copy_##name, \ (asn1_type_release)der_free_##name, \ sizeof(type) \ } el(integer, int), el(heim_integer, heim_integer), el(integer, int), + el(integer64, int64_t), el(unsigned, unsigned), + el(unsigned64, uint64_t), el(general_string, heim_general_string), el(octet_string, heim_octet_string), elber(octet_string, heim_octet_string), el(ia5_string, heim_ia5_string), el(bmp_string, heim_bmp_string), el(universal_string, heim_universal_string), el(printable_string, heim_printable_string), el(visible_string, heim_visible_string), el(utf8string, heim_utf8_string), el(generalized_time, time_t), el(utctime, time_t), el(bit_string, heim_bit_string), { (asn1_type_encode)der_put_boolean, (asn1_type_decode)der_get_boolean, (asn1_type_length)der_length_boolean, (asn1_type_copy)der_copy_integer, (asn1_type_release)der_free_integer, sizeof(int) }, el(oid, heim_oid), el(general_string, heim_general_string), #undef el #undef elber }; static size_t sizeofType(const struct asn1_template *t) { return t->offset; } /* * Here is abstraction to not so well evil fact of bit fields in C, * they are endian dependent, so when getting and setting bits in the * host local structure we need to know the endianness of the host. * * Its not the first time in Heimdal this have bitten us, and some day * we'll grow up and use #defined constant, but bit fields are still * so pretty and shiny. */ static void bmember_get_bit(const unsigned char *p, void *data, unsigned int bit, size_t size) { unsigned int localbit = bit % 8; if ((*p >> (7 - localbit)) & 1) { #ifdef WORDS_BIGENDIAN *(unsigned int *)data |= (1 << ((size * 8) - bit - 1)); #else *(unsigned int *)data |= (1 << bit); #endif } } static int bmember_isset_bit(const void *data, unsigned int bit, size_t size) { #ifdef WORDS_BIGENDIAN if ((*(unsigned int *)data) & (1 << ((size * 8) - bit - 1))) return 1; return 0; #else if ((*(unsigned int *)data) & (1 << bit)) return 1; return 0; #endif } static void bmember_put_bit(unsigned char *p, const void *data, unsigned int bit, size_t size, unsigned int *bitset) { unsigned int localbit = bit % 8; if (bmember_isset_bit(data, bit, size)) { *p |= (1 << (7 - localbit)); if (*bitset == 0) *bitset = (7 - localbit) + 1; } } int _asn1_decode(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size) { size_t elements = A1_HEADER_LEN(t); size_t oldlen = len; int ret = 0; const unsigned char *startp = NULL; unsigned int template_flags = t->tt; /* skip over header */ t++; if (template_flags & A1_HF_PRESERVE) startp = p; while (elements) { switch (t->tt & A1_OP_MASK) { case A1_OP_TYPE: case A1_OP_TYPE_EXTERN: { size_t newsize, size; void *el = DPO(data, t->offset); void **pel = (void **)el; if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { size = sizeofType(t->ptr); } else { const struct asn1_type_func *f = t->ptr; size = f->size; } if (t->tt & A1_FLAG_OPTIONAL) { *pel = calloc(1, size); if (*pel == NULL) return ENOMEM; el = *pel; } if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize); } else { const struct asn1_type_func *f = t->ptr; ret = (f->decode)(p, len, el, &newsize); } if (ret) { if (t->tt & A1_FLAG_OPTIONAL) { free(*pel); *pel = NULL; break; } return ret; } p += newsize; len -= newsize; break; } case A1_OP_TAG: { Der_type dertype; size_t newsize; size_t datalen, l; void *olddata = data; int is_indefinite = 0; int subflags = flags; ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt), &dertype, A1_TAG_TAG(t->tt), &datalen, &l); if (ret) { if (t->tt & A1_FLAG_OPTIONAL) break; return ret; } p += l; len -= l; /* * Only allow indefinite encoding for OCTET STRING and BER * for now. Should handle BIT STRING too. */ if (dertype != A1_TAG_TYPE(t->tt) && (flags & A1_PF_ALLOW_BER)) { const struct asn1_template *subtype = t->ptr; subtype++; /* skip header */ if (((subtype->tt & A1_OP_MASK) == A1_OP_PARSE) && A1_PARSE_TYPE(subtype->tt) == A1T_OCTET_STRING) subflags |= A1_PF_INDEFINTE; } if (datalen == ASN1_INDEFINITE) { if ((flags & A1_PF_ALLOW_BER) == 0) return ASN1_GOT_BER; is_indefinite = 1; datalen = len; if (datalen < 2) return ASN1_OVERRUN; /* hide EndOfContent for sub-decoder, catching it below */ datalen -= 2; } else if (datalen > len) return ASN1_OVERRUN; data = DPO(data, t->offset); if (t->tt & A1_FLAG_OPTIONAL) { void **el = (void **)data; size_t ellen = sizeofType(t->ptr); *el = calloc(1, ellen); if (*el == NULL) return ENOMEM; data = *el; } ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize); if (ret) return ret; if (newsize != datalen) return ASN1_EXTRA_DATA; len -= datalen; p += datalen; /* * Indefinite encoding needs a trailing EndOfContent, * check for that. */ if (is_indefinite) { ret = der_match_tag_and_length(p, len, ASN1_C_UNIV, &dertype, UT_EndOfContent, &datalen, &l); if (ret) return ret; if (dertype != PRIM) return ASN1_BAD_ID; if (datalen != 0) return ASN1_INDEF_EXTRA_DATA; p += l; len -= l; } data = olddata; break; } case A1_OP_PARSE: { unsigned int type = A1_PARSE_TYPE(t->tt); size_t newsize; void *el = DPO(data, t->offset); /* * INDEFINITE primitive types are one element after the * same type but non-INDEFINITE version. */ if (flags & A1_PF_INDEFINTE) type++; if (type >= sizeof(prim)/sizeof(prim[0])) { ABORT_ON_ERROR(); return ASN1_PARSE_ERROR; } ret = (prim[type].decode)(p, len, el, &newsize); if (ret) return ret; p += newsize; len -= newsize; break; } case A1_OP_SETOF: case A1_OP_SEQOF: { struct template_of *el = DPO(data, t->offset); size_t newsize; size_t ellen = sizeofType(t->ptr); size_t vallength = 0; while (len > 0) { void *tmp; size_t newlen = vallength + ellen; if (vallength > newlen) return ASN1_OVERFLOW; tmp = realloc(el->val, newlen); if (tmp == NULL) return ENOMEM; memset(DPO(tmp, vallength), 0, ellen); el->val = tmp; ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len, DPO(el->val, vallength), &newsize); if (ret) return ret; vallength = newlen; el->len++; p += newsize; len -= newsize; } break; } case A1_OP_BMEMBER: { const struct asn1_template *bmember = t->ptr; size_t size = bmember->offset; size_t elements = A1_HEADER_LEN(bmember); size_t pos = 0; bmember++; memset(data, 0, size); if (len < 1) return ASN1_OVERRUN; p++; len--; while (elements && len) { while (bmember->offset / 8 > pos / 8) { if (len < 1) break; p++; len--; pos += 8; } if (len) { bmember_get_bit(p, data, bmember->offset, size); elements--; bmember++; } } len = 0; break; } case A1_OP_CHOICE: { const struct asn1_template *choice = t->ptr; unsigned int *element = DPO(data, choice->offset); size_t datalen; unsigned int i; for (i = 1; i < A1_HEADER_LEN(choice) + 1; i++) { /* should match first tag instead, store it in choice.tt */ ret = _asn1_decode(choice[i].ptr, 0, p, len, DPO(data, choice[i].offset), &datalen); if (ret == 0) { *element = i; p += datalen; len -= datalen; break; } else if (ret != ASN1_BAD_ID && ret != ASN1_MISPLACED_FIELD && ret != ASN1_MISSING_FIELD) { return ret; } } if (i >= A1_HEADER_LEN(choice) + 1) { if (choice->tt == 0) return ASN1_BAD_ID; *element = 0; ret = der_get_octet_string(p, len, DPO(data, choice->tt), &datalen); if (ret) return ret; p += datalen; len -= datalen; } break; } default: ABORT_ON_ERROR(); return ASN1_PARSE_ERROR; } t++; elements--; } /* if we are using padding, eat up read of context */ if (template_flags & A1_HF_ELLIPSIS) len = 0; oldlen -= len; if (size) *size = oldlen; /* * saved the raw bits if asked for it, useful for signature * verification. */ if (startp) { heim_octet_string *save = data; save->data = malloc(oldlen); if (save->data == NULL) return ENOMEM; else { save->length = oldlen; memcpy(save->data, startp, oldlen); } } return 0; } int _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const void *data, size_t *size) { size_t elements = A1_HEADER_LEN(t); int ret = 0; size_t oldlen = len; t += A1_HEADER_LEN(t); while (elements) { switch (t->tt & A1_OP_MASK) { case A1_OP_TYPE: case A1_OP_TYPE_EXTERN: { size_t newsize; const void *el = DPOC(data, t->offset); if (t->tt & A1_FLAG_OPTIONAL) { void **pel = (void **)el; if (*pel == NULL) break; el = *pel; } if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { ret = _asn1_encode(t->ptr, p, len, el, &newsize); } else { const struct asn1_type_func *f = t->ptr; ret = (f->encode)(p, len, el, &newsize); } if (ret) return ret; p -= newsize; len -= newsize; break; } case A1_OP_TAG: { const void *olddata = data; size_t l, datalen; data = DPOC(data, t->offset); if (t->tt & A1_FLAG_OPTIONAL) { void **el = (void **)data; if (*el == NULL) { data = olddata; break; } data = *el; } ret = _asn1_encode(t->ptr, p, len, data, &datalen); if (ret) return ret; len -= datalen; p -= datalen; ret = der_put_length_and_tag(p, len, datalen, A1_TAG_CLASS(t->tt), A1_TAG_TYPE(t->tt), A1_TAG_TAG(t->tt), &l); if (ret) return ret; p -= l; len -= l; data = olddata; break; } case A1_OP_PARSE: { unsigned int type = A1_PARSE_TYPE(t->tt); size_t newsize; const void *el = DPOC(data, t->offset); if (type > sizeof(prim)/sizeof(prim[0])) { ABORT_ON_ERROR(); return ASN1_PARSE_ERROR; } ret = (prim[type].encode)(p, len, el, &newsize); if (ret) return ret; p -= newsize; len -= newsize; break; } case A1_OP_SETOF: { const struct template_of *el = DPOC(data, t->offset); size_t ellen = sizeofType(t->ptr); struct heim_octet_string *val; unsigned char *elptr = el->val; size_t i, totallen; if (el->len == 0) break; if (el->len > UINT_MAX/sizeof(val[0])) return ERANGE; val = malloc(sizeof(val[0]) * el->len); if (val == NULL) return ENOMEM; for(totallen = 0, i = 0; i < el->len; i++) { unsigned char *next; size_t l; val[i].length = _asn1_length(t->ptr, elptr); val[i].data = malloc(val[i].length); ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1), val[i].length, elptr, &l); if (ret) break; next = elptr + ellen; if (next < elptr) { ret = ASN1_OVERFLOW; break; } elptr = next; totallen += val[i].length; } if (ret == 0 && totallen > len) ret = ASN1_OVERFLOW; if (ret) { do { free(val[i].data); } while(i-- > 0); free(val); return ret; } len -= totallen; qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort); i = el->len - 1; do { p -= val[i].length; memcpy(p + 1, val[i].data, val[i].length); free(val[i].data); } while(i-- > 0); free(val); break; } case A1_OP_SEQOF: { struct template_of *el = DPO(data, t->offset); size_t ellen = sizeofType(t->ptr); size_t newsize; unsigned int i; unsigned char *elptr = el->val; if (el->len == 0) break; elptr += ellen * (el->len - 1); for (i = 0; i < el->len; i++) { ret = _asn1_encode(t->ptr, p, len, elptr, &newsize); if (ret) return ret; p -= newsize; len -= newsize; elptr -= ellen; } break; } case A1_OP_BMEMBER: { const struct asn1_template *bmember = t->ptr; size_t size = bmember->offset; size_t elements = A1_HEADER_LEN(bmember); size_t pos; unsigned char c = 0; unsigned int bitset = 0; int rfc1510 = (bmember->tt & A1_HBF_RFC1510); bmember += elements; if (rfc1510) pos = 31; else pos = bmember->offset; while (elements && len) { while (bmember->offset / 8 < pos / 8) { if (rfc1510 || bitset || c) { if (len < 1) return ASN1_OVERFLOW; *p-- = c; len--; } c = 0; pos -= 8; } bmember_put_bit(&c, data, bmember->offset, size, &bitset); elements--; bmember--; } if (rfc1510 || bitset) { if (len < 1) return ASN1_OVERFLOW; *p-- = c; len--; } if (len < 1) return ASN1_OVERFLOW; if (rfc1510 || bitset == 0) *p-- = 0; else *p-- = bitset - 1; len--; break; } case A1_OP_CHOICE: { const struct asn1_template *choice = t->ptr; const unsigned int *element = DPOC(data, choice->offset); size_t datalen; const void *el; if (*element > A1_HEADER_LEN(choice)) { printf("element: %d\n", *element); return ASN1_PARSE_ERROR; } if (*element == 0) { ret += der_put_octet_string(p, len, DPOC(data, choice->tt), &datalen); } else { choice += *element; el = DPOC(data, choice->offset); ret = _asn1_encode(choice->ptr, p, len, el, &datalen); if (ret) return ret; } len -= datalen; p -= datalen; break; } default: ABORT_ON_ERROR(); } t--; elements--; } if (size) *size = oldlen - len; return 0; } size_t _asn1_length(const struct asn1_template *t, const void *data) { size_t elements = A1_HEADER_LEN(t); size_t ret = 0; t += A1_HEADER_LEN(t); while (elements) { switch (t->tt & A1_OP_MASK) { case A1_OP_TYPE: case A1_OP_TYPE_EXTERN: { const void *el = DPOC(data, t->offset); if (t->tt & A1_FLAG_OPTIONAL) { void **pel = (void **)el; if (*pel == NULL) break; el = *pel; } if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { ret += _asn1_length(t->ptr, el); } else { const struct asn1_type_func *f = t->ptr; ret += (f->length)(el); } break; } case A1_OP_TAG: { size_t datalen; const void *olddata = data; data = DPO(data, t->offset); if (t->tt & A1_FLAG_OPTIONAL) { void **el = (void **)data; if (*el == NULL) { data = olddata; break; } data = *el; } datalen = _asn1_length(t->ptr, data); ret += der_length_tag(A1_TAG_TAG(t->tt)) + der_length_len(datalen); ret += datalen; data = olddata; break; } case A1_OP_PARSE: { unsigned int type = A1_PARSE_TYPE(t->tt); const void *el = DPOC(data, t->offset); if (type > sizeof(prim)/sizeof(prim[0])) { ABORT_ON_ERROR(); break; } ret += (prim[type].length)(el); break; } case A1_OP_SETOF: case A1_OP_SEQOF: { const struct template_of *el = DPOC(data, t->offset); size_t ellen = sizeofType(t->ptr); const unsigned char *element = el->val; unsigned int i; for (i = 0; i < el->len; i++) { ret += _asn1_length(t->ptr, element); element += ellen; } break; } case A1_OP_BMEMBER: { const struct asn1_template *bmember = t->ptr; size_t size = bmember->offset; size_t elements = A1_HEADER_LEN(bmember); int rfc1510 = (bmember->tt & A1_HBF_RFC1510); if (rfc1510) { ret += 5; } else { ret += 1; bmember += elements; while (elements) { if (bmember_isset_bit(data, bmember->offset, size)) { ret += (bmember->offset / 8) + 1; break; } elements--; bmember--; } } break; } case A1_OP_CHOICE: { const struct asn1_template *choice = t->ptr; const unsigned int *element = DPOC(data, choice->offset); if (*element > A1_HEADER_LEN(choice)) break; if (*element == 0) { ret += der_length_octet_string(DPOC(data, choice->tt)); } else { choice += *element; ret += _asn1_length(choice->ptr, DPOC(data, choice->offset)); } break; } default: ABORT_ON_ERROR(); break; } elements--; t--; } return ret; } void _asn1_free(const struct asn1_template *t, void *data) { size_t elements = A1_HEADER_LEN(t); if (t->tt & A1_HF_PRESERVE) der_free_octet_string(data); t++; while (elements) { switch (t->tt & A1_OP_MASK) { case A1_OP_TYPE: case A1_OP_TYPE_EXTERN: { void *el = DPO(data, t->offset); if (t->tt & A1_FLAG_OPTIONAL) { void **pel = (void **)el; if (*pel == NULL) break; el = *pel; } if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { _asn1_free(t->ptr, el); } else { const struct asn1_type_func *f = t->ptr; (f->release)(el); } if (t->tt & A1_FLAG_OPTIONAL) free(el); break; } case A1_OP_PARSE: { unsigned int type = A1_PARSE_TYPE(t->tt); void *el = DPO(data, t->offset); if (type > sizeof(prim)/sizeof(prim[0])) { ABORT_ON_ERROR(); break; } (prim[type].release)(el); break; } case A1_OP_TAG: { void *el = DPO(data, t->offset); if (t->tt & A1_FLAG_OPTIONAL) { void **pel = (void **)el; if (*pel == NULL) break; el = *pel; } _asn1_free(t->ptr, el); if (t->tt & A1_FLAG_OPTIONAL) free(el); break; } case A1_OP_SETOF: case A1_OP_SEQOF: { struct template_of *el = DPO(data, t->offset); size_t ellen = sizeofType(t->ptr); unsigned char *element = el->val; unsigned int i; for (i = 0; i < el->len; i++) { _asn1_free(t->ptr, element); element += ellen; } free(el->val); el->val = NULL; el->len = 0; break; } case A1_OP_BMEMBER: break; case A1_OP_CHOICE: { const struct asn1_template *choice = t->ptr; const unsigned int *element = DPOC(data, choice->offset); if (*element > A1_HEADER_LEN(choice)) break; if (*element == 0) { der_free_octet_string(DPO(data, choice->tt)); } else { choice += *element; _asn1_free(choice->ptr, DPO(data, choice->offset)); } break; } default: ABORT_ON_ERROR(); break; } t++; elements--; } } int _asn1_copy(const struct asn1_template *t, const void *from, void *to) { size_t elements = A1_HEADER_LEN(t); int ret = 0; int preserve = (t->tt & A1_HF_PRESERVE); t++; if (preserve) { ret = der_copy_octet_string(from, to); if (ret) return ret; } while (elements) { switch (t->tt & A1_OP_MASK) { case A1_OP_TYPE: case A1_OP_TYPE_EXTERN: { const void *fel = DPOC(from, t->offset); void *tel = DPO(to, t->offset); void **ptel = (void **)tel; size_t size; if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { size = sizeofType(t->ptr); } else { const struct asn1_type_func *f = t->ptr; size = f->size; } if (t->tt & A1_FLAG_OPTIONAL) { void **pfel = (void **)fel; if (*pfel == NULL) break; fel = *pfel; tel = *ptel = calloc(1, size); if (tel == NULL) return ENOMEM; } if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { ret = _asn1_copy(t->ptr, fel, tel); } else { const struct asn1_type_func *f = t->ptr; ret = (f->copy)(fel, tel); } if (ret) { if (t->tt & A1_FLAG_OPTIONAL) { free(*ptel); *ptel = NULL; } return ret; } break; } case A1_OP_PARSE: { unsigned int type = A1_PARSE_TYPE(t->tt); const void *fel = DPOC(from, t->offset); void *tel = DPO(to, t->offset); if (type > sizeof(prim)/sizeof(prim[0])) { ABORT_ON_ERROR(); return ASN1_PARSE_ERROR; } ret = (prim[type].copy)(fel, tel); if (ret) return ret; break; } case A1_OP_TAG: { const void *oldfrom = from; void *oldto = to; void **tel = NULL; from = DPOC(from, t->offset); to = DPO(to, t->offset); if (t->tt & A1_FLAG_OPTIONAL) { void **fel = (void **)from; tel = (void **)to; if (*fel == NULL) { from = oldfrom; to = oldto; break; } from = *fel; to = *tel = calloc(1, sizeofType(t->ptr)); if (to == NULL) return ENOMEM; } ret = _asn1_copy(t->ptr, from, to); if (ret) { if (t->tt & A1_FLAG_OPTIONAL) { free(*tel); *tel = NULL; } return ret; } from = oldfrom; to = oldto; break; } case A1_OP_SETOF: case A1_OP_SEQOF: { const struct template_of *fel = DPOC(from, t->offset); struct template_of *tel = DPO(to, t->offset); size_t ellen = sizeofType(t->ptr); unsigned int i; tel->val = calloc(fel->len, ellen); if (tel->val == NULL) return ENOMEM; tel->len = fel->len; for (i = 0; i < fel->len; i++) { ret = _asn1_copy(t->ptr, DPOC(fel->val, (i * ellen)), DPO(tel->val, (i *ellen))); if (ret) return ret; } break; } case A1_OP_BMEMBER: { const struct asn1_template *bmember = t->ptr; size_t size = bmember->offset; memcpy(to, from, size); break; } case A1_OP_CHOICE: { const struct asn1_template *choice = t->ptr; const unsigned int *felement = DPOC(from, choice->offset); unsigned int *telement = DPO(to, choice->offset); if (*felement > A1_HEADER_LEN(choice)) return ASN1_PARSE_ERROR; *telement = *felement; if (*felement == 0) { ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt)); } else { choice += *felement; ret = _asn1_copy(choice->ptr, DPOC(from, choice->offset), DPO(to, choice->offset)); } if (ret) return ret; break; } default: ABORT_ON_ERROR(); break; } t++; elements--; } return 0; } int _asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size) { int ret; memset(data, 0, t->offset); ret = _asn1_decode(t, flags, p, len, data, size); if (ret) { _asn1_free(t, data); memset(data, 0, t->offset); } return ret; } int _asn1_copy_top(const struct asn1_template *t, const void *from, void *to) { int ret; memset(to, 0, t->offset); ret = _asn1_copy(t, from, to); if (ret) { _asn1_free(t, to); memset(to, 0, t->offset); } return ret; } diff --git a/crypto/heimdal/lib/asn1/test.asn1 b/crypto/heimdal/lib/asn1/test.asn1 index 89154e337c8f..9dfd28a8ea2f 100644 --- a/crypto/heimdal/lib/asn1/test.asn1 +++ b/crypto/heimdal/lib/asn1/test.asn1 @@ -1,138 +1,140 @@ -- $Id$ -- TEST DEFINITIONS ::= BEGIN IMPORTS heim_any FROM heim; TESTuint32 ::= INTEGER (0..4294967295) +TESTuint64 ::= INTEGER(0..18446744073709551615) +TESTint64 ::= INTEGER(-9223372036854775808..9223372036854775807) TESTLargeTag ::= SEQUENCE { foo[127] INTEGER (-2147483648..2147483647), bar[128] 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), ... } TESTInteger ::= INTEGER (-2147483648..2147483647) TESTInteger2 ::= [4] IMPLICIT TESTInteger TESTInteger3 ::= [5] IMPLICIT TESTInteger2 TESTImplicit ::= SEQUENCE { ti1[0] IMPLICIT INTEGER (-2147483648..2147483647), ti2[1] IMPLICIT SEQUENCE { foo[127] INTEGER (-2147483648..2147483647) }, ti3[2] IMPLICIT [5] IMPLICIT [4] IMPLICIT INTEGER (-2147483648..2147483647) } TESTImplicit2 ::= SEQUENCE { ti1[0] IMPLICIT TESTInteger, ti2[1] IMPLICIT TESTLargeTag, ti3[2] IMPLICIT TESTInteger3 } TESTAllocInner ::= SEQUENCE { ai[0] TESTInteger } TESTAlloc ::= SEQUENCE { tagless TESTAllocInner OPTIONAL, three [1] INTEGER (-2147483648..2147483647), tagless2 heim_any OPTIONAL } TESTOptional ::= SEQUENCE { zero [0] INTEGER (-2147483648..2147483647) OPTIONAL, one [1] INTEGER (-2147483648..2147483647) OPTIONAL } TESTCONTAINING ::= OCTET STRING ( CONTAINING INTEGER ) TESTENCODEDBY ::= OCTET STRING ( ENCODED BY { joint-iso-itu-t(2) asn(1) ber-derived(2) distinguished-encoding(1) } ) TESTDer OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) asn(1) ber-derived(2) distinguished-encoding(1) } TESTCONTAININGENCODEDBY ::= OCTET STRING ( CONTAINING INTEGER ENCODED BY { joint-iso-itu-t(2) asn(1) ber-derived(2) distinguished-encoding(1) } ) TESTCONTAININGENCODEDBY2 ::= OCTET STRING ( CONTAINING INTEGER ENCODED BY TESTDer ) TESTValue1 INTEGER ::= 1 TESTUSERCONSTRAINED ::= OCTET STRING (CONSTRAINED BY { -- meh -- }) -- TESTUSERCONSTRAINED2 ::= OCTET STRING (CONSTRAINED BY { TESTInteger }) -- TESTUSERCONSTRAINED3 ::= OCTET STRING (CONSTRAINED BY { INTEGER }) -- TESTUSERCONSTRAINED4 ::= OCTET STRING (CONSTRAINED BY { INTEGER : 1 }) TESTSeqOf ::= SEQUENCE OF TESTInteger TESTSeqSizeOf1 ::= SEQUENCE SIZE (2) OF TESTInteger TESTSeqSizeOf2 ::= SEQUENCE SIZE (1..2) OF TESTInteger TESTSeqSizeOf3 ::= SEQUENCE SIZE (1..MAX) OF TESTInteger TESTSeqSizeOf4 ::= SEQUENCE SIZE (MIN..2) OF TESTInteger TESTOSSize1 ::= OCTET STRING SIZE (1..2) TESTSeqOfSeq ::= SEQUENCE OF SEQUENCE { zero [0] TESTInteger } TESTSeqOfSeq2 ::= SEQUENCE OF SEQUENCE { string [0] GeneralString } TESTSeqOfSeq3 ::= SEQUENCE OF SEQUENCE { zero [0] TESTInteger, string [0] GeneralString } TESTSeqOf2 ::= SEQUENCE { strings SEQUENCE OF GeneralString } TESTSeqOf3 ::= SEQUENCE { strings SEQUENCE OF GeneralString OPTIONAL } TESTPreserve ::= SEQUENCE { zero [0] TESTInteger, one [1] TESTInteger } TESTBitString ::= BIT STRING { zero(0), eight(8), thirtyone(31) } TESTMechType::= OBJECT IDENTIFIER TESTMechTypeList ::= SEQUENCE OF TESTMechType END