asn1: Teach template backend to DEFAULT
This commit is contained in:
@@ -38,6 +38,11 @@
|
|||||||
#ifndef __TEMPLATE_H__
|
#ifndef __TEMPLATE_H__
|
||||||
#define __TEMPLATE_H__
|
#define __TEMPLATE_H__
|
||||||
|
|
||||||
|
/* header:
|
||||||
|
* HF flags if not a BIT STRING type
|
||||||
|
* HBF flags if a BIT STRING type
|
||||||
|
*/
|
||||||
|
|
||||||
/* tag:
|
/* tag:
|
||||||
* 0..20 tag
|
* 0..20 tag
|
||||||
* 21 type
|
* 21 type
|
||||||
@@ -53,6 +58,11 @@
|
|||||||
* 28..31 op
|
* 28..31 op
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* defval: (next template entry is defaulted)
|
||||||
|
*
|
||||||
|
* DV flags (ptr is or points to defval)
|
||||||
|
*/
|
||||||
|
|
||||||
#define A1_OP_MASK (0xf0000000)
|
#define A1_OP_MASK (0xf0000000)
|
||||||
#define A1_OP_TYPE (0x10000000)
|
#define A1_OP_TYPE (0x10000000)
|
||||||
#define A1_OP_TYPE_EXTERN (0x20000000)
|
#define A1_OP_TYPE_EXTERN (0x20000000)
|
||||||
@@ -62,10 +72,12 @@
|
|||||||
#define A1_OP_SETOF (0x60000000)
|
#define A1_OP_SETOF (0x60000000)
|
||||||
#define A1_OP_BMEMBER (0x70000000)
|
#define A1_OP_BMEMBER (0x70000000)
|
||||||
#define A1_OP_CHOICE (0x80000000)
|
#define A1_OP_CHOICE (0x80000000)
|
||||||
|
#define A1_OP_DEFVAL (0x90000000)
|
||||||
|
|
||||||
#define A1_FLAG_MASK (0x0f000000)
|
#define A1_FLAG_MASK (0x0f000000)
|
||||||
#define A1_FLAG_OPTIONAL (0x01000000)
|
#define A1_FLAG_OPTIONAL (0x01000000)
|
||||||
#define A1_FLAG_IMPLICIT (0x02000000)
|
#define A1_FLAG_IMPLICIT (0x02000000)
|
||||||
|
#define A1_FLAG_DEFAULT (0x04000000)
|
||||||
|
|
||||||
#define A1_TAG_T(CLASS,TYPE,TAG) ((A1_OP_TAG) | (((CLASS) << 22) | ((TYPE) << 21) | (TAG)))
|
#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_CLASS(x) (((x) >> 22) & 0x3)
|
||||||
@@ -87,6 +99,12 @@
|
|||||||
|
|
||||||
#define A1_HBF_RFC1510 0x1
|
#define A1_HBF_RFC1510 0x1
|
||||||
|
|
||||||
|
#define A1_DV_BOOLEAN 0x01
|
||||||
|
#define A1_DV_INTEGER 0x02
|
||||||
|
#define A1_DV_INTEGER32 0x04
|
||||||
|
#define A1_DV_INTEGER64 0x08
|
||||||
|
#define A1_DV_UTF8STRING 0x10
|
||||||
|
|
||||||
|
|
||||||
struct asn1_template {
|
struct asn1_template {
|
||||||
uint32_t tt;
|
uint32_t tt;
|
||||||
|
@@ -1888,6 +1888,71 @@ test_seqof5(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmp_default(void *a, void *b)
|
||||||
|
{
|
||||||
|
TESTDefault *aa = a;
|
||||||
|
TESTDefault *ab = b;
|
||||||
|
|
||||||
|
COMPARE_STRING(aa,ab,name);
|
||||||
|
COMPARE_INTEGER(aa,ab,version);
|
||||||
|
COMPARE_INTEGER(aa,ab,maxint);
|
||||||
|
COMPARE_INTEGER(aa,ab,works);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
test_default(void)
|
||||||
|
{
|
||||||
|
struct test_case tests[] = {
|
||||||
|
{ NULL, 2, "\x30\x00", NULL },
|
||||||
|
{ NULL, 25,
|
||||||
|
"\x30\x17\x0c\x07\x68\x65\x69\x6d\x64\x61"
|
||||||
|
"\x6c\xa0\x03\x02\x01\x07\x02\x04\x7f\xff"
|
||||||
|
"\xff\xff\x01\x01\x00",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{ NULL, 10,
|
||||||
|
"\x30\x08\xa0\x03\x02\x01\x07\x01\x01\x00",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{ NULL, 17,
|
||||||
|
"\x30\x0f\x0c\x07\x68\x65\x69\x6d\x64\x61\x6c\x02\x04"
|
||||||
|
"\x7f\xff\xff\xff",
|
||||||
|
NULL
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TESTDefault values[] = {
|
||||||
|
{ "Heimdal", 8, 9223372036854775807, 1 },
|
||||||
|
{ "heimdal", 7, 2147483647, 0 },
|
||||||
|
{ "Heimdal", 7, 9223372036854775807, 0 },
|
||||||
|
{ "heimdal", 8, 2147483647, 1 },
|
||||||
|
};
|
||||||
|
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, "TESTDefault %d", i) < 0)
|
||||||
|
errx(1, "malloc");
|
||||||
|
if (tests[i].name == NULL)
|
||||||
|
errx(1, "malloc");
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = generic_test (tests, ntests, sizeof(TESTDefault),
|
||||||
|
(generic_encode)encode_TESTDefault,
|
||||||
|
(generic_length)length_TESTDefault,
|
||||||
|
(generic_decode)decode_TESTDefault,
|
||||||
|
(generic_free)free_TESTDefault,
|
||||||
|
cmp_default,
|
||||||
|
(generic_copy)copy_TESTDefault);
|
||||||
|
for (i = 0; i < ntests; ++i)
|
||||||
|
free(tests[i].name);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
test_x690sample(void)
|
test_x690sample(void)
|
||||||
{
|
{
|
||||||
@@ -2005,5 +2070,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
DO_ONE(test_x690sample);
|
DO_ONE(test_x690sample);
|
||||||
|
|
||||||
|
DO_ONE(test_default);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -54,6 +54,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gen_locl.h"
|
#include "gen_locl.h"
|
||||||
|
#include <vis.h>
|
||||||
|
|
||||||
static const char *symbol_name(const char *, const Type *);
|
static const char *symbol_name(const char *, const Type *);
|
||||||
static void generate_template_type(const char *, const char **, const char *, const char *, const char *,
|
static void generate_template_type(const char *, const char **, const char *, const char *, const char *,
|
||||||
@@ -182,8 +183,7 @@ bitstring_symbol(const char *basename, const Type *t)
|
|||||||
|
|
||||||
|
|
||||||
/* XXX Make sure this is sorted by `type' and can just index this by type */
|
/* XXX Make sure this is sorted by `type' and can just index this by type */
|
||||||
/* XXX Make this const! */
|
const struct {
|
||||||
struct {
|
|
||||||
enum typetype type;
|
enum typetype type;
|
||||||
const char *(*symbol_name)(const char *, const Type *);
|
const char *(*symbol_name)(const char *, const Type *);
|
||||||
int is_struct;
|
int is_struct;
|
||||||
@@ -499,7 +499,109 @@ compact_tag(const Type *t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
template_members(struct templatehead *temp, const char *basetype, const char *name, const Type *t, int optional, int implicit, int isstruct, int need_offset)
|
defval(struct templatehead *temp, Member *m)
|
||||||
|
{
|
||||||
|
switch (m->defval->type) {
|
||||||
|
case booleanvalue:
|
||||||
|
add_line(temp, "{ A1_OP_DEFVAL|A1_DV_BOOLEAN, ~0, (void *)%u }",
|
||||||
|
m->defval->u.booleanvalue);
|
||||||
|
break;
|
||||||
|
case nullvalue:
|
||||||
|
add_line(temp, "{ A1_OP_DEFVAL|A1_DV_NULL, ~0, (void *)0 }");
|
||||||
|
break;
|
||||||
|
case integervalue: {
|
||||||
|
const char *dv = "A1_DV_INTEGER";
|
||||||
|
Type *t = m->type;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (t->range)
|
||||||
|
break;
|
||||||
|
if (t->type == TInteger && t->members)
|
||||||
|
break;
|
||||||
|
if (t->type == TEnumerated)
|
||||||
|
break;
|
||||||
|
if (t->subtype)
|
||||||
|
t = t->subtype;
|
||||||
|
else if (t->symbol && t->symbol->type)
|
||||||
|
t = t->symbol->type;
|
||||||
|
else
|
||||||
|
errx(1, "DEFAULT values for unconstrained INTEGER members not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t->members)
|
||||||
|
dv = "A1_DV_INTEGER32"; /* XXX Enum size assumptions! No good! */
|
||||||
|
else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX)
|
||||||
|
dv = "A1_DV_INTEGER64";
|
||||||
|
else if (t->range->min >= 0 && t->range->max > UINT_MAX)
|
||||||
|
dv = "A1_DV_INTEGER64";
|
||||||
|
else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX)
|
||||||
|
dv = "A1_DV_INTEGER32";
|
||||||
|
else if (t->range->min >= 0 && t->range->max <= UINT_MAX)
|
||||||
|
dv = "A1_DV_INTEGER32";
|
||||||
|
else
|
||||||
|
errx(1, "unsupported range %lld -> %lld",
|
||||||
|
(long long)m->type->range->min, (long long)m->type->range->max);
|
||||||
|
add_line(temp, "{ A1_OP_DEFVAL|%s, ~0, (void *)%llu }",
|
||||||
|
dv, (long long)m->defval->u.integervalue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case stringvalue: {
|
||||||
|
char *quoted;
|
||||||
|
|
||||||
|
if (rk_strasvis("ed, m->defval->u.stringvalue,
|
||||||
|
VIS_CSTYLE | VIS_DQ | VIS_NL, "") < 0)
|
||||||
|
err(1, "Could not quote a string");
|
||||||
|
add_line(temp, "{ A1_OP_DEFVAL|A1_DV_UTF8STRING, ~0, (void *)\"%s\" }",
|
||||||
|
quoted);
|
||||||
|
free(quoted);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case objectidentifiervalue: {
|
||||||
|
struct objid *o;
|
||||||
|
size_t sz = sizeof("{ }");
|
||||||
|
char *s, *p;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
for (o = m->defval->u.objectidentifiervalue; o != NULL; o = o->next) {
|
||||||
|
if ((len = snprintf(0, 0, " %d", o->value)) < 0)
|
||||||
|
err(1, "Could not format integer");
|
||||||
|
sz += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p = s = malloc(sz)) == NULL)
|
||||||
|
err(1, "Could not allocate string");
|
||||||
|
|
||||||
|
len = snprintf(p, sz, "{");
|
||||||
|
sz -= len;
|
||||||
|
p += len;
|
||||||
|
for (o = m->defval->u.objectidentifiervalue; o != NULL; o = o->next) {
|
||||||
|
if ((len = snprintf(p, sz, " %d", o->value)) < 0 || len > sz - 1)
|
||||||
|
err(1, "Could not format integer");
|
||||||
|
sz -= len;
|
||||||
|
p += len;
|
||||||
|
}
|
||||||
|
len = snprintf(p, sz, " }");
|
||||||
|
sz -= len;
|
||||||
|
p += len;
|
||||||
|
|
||||||
|
add_line(temp, "{ A1_OP_DEFVAL|A1_DV_INTEGER, ~0, (void *)\"%s\" }", s);
|
||||||
|
free(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
template_members(struct templatehead *temp,
|
||||||
|
const char *basetype,
|
||||||
|
const char *name,
|
||||||
|
const Type *t,
|
||||||
|
int optional,
|
||||||
|
int defaulted,
|
||||||
|
int implicit,
|
||||||
|
int isstruct,
|
||||||
|
int need_offset)
|
||||||
{
|
{
|
||||||
char *poffset = NULL;
|
char *poffset = NULL;
|
||||||
|
|
||||||
@@ -511,15 +613,17 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
|
|||||||
switch (t->type) {
|
switch (t->type) {
|
||||||
case TType:
|
case TType:
|
||||||
if (use_extern(t->symbol)) {
|
if (use_extern(t->symbol)) {
|
||||||
add_line(temp, "{ A1_OP_TYPE_EXTERN %s%s, %s, &asn1_extern_%s}",
|
add_line(temp, "{ A1_OP_TYPE_EXTERN %s%s%s, %s, &asn1_extern_%s}",
|
||||||
optional ? "|A1_FLAG_OPTIONAL" : "",
|
optional ? "|A1_FLAG_OPTIONAL" : "",
|
||||||
implicit ? "|A1_FLAG_IMPLICIT" : "",
|
defaulted ? "|A1_FLAG_DEFAULT" : "",
|
||||||
|
implicit ? "|A1_FLAG_IMPLICIT" : "",
|
||||||
poffset, t->symbol->gen_name);
|
poffset, t->symbol->gen_name);
|
||||||
} else {
|
} else {
|
||||||
add_line_pointer(temp, t->symbol->gen_name, poffset,
|
add_line_pointer(temp, t->symbol->gen_name, poffset,
|
||||||
"A1_OP_TYPE %s%s",
|
"A1_OP_TYPE %s%s%s",
|
||||||
optional ? "|A1_FLAG_OPTIONAL" : "",
|
optional ? "|A1_FLAG_OPTIONAL" : "",
|
||||||
implicit ? "|A1_FLAG_IMPLICIT" : "");
|
defaulted ? "|A1_FLAG_DEFAULT" : "",
|
||||||
|
implicit ? "|A1_FLAG_IMPLICIT" : "");
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -650,7 +754,10 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
|
|||||||
if (newbasename == NULL)
|
if (newbasename == NULL)
|
||||||
errx(1, "malloc");
|
errx(1, "malloc");
|
||||||
|
|
||||||
template_members(temp, newbasename, m->gen_name, m->type, m->optional, 0, isstruct, 1);
|
if (m->defval)
|
||||||
|
defval(temp, m);
|
||||||
|
|
||||||
|
template_members(temp, newbasename, m->gen_name, m->type, m->optional, m->defval ? 1 : 0, 0, isstruct, 1);
|
||||||
|
|
||||||
free(newbasename);
|
free(newbasename);
|
||||||
}
|
}
|
||||||
@@ -676,7 +783,10 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
|
|||||||
if (newbasename == NULL)
|
if (newbasename == NULL)
|
||||||
errx(1, "malloc");
|
errx(1, "malloc");
|
||||||
|
|
||||||
template_members(temp, newbasename, m->gen_name, m->type, m->optional, 0, isstruct, 1);
|
if (m->defval)
|
||||||
|
defval(temp, m);
|
||||||
|
|
||||||
|
template_members(temp, newbasename, m->gen_name, m->type, m->optional, m->defval ? 1 : 0, 0, isstruct, 1);
|
||||||
|
|
||||||
free(newbasename);
|
free(newbasename);
|
||||||
}
|
}
|
||||||
@@ -720,11 +830,12 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
|
|||||||
t->subtype, 0, subtype_is_struct, 0);
|
t->subtype, 0, subtype_is_struct, 0);
|
||||||
|
|
||||||
add_line_pointer(temp, dupname, poffset,
|
add_line_pointer(temp, dupname, poffset,
|
||||||
"A1_TAG_T(%s,%s,%s)%s%s",
|
"A1_TAG_T(%s,%s,%s)%s%s%s",
|
||||||
classname(t->tag.tagclass),
|
classname(t->tag.tagclass),
|
||||||
prim ? "PRIM" : "CONS",
|
prim ? "PRIM" : "CONS",
|
||||||
valuename(t->tag.tagclass, t->tag.tagvalue),
|
valuename(t->tag.tagclass, t->tag.tagvalue),
|
||||||
optional ? "|A1_FLAG_OPTIONAL" : "",
|
optional ? "|A1_FLAG_OPTIONAL" : "",
|
||||||
|
defaulted ? "|A1_FLAG_DEFAULT" : "",
|
||||||
tagimplicit ? "|A1_FLAG_IMPLICIT" : "");
|
tagimplicit ? "|A1_FLAG_IMPLICIT" : "");
|
||||||
|
|
||||||
free(tname);
|
free(tname);
|
||||||
@@ -900,7 +1011,9 @@ generate_template_type(const char *varname,
|
|||||||
const char *basetype,
|
const char *basetype,
|
||||||
const char *name,
|
const char *name,
|
||||||
Type *type,
|
Type *type,
|
||||||
int optional, int isstruct, int need_offset)
|
int optional,
|
||||||
|
int isstruct,
|
||||||
|
int need_offset)
|
||||||
{
|
{
|
||||||
struct tlist *tl;
|
struct tlist *tl;
|
||||||
const char *d;
|
const char *d;
|
||||||
@@ -920,7 +1033,8 @@ generate_template_type(const char *varname,
|
|||||||
implicit = (type->tag.tagenv == TE_IMPLICIT);
|
implicit = (type->tag.tagenv == TE_IMPLICIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
template_members(&tl->template, basetype, name, type, optional, implicit, isstruct, need_offset);
|
template_members(&tl->template, basetype, name, type, optional, 0,
|
||||||
|
implicit, isstruct, need_offset);
|
||||||
|
|
||||||
/* if its a sequence or set type, check if there is a ellipsis */
|
/* if its a sequence or set type, check if there is a ellipsis */
|
||||||
if (type->type == TSequence || type->type == TSet) {
|
if (type->type == TSequence || type->type == TSet) {
|
||||||
|
@@ -209,6 +209,7 @@ int
|
|||||||
_asn1_decode(const struct asn1_template *t, unsigned flags,
|
_asn1_decode(const struct asn1_template *t, unsigned flags,
|
||||||
const unsigned char *p, size_t len, void *data, size_t *size)
|
const unsigned char *p, size_t len, void *data, size_t *size)
|
||||||
{
|
{
|
||||||
|
const struct asn1_template *tdefval = NULL;
|
||||||
size_t elements = A1_HEADER_LEN(t);
|
size_t elements = A1_HEADER_LEN(t);
|
||||||
size_t oldlen = len;
|
size_t oldlen = len;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -223,6 +224,9 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
|||||||
|
|
||||||
while (elements) {
|
while (elements) {
|
||||||
switch (t->tt & A1_OP_MASK) {
|
switch (t->tt & A1_OP_MASK) {
|
||||||
|
case A1_OP_DEFVAL:
|
||||||
|
tdefval = t;
|
||||||
|
break;
|
||||||
case A1_OP_TYPE:
|
case A1_OP_TYPE:
|
||||||
case A1_OP_TYPE_EXTERN: {
|
case A1_OP_TYPE_EXTERN: {
|
||||||
size_t newsize, elsize;
|
size_t newsize, elsize;
|
||||||
@@ -250,10 +254,45 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
|||||||
}
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (t->tt & A1_FLAG_OPTIONAL) {
|
if (t->tt & A1_FLAG_OPTIONAL) {
|
||||||
|
/*
|
||||||
|
* Optional field not present in encoding, presumably,
|
||||||
|
* though we should really look more carefully at `ret'.
|
||||||
|
*/
|
||||||
free(*pel);
|
free(*pel);
|
||||||
*pel = NULL;
|
*pel = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
} else if (t->tt & A1_FLAG_DEFAULT) {
|
||||||
|
/*
|
||||||
|
* Defaulted field not present in encoding, presumably,
|
||||||
|
* though we should really look more carefully at `ret'.
|
||||||
|
*/
|
||||||
|
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||||
|
int *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
*i = tdefval->ptr ? 1 : 0;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||||
|
int64_t *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
*i = (int64_t)(intptr_t)tdefval->ptr;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||||
|
int32_t *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
*i = (int32_t)(intptr_t)tdefval->ptr;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||||
|
struct heim_integer *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
if ((ret = der_copy_heim_integer(tdefval->ptr, i)))
|
||||||
|
return ret;
|
||||||
|
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||||
|
char **s = el;
|
||||||
|
|
||||||
|
if ((*s = strdup(tdefval->ptr)) == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
p += newsize; len -= newsize;
|
p += newsize; len -= newsize;
|
||||||
@@ -269,6 +308,8 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
|||||||
int subflags = flags;
|
int subflags = flags;
|
||||||
int replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
|
int replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
|
||||||
|
|
||||||
|
data = DPO(data, t->offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX If this type (chasing t->ptr through IMPLICIT tags, if this
|
* XXX If this type (chasing t->ptr through IMPLICIT tags, if this
|
||||||
* one is too, till we find a non-TTag) is a [UNIVERSAL SET] type,
|
* one is too, till we find a non-TTag) is a [UNIVERSAL SET] type,
|
||||||
@@ -283,8 +324,42 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
|||||||
&dertype, A1_TAG_TAG(t->tt),
|
&dertype, A1_TAG_TAG(t->tt),
|
||||||
&datalen, &l);
|
&datalen, &l);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (t->tt & A1_FLAG_OPTIONAL)
|
if (t->tt & A1_FLAG_OPTIONAL) {
|
||||||
|
data = olddata;
|
||||||
break;
|
break;
|
||||||
|
} else if (t->tt & A1_FLAG_DEFAULT) {
|
||||||
|
/*
|
||||||
|
* Defaulted field not present in encoding, presumably,
|
||||||
|
* though we should really look more carefully at `ret'.
|
||||||
|
*/
|
||||||
|
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||||
|
int *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
*i = tdefval->ptr ? 1 : 0;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||||
|
int64_t *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
*i = (int64_t)(intptr_t)tdefval->ptr;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||||
|
int32_t *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
*i = (int32_t)(intptr_t)tdefval->ptr;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||||
|
struct heim_integer *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
if ((ret = der_copy_heim_integer(tdefval->ptr, i)))
|
||||||
|
return ret;
|
||||||
|
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||||
|
char **s = data;
|
||||||
|
|
||||||
|
if ((*s = strdup(tdefval->ptr)) == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
data = olddata;
|
||||||
|
break;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,8 +391,6 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
|||||||
} else if (datalen > len)
|
} else if (datalen > len)
|
||||||
return ASN1_OVERRUN;
|
return ASN1_OVERRUN;
|
||||||
|
|
||||||
data = DPO(data, t->offset);
|
|
||||||
|
|
||||||
if (t->tt & A1_FLAG_OPTIONAL) {
|
if (t->tt & A1_FLAG_OPTIONAL) {
|
||||||
void **el = (void **)data;
|
void **el = (void **)data;
|
||||||
size_t ellen = _asn1_sizeofType(t->ptr);
|
size_t ellen = _asn1_sizeofType(t->ptr);
|
||||||
@@ -484,7 +557,7 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
|||||||
|
|
||||||
/* provide a saner value as default, we should have a NO element value */
|
/* provide a saner value as default, we should have a NO element value */
|
||||||
*element = 1;
|
*element = 1;
|
||||||
|
|
||||||
for (i = 1; i < A1_HEADER_LEN(choice) + 1; i++) {
|
for (i = 1; i < A1_HEADER_LEN(choice) + 1; i++) {
|
||||||
/* should match first tag instead, store it in choice.tt */
|
/* should match first tag instead, store it in choice.tt */
|
||||||
ret = _asn1_decode(choice[i].ptr, 0, p, len,
|
ret = _asn1_decode(choice[i].ptr, 0, p, len,
|
||||||
@@ -556,6 +629,7 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
|
|||||||
|
|
||||||
while (elements) {
|
while (elements) {
|
||||||
switch (t->tt & A1_OP_MASK) {
|
switch (t->tt & A1_OP_MASK) {
|
||||||
|
case A1_OP_DEFVAL: break;
|
||||||
case A1_OP_TYPE:
|
case A1_OP_TYPE:
|
||||||
case A1_OP_TYPE_EXTERN: {
|
case A1_OP_TYPE_EXTERN: {
|
||||||
size_t newsize;
|
size_t newsize;
|
||||||
@@ -566,7 +640,40 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
|
|||||||
if (*pel == NULL)
|
if (*pel == NULL)
|
||||||
break;
|
break;
|
||||||
el = *pel;
|
el = *pel;
|
||||||
}
|
} else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
|
||||||
|
const struct asn1_template *tdefval = t - 1;
|
||||||
|
/* Compare tdefval to whatever's at `el' */
|
||||||
|
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||||
|
const int *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
|
||||||
|
break;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||||
|
const int64_t *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
if (*i == (int64_t)(intptr_t)tdefval->ptr)
|
||||||
|
break;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||||
|
const int32_t *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
|
||||||
|
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
|
||||||
|
*i == (int32_t)(intptr_t)tdefval->ptr)
|
||||||
|
break;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||||
|
const struct heim_integer *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
|
||||||
|
break;
|
||||||
|
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||||
|
const char * const *s = el;
|
||||||
|
|
||||||
|
if (*s && strcmp(*s, tdefval->ptr) == 0)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
|
if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
|
||||||
ret = _asn1_encode(t->ptr, p, len, el, &newsize);
|
ret = _asn1_encode(t->ptr, p, len, el, &newsize);
|
||||||
@@ -605,7 +712,46 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
data = *el;
|
data = *el;
|
||||||
}
|
} else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
|
||||||
|
const struct asn1_template *tdefval = t - 1;
|
||||||
|
int exclude = 0;
|
||||||
|
|
||||||
|
/* Compare tdefval to whatever's at `data' */
|
||||||
|
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||||
|
const int *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
|
||||||
|
exclude = 1;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||||
|
const int64_t *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
if (*i == (int64_t)(intptr_t)tdefval->ptr)
|
||||||
|
exclude = 1;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||||
|
const int32_t *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
|
||||||
|
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
|
||||||
|
*i == (int32_t)(intptr_t)tdefval->ptr)
|
||||||
|
exclude = 1;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||||
|
const struct heim_integer *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
|
||||||
|
break;
|
||||||
|
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||||
|
const char * const *s = data;
|
||||||
|
|
||||||
|
if (*s && strcmp(*s, tdefval->ptr) == 0)
|
||||||
|
exclude = 1;
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if (exclude) {
|
||||||
|
data = olddata;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
|
replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
|
||||||
|
|
||||||
@@ -880,6 +1026,7 @@ _asn1_length(const struct asn1_template *t, const void *data)
|
|||||||
|
|
||||||
while (elements) {
|
while (elements) {
|
||||||
switch (t->tt & A1_OP_MASK) {
|
switch (t->tt & A1_OP_MASK) {
|
||||||
|
case A1_OP_DEFVAL: break;
|
||||||
case A1_OP_TYPE:
|
case A1_OP_TYPE:
|
||||||
case A1_OP_TYPE_EXTERN: {
|
case A1_OP_TYPE_EXTERN: {
|
||||||
const void *el = DPOC(data, t->offset);
|
const void *el = DPOC(data, t->offset);
|
||||||
@@ -889,7 +1036,41 @@ _asn1_length(const struct asn1_template *t, const void *data)
|
|||||||
if (*pel == NULL)
|
if (*pel == NULL)
|
||||||
break;
|
break;
|
||||||
el = *pel;
|
el = *pel;
|
||||||
}
|
} else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
|
||||||
|
const struct asn1_template *tdefval = t - 1;
|
||||||
|
|
||||||
|
/* Compare tdefval to whatever's at `el' */
|
||||||
|
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||||
|
const int *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
|
||||||
|
break;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||||
|
const int64_t *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
if (*i == (int64_t)(intptr_t)tdefval->ptr)
|
||||||
|
break;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||||
|
const int32_t *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
|
||||||
|
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
|
||||||
|
*i == (int32_t)(intptr_t)tdefval->ptr)
|
||||||
|
break;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||||
|
const struct heim_integer *i = (void *)(char *)el;
|
||||||
|
|
||||||
|
if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
|
||||||
|
break;
|
||||||
|
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||||
|
const char * const *s = el;
|
||||||
|
|
||||||
|
if (*s && strcmp(*s, tdefval->ptr) == 0)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
|
if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
|
||||||
ret += _asn1_length(t->ptr, el);
|
ret += _asn1_length(t->ptr, el);
|
||||||
@@ -913,7 +1094,46 @@ _asn1_length(const struct asn1_template *t, const void *data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
data = *el;
|
data = *el;
|
||||||
}
|
} else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
|
||||||
|
const struct asn1_template *tdefval = t - 1;
|
||||||
|
int exclude = 0;
|
||||||
|
|
||||||
|
/* Compare tdefval to whatever's at `data' */
|
||||||
|
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||||
|
const int *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
|
||||||
|
exclude = 1;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||||
|
const int64_t *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
if (*i == (int64_t)(intptr_t)tdefval->ptr)
|
||||||
|
exclude = 1;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||||
|
const int32_t *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
|
||||||
|
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
|
||||||
|
*i == (int32_t)(intptr_t)tdefval->ptr)
|
||||||
|
exclude = 1;
|
||||||
|
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||||
|
const struct heim_integer *i = (void *)(char *)data;
|
||||||
|
|
||||||
|
if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
|
||||||
|
exclude = 1;
|
||||||
|
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||||
|
const char * const *s = data;
|
||||||
|
|
||||||
|
if (*s && strcmp(*s, tdefval->ptr) == 0)
|
||||||
|
exclude = 1;
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if (exclude) {
|
||||||
|
data = olddata;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (t->tt & A1_FLAG_IMPLICIT)
|
if (t->tt & A1_FLAG_IMPLICIT)
|
||||||
oldtaglen = inner_type_taglen(t->ptr);
|
oldtaglen = inner_type_taglen(t->ptr);
|
||||||
@@ -1011,6 +1231,7 @@ _asn1_free(const struct asn1_template *t, void *data)
|
|||||||
|
|
||||||
while (elements) {
|
while (elements) {
|
||||||
switch (t->tt & A1_OP_MASK) {
|
switch (t->tt & A1_OP_MASK) {
|
||||||
|
case A1_OP_DEFVAL: break;
|
||||||
case A1_OP_TYPE:
|
case A1_OP_TYPE:
|
||||||
case A1_OP_TYPE_EXTERN: {
|
case A1_OP_TYPE_EXTERN: {
|
||||||
void *el = DPO(data, t->offset);
|
void *el = DPO(data, t->offset);
|
||||||
@@ -1121,6 +1342,7 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to)
|
|||||||
|
|
||||||
while (elements) {
|
while (elements) {
|
||||||
switch (t->tt & A1_OP_MASK) {
|
switch (t->tt & A1_OP_MASK) {
|
||||||
|
case A1_OP_DEFVAL: break;
|
||||||
case A1_OP_TYPE:
|
case A1_OP_TYPE:
|
||||||
case A1_OP_TYPE_EXTERN: {
|
case A1_OP_TYPE_EXTERN: {
|
||||||
const void *fel = DPOC(from, t->offset);
|
const void *fel = DPOC(from, t->offset);
|
||||||
|
@@ -26,13 +26,19 @@ TESTOutOfOrderBar ::= SEQUENCE {
|
|||||||
-- which we well might since XDR's syntax is a dual of a strict subset of
|
-- which we well might since XDR's syntax is a dual of a strict subset of
|
||||||
-- ASN.1, and since XDR the encoding is fairly straightforward.
|
-- ASN.1, and since XDR the encoding is fairly straightforward.
|
||||||
--
|
--
|
||||||
-- Note that the `next' member has to be OPTIONAL or DEFAULTed for this to
|
-- Note that the `next' member has to be OPTIONAL for this to work.
|
||||||
-- work.
|
|
||||||
TESTCircular ::= SEQUENCE {
|
TESTCircular ::= SEQUENCE {
|
||||||
name UTF8String,
|
name UTF8String,
|
||||||
next TESTCircular OPTIONAL
|
next TESTCircular OPTIONAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TESTDefault ::= SEQUENCE {
|
||||||
|
name UTF8String DEFAULT "Heimdal",
|
||||||
|
version [0] TESTuint32 DEFAULT 8,
|
||||||
|
maxint TESTuint64 DEFAULT 9223372036854775807,
|
||||||
|
works BOOLEAN DEFAULT TRUE
|
||||||
|
}
|
||||||
|
|
||||||
TESTuint32 ::= INTEGER (0..4294967295)
|
TESTuint32 ::= INTEGER (0..4294967295)
|
||||||
TESTuint64 ::= INTEGER(0..9223372036854775807)
|
TESTuint64 ::= INTEGER(0..9223372036854775807)
|
||||||
TESTint64 ::= INTEGER(-9223372036854775808..9223372036854775807)
|
TESTint64 ::= INTEGER(-9223372036854775808..9223372036854775807)
|
||||||
|
Reference in New Issue
Block a user