-
Notifications
You must be signed in to change notification settings - Fork 0
/
ngx_http_est_asn1.c
112 lines (100 loc) · 3.09 KB
/
ngx_http_est_asn1.c
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include "ngx_http_est.h"
ngx_int_t
ngx_http_est_asn1_parse(ngx_array_t *array, const unsigned char **data, size_t length, off_t offset) {
ASN1_OBJECT *obj;
ngx_str_t *attribute;
const unsigned char *end, *p1, *p2, *p3, *p4;
char buf[128];
int class, header, ret, tag, val;
long len;
/*
This function is intended to parse through an ASN.1 structure, identifying
object identifiers contained therein. This function has been drawn from the
libest library within which the corresponding function has been derived from
the OpenSSL library.
*/
obj = NULL;
p1 = *data;
end = p1 + length;
p2 = p1 - 1;
while ((p1 < end) && (p2 < p1)) {
p2 = p1;
val = ASN1_get_object(&p1, &len, &tag, &class, length);
if (val & 0x80) {
*data = p1;
return -1;
}
header = p1 - p2;
length -= header;
if (val & V_ASN1_CONSTRUCTED) {
p3 = p1 + len;
if (len > (long)length) {
*data = p1;
return -1;
}
if ((val == 0x21) &&
(len == 0)) {
ret = ngx_http_est_asn1_parse(array, &p1, (size_t)(end - p1), offset + (p1 - *data));
if (ret < 0) {
*data = p1;
return -1;
}
if (p1 >= end) {
break;
}
} else {
while (p1 < p3) {
ret = ngx_http_est_asn1_parse(array, &p1, (size_t)len, offset + (p1 - *data));
if (ret < 0) {
*data = p1;
return -1;
}
}
}
}
else if (class != 0) {
p1 += len;
}
else {
if (tag == V_ASN1_OBJECT) {
p4 = p2;
if (d2i_ASN1_OBJECT(&obj, &p4, len + header) == NULL) {
ASN1_OBJECT_free(obj);
*data = p1;
return -1;
}
i2t_ASN1_OBJECT(buf, sizeof(buf), obj);
/* assert(strlen(buf) > 0); */
attribute = ngx_array_push(array);
if (attribute == NULL) {
goto error;
}
attribute->len = strlen(buf) + 1;
attribute->data = ngx_pnalloc(array->pool, attribute->len);
if (attribute->data == NULL) {
goto error;
}
(void) ngx_copy(attribute->data, buf, strlen(buf));
ASN1_OBJECT_free(obj);
}
p1 += len;
if ((tag == V_ASN1_EOC) &&
(class == 0)) {
*data = p1;
return 0;
}
}
length -= len;
}
*data = p1;
return 0;
error:
ASN1_OBJECT_free(obj);
return -1;
}