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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
--- src/lib/gssapi/spnego/spnego_mech.c
+++ src/lib/gssapi/spnego/spnego_mech.c
@@ -54,8 +54,8 @@ typedef const gss_OID_desc *gss_OID_const;
/* der routines defined in libgss */
extern unsigned int gssint_der_length_size(OM_uint32);
-extern int gssint_get_der_length(unsigned char **, OM_uint32, OM_uint32*);
-extern int gssint_put_der_length(OM_uint32, unsigned char **, OM_uint32);
+extern int gssint_get_der_length(unsigned char **, OM_uint32, unsigned int*);
+extern int gssint_put_der_length(OM_uint32, unsigned char **, unsigned int);
/* private routines for spnego_mechanism */
@@ -1249,7 +1249,8 @@ spnego_gss_accept_sec_context(void *ct,
}
cleanup:
if (return_token != NO_TOKEN_SEND && return_token != CHECK_MIC) {
- tmpret = make_spnego_tokenTarg_msg(negState, sc->internal_mech,
+ tmpret = make_spnego_tokenTarg_msg(negState,
+ sc ? sc->internal_mech : GSS_C_NO_OID,
&mechtok_out, mic_out,
return_token,
output_token);
@@ -1802,22 +1803,16 @@ static gss_buffer_t
get_input_token(unsigned char **buff_in, unsigned int buff_length)
{
gss_buffer_t input_token;
- unsigned int bytes;
+ unsigned int len;
- if (**buff_in != OCTET_STRING)
+ if (g_get_tag_and_length(buff_in, OCTET_STRING, buff_length, &len) < 0)
return (NULL);
- (*buff_in)++;
input_token = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
-
if (input_token == NULL)
return (NULL);
- input_token->length = gssint_get_der_length(buff_in, buff_length, &bytes);
- if ((int)input_token->length == -1) {
- free(input_token);
- return (NULL);
- }
+ input_token->length = len;
input_token->value = malloc(input_token->length);
if (input_token->value == NULL) {
@@ -1869,8 +1864,8 @@ get_mech_set(OM_uint32 *minor_status, unsigned char **buff_in,
{
gss_OID_set returned_mechSet;
OM_uint32 major_status;
- OM_uint32 length;
- OM_uint32 bytes;
+ int length;
+ unsigned int bytes;
OM_uint32 set_length;
unsigned char *start;
int i;
@@ -1882,22 +1877,25 @@ get_mech_set(OM_uint32 *minor_status, unsigned char **buff_in,
(*buff_in)++;
length = gssint_get_der_length(buff_in, buff_length, &bytes);
+ if (length < 0 || buff_length - bytes < (unsigned int)length)
+ return NULL;
major_status = gss_create_empty_oid_set(minor_status,
&returned_mechSet);
if (major_status != GSS_S_COMPLETE)
return (NULL);
- for (set_length = 0, i = 0; set_length < length; i++) {
+ for (set_length = 0, i = 0; set_length < (unsigned int)length; i++) {
gss_OID_desc *temp = get_mech_oid(minor_status, buff_in,
buff_length - (*buff_in - start));
- if (temp != NULL) {
- major_status = gss_add_oid_set_member(minor_status,
- temp, &returned_mechSet);
- if (major_status == GSS_S_COMPLETE) {
+ if (temp == NULL)
+ break;
+
+ major_status = gss_add_oid_set_member(minor_status,
+ temp, &returned_mechSet);
+ if (major_status == GSS_S_COMPLETE) {
set_length += returned_mechSet->elements[i].length +2;
generic_gss_release_oid(minor_status, &temp);
- }
}
}
@@ -2097,7 +2095,7 @@ get_negTokenResp(OM_uint32 *minor_status,
return GSS_S_DEFECTIVE_TOKEN;
if (*ptr++ == SEQUENCE) {
tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
- if (tmplen < 0)
+ if (tmplen < 0 || REMAIN < (unsigned int)tmplen)
return GSS_S_DEFECTIVE_TOKEN;
}
if (REMAIN < 1)
@@ -2107,7 +2105,7 @@ get_negTokenResp(OM_uint32 *minor_status,
if (tag == CONTEXT) {
tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
- if (tmplen < 0)
+ if (tmplen < 0 || REMAIN < (unsigned int)tmplen)
return GSS_S_DEFECTIVE_TOKEN;
if (g_get_tag_and_length(&ptr, ENUMERATED,
@@ -2128,7 +2126,7 @@ get_negTokenResp(OM_uint32 *minor_status,
}
if (tag == (CONTEXT | 0x01)) {
tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
- if (tmplen < 0)
+ if (tmplen < 0 || REMAIN < (unsigned int)tmplen)
return GSS_S_DEFECTIVE_TOKEN;
*supportedMech = get_mech_oid(minor_status, &ptr, REMAIN);
@@ -2142,7 +2140,7 @@ get_negTokenResp(OM_uint32 *minor_status,
}
if (tag == (CONTEXT | 0x02)) {
tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
- if (tmplen < 0)
+ if (tmplen < 0 || REMAIN < (unsigned int)tmplen)
return GSS_S_DEFECTIVE_TOKEN;
*responseToken = get_input_token(&ptr, REMAIN);
@@ -2156,7 +2154,7 @@ get_negTokenResp(OM_uint32 *minor_status,
}
if (tag == (CONTEXT | 0x03)) {
tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
- if (tmplen < 0)
+ if (tmplen < 0 || REMAIN < (unsigned int)tmplen)
return GSS_S_DEFECTIVE_TOKEN;
*mechListMIC = get_input_token(&ptr, REMAIN);
@@ -2464,6 +2462,8 @@ make_spnego_tokenTarg_msg(OM_uint32 status, gss_OID mech_wanted,
if (outbuf == GSS_C_NO_BUFFER)
return (GSS_S_DEFECTIVE_TOKEN);
+ if (sendtoken == INIT_TOKEN_SEND && mech_wanted == GSS_C_NO_OID)
+ return (GSS_S_DEFECTIVE_TOKEN);
outbuf->length = 0;
outbuf->value = NULL;
@@ -2715,7 +2715,7 @@ g_get_tag_and_length(unsigned char **buf, int tag,
&encoded_len);
if (tmplen < 0) {
ret = -1;
- } else if (tmplen > buflen - (ptr - *buf)) {
+ } else if ((unsigned int)tmplen > buflen - (ptr - *buf)) {
ret = -1;
} else
ret = 0;
--- src/lib/krb5/asn.1/asn1buf.c
+++ src/lib/krb5/asn.1/asn1buf.c
@@ -78,11 +78,11 @@ asn1_error_code asn1buf_wrap_data(asn1buf *buf, const krb5_data *code)
asn1_error_code asn1buf_imbed(asn1buf *subbuf, const asn1buf *buf, const unsigned int length, const int indef)
{
+ if (buf->next > buf->bound + 1) return ASN1_OVERRUN;
subbuf->base = subbuf->next = buf->next;
if (!indef) {
+ if (length > (size_t)(buf->bound + 1 - buf->next)) return ASN1_OVERRUN;
subbuf->bound = subbuf->base + length - 1;
- if (subbuf->bound > buf->bound)
- return ASN1_OVERRUN;
} else /* constructed indefinite */
subbuf->bound = buf->bound;
return 0;
@@ -200,6 +200,7 @@ asn1_error_code asn1buf_remove_octetstring(asn1buf *buf, const unsigned int len,
{
int i;
+ if (buf->next > buf->bound + 1) return ASN1_OVERRUN;
if (len > buf->bound + 1 - buf->next) return ASN1_OVERRUN;
if (len == 0) {
*s = 0;
@@ -218,6 +219,7 @@ asn1_error_code asn1buf_remove_charstring(asn1buf *buf, const unsigned int len,
{
int i;
+ if (buf->next > buf->bound + 1) return ASN1_OVERRUN;
if (len > buf->bound + 1 - buf->next) return ASN1_OVERRUN;
if (len == 0) {
*s = 0;
|