summaryrefslogtreecommitdiff
path: root/src/libstrongswan/asn1
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/asn1')
-rw-r--r--src/libstrongswan/asn1/asn1.c16
-rw-r--r--src/libstrongswan/asn1/asn1_parser.c70
-rw-r--r--src/libstrongswan/asn1/asn1_parser.h27
3 files changed, 84 insertions, 29 deletions
diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c
index 5ce840325..8b9dc1c48 100644
--- a/src/libstrongswan/asn1/asn1.c
+++ b/src/libstrongswan/asn1/asn1.c
@@ -350,13 +350,15 @@ time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
int tm_leap_4, tm_leap_100, tm_leap_400, tm_leap;
int tz_hour, tz_min, tz_offset;
time_t tm_days, tm_secs;
- u_char *eot = NULL;
+ char buf[BUF_LEN], *eot = NULL;
- if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL)
+ snprintf(buf, sizeof(buf), "%.*s", (int)utctime->len, utctime->ptr);
+
+ if ((eot = strchr(buf, 'Z')) != NULL)
{
tz_offset = 0; /* Zulu time with a zero time zone offset */
}
- else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL)
+ else if ((eot = strchr(buf, '+')) != NULL)
{
if (sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min) != 2)
{
@@ -364,7 +366,7 @@ time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
}
tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */
}
- else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL)
+ else if ((eot = strchr(buf, '-')) != NULL)
{
if (sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min) != 2)
{
@@ -382,15 +384,15 @@ time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d":
"%4d%2d%2d%2d%2d";
- if (sscanf(utctime->ptr, format, &tm_year, &tm_mon, &tm_day,
- &tm_hour, &tm_min) != 5)
+ if (sscanf(buf, format, &tm_year, &tm_mon, &tm_day,
+ &tm_hour, &tm_min) != 5)
{
return 0; /* error in [yy]yymmddhhmm time format */
}
}
/* is there a seconds field? */
- if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14))
+ if ((eot - buf) == ((type == ASN1_UTCTIME)?12:14))
{
if (sscanf(eot-2, "%2d", &tm_sec) != 1)
{
diff --git a/src/libstrongswan/asn1/asn1_parser.c b/src/libstrongswan/asn1/asn1_parser.c
index e7b7a428d..4d5f799b7 100644
--- a/src/libstrongswan/asn1/asn1_parser.c
+++ b/src/libstrongswan/asn1/asn1_parser.c
@@ -1,8 +1,7 @@
/*
* Copyright (C) 2006 Martin Will
- * Copyright (C) 2000-2008 Andreas Steffen
- *
- * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2000-2017 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
*
* 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
@@ -76,12 +75,18 @@ struct private_asn1_parser_t {
* Current parsing pointer for each level
*/
chunk_t blobs[ASN1_MAX_LEVEL + 2];
+
+ /**
+ * Parsing a CHOICE on the current level ?
+ */
+ bool choice[ASN1_MAX_LEVEL + 2];
+
};
METHOD(asn1_parser_t, iterate, bool,
private_asn1_parser_t *this, int *objectID, chunk_t *object)
{
- chunk_t *blob, *blob1;
+ chunk_t *blob, *blob1, blob_ori;
u_char *start_ptr;
u_int level;
asn1Object_t obj;
@@ -97,7 +102,7 @@ METHOD(asn1_parser_t, iterate, bool,
return FALSE;
}
- if (obj.flags & ASN1_END) /* end of loop or option found */
+ if (obj.flags & ASN1_END) /* end of loop or choice or option found */
{
if (this->loopAddr[obj.level] && this->blobs[obj.level+1].len > 0)
{
@@ -106,13 +111,42 @@ METHOD(asn1_parser_t, iterate, bool,
}
else
{
- this->loopAddr[obj.level] = 0; /* exit loop or option*/
+ this->loopAddr[obj.level] = 0; /* exit loop */
+
+ if (obj.flags & ASN1_CHOICE) /* end of choices */
+ {
+ if (this->choice[obj.level+1])
+ {
+ DBG1(DBG_ASN, "L%d - %s: incorrect choice encoding",
+ this->level0 + obj.level, obj.name);
+ this->success = FALSE;
+ goto end;
+ }
+ }
+
+ if (obj.flags & ASN1_CH) /* end of choice */
+ {
+ /* parsed a valid choice */
+ this->choice[obj.level] = FALSE;
+
+ /* advance to end of choices */
+ do
+ {
+ this->line++;
+ }
+ while (!((this->objects[this->line].flags & ASN1_END) &&
+ (this->objects[this->line].flags & ASN1_CHOICE) &&
+ (this->objects[this->line].level == obj.level-1)));
+ this->line--;
+ }
+
goto end;
}
}
level = this->level0 + obj.level;
blob = this->blobs + obj.level;
+ blob_ori = *blob;
blob1 = blob + 1;
start_ptr = blob->ptr;
@@ -129,7 +163,6 @@ METHOD(asn1_parser_t, iterate, bool,
}
/* handle ASN.1 options */
-
if ((obj.flags & ASN1_OPT)
&& (blob->len == 0 || *start_ptr != obj.type))
{
@@ -144,7 +177,6 @@ METHOD(asn1_parser_t, iterate, bool,
}
/* an ASN.1 object must possess at least a tag and length field */
-
if (blob->len < 2)
{
DBG1(DBG_ASN, "L%d - %s: ASN.1 object smaller than 2 octets",
@@ -167,8 +199,16 @@ METHOD(asn1_parser_t, iterate, bool,
blob->ptr += blob1->len;
blob->len -= blob1->len;
- /* return raw ASN.1 object without prior type checking */
+ /* handle ASN.1 choice without explicit context encoding */
+ if ((obj.flags & ASN1_CHOICE) && obj.type == ASN1_EOC)
+ {
+ DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
+ this->choice[obj.level+1] = TRUE;
+ *blob1 = blob_ori;
+ goto end;
+ }
+ /* return raw ASN.1 object without prior type checking */
if (obj.flags & ASN1_RAW)
{
DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
@@ -209,6 +249,18 @@ METHOD(asn1_parser_t, iterate, bool,
}
}
+ /* In case of a "CHOICE" start to scan for exactly one valid choice */
+ if (obj.flags & ASN1_CHOICE)
+ {
+ if (blob1->len == 0)
+ {
+ DBG1(DBG_ASN, "L%d - %s: contains no choice", level, obj.name);
+ this->success = FALSE;
+ goto end;
+ }
+ this->choice[obj.level+1] = TRUE;
+ }
+
if (obj.flags & ASN1_OBJ)
{
object->ptr = start_ptr;
diff --git a/src/libstrongswan/asn1/asn1_parser.h b/src/libstrongswan/asn1/asn1_parser.h
index 0edc22c23..2ee1e892f 100644
--- a/src/libstrongswan/asn1/asn1_parser.h
+++ b/src/libstrongswan/asn1/asn1_parser.h
@@ -1,8 +1,7 @@
/*
* Copyright (C) 2006 Martin Will
- * Copyright (C) 2000-2008 Andreas Steffen
- *
- * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2000-2017 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
*
* 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
@@ -32,15 +31,17 @@
/**
* Definition of ASN.1 flags
*/
-#define ASN1_NONE 0x00
-#define ASN1_DEF 0x01
-#define ASN1_OPT 0x02
-#define ASN1_LOOP 0x04
-#define ASN1_END 0x08
-#define ASN1_OBJ 0x10
-#define ASN1_BODY 0x20
-#define ASN1_RAW 0x40
-#define ASN1_EXIT 0x80
+#define ASN1_NONE 0x0000
+#define ASN1_DEF 0x0001
+#define ASN1_OPT 0x0002
+#define ASN1_LOOP 0x0004
+#define ASN1_CHOICE 0x0008
+#define ASN1_CH 0x0010
+#define ASN1_END 0x0020
+#define ASN1_OBJ 0x0040
+#define ASN1_BODY 0x0080
+#define ASN1_RAW 0x0100
+#define ASN1_EXIT 0x0200
typedef struct asn1Object_t asn1Object_t;
@@ -51,7 +52,7 @@ struct asn1Object_t{
u_int level;
const u_char *name;
asn1_t type;
- u_char flags;
+ uint16_t flags;
};
typedef struct asn1_parser_t asn1_parser_t;