1 /* $NetBSD: decapsulate.c,v 1.3 2023/06/19 21:41:43 christos Exp $ */
2
3 /*
4 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include "gsskrb5_locl.h"
37
38 /*
39 * return the length of the mechanism in token or -1
40 * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN
41 */
42
43 ssize_t
_gsskrb5_get_mech(const u_char * ptr,size_t total_len,const u_char ** mech_ret)44 _gsskrb5_get_mech (const u_char *ptr,
45 size_t total_len,
46 const u_char **mech_ret)
47 {
48 size_t len, len_len, mech_len, foo;
49 const u_char *p = ptr;
50 int e;
51
52 if (total_len < 1)
53 return -1;
54 if (*p++ != 0x60)
55 return -1;
56 e = der_get_length (p, total_len - 1, &len, &len_len);
57 if (e || 1 + len_len + len != total_len)
58 return -1;
59 if (total_len < 1 + len_len + 1)
60 return -1;
61 p += len_len;
62 if (*p++ != 0x06)
63 return -1;
64 e = der_get_length (p, total_len - 1 - len_len - 1,
65 &mech_len, &foo);
66 if (e)
67 return -1;
68 p += foo;
69 *mech_ret = p;
70 return mech_len;
71 }
72
73 OM_uint32
_gssapi_verify_mech_header(u_char ** str,size_t total_len,gss_OID mech)74 _gssapi_verify_mech_header(u_char **str,
75 size_t total_len,
76 gss_OID mech)
77 {
78 const u_char *p;
79 ssize_t mech_len;
80
81 mech_len = _gsskrb5_get_mech (*str, total_len, &p);
82 if (mech_len < 0)
83 return GSS_S_DEFECTIVE_TOKEN;
84
85 if (mech_len != mech->length)
86 return GSS_S_BAD_MECH;
87 if (mech_len > total_len)
88 return GSS_S_BAD_MECH;
89 if (p - *str > total_len - mech_len)
90 return GSS_S_BAD_MECH;
91 if (ct_memcmp(p,
92 mech->elements,
93 mech->length) != 0)
94 return GSS_S_BAD_MECH;
95 p += mech_len;
96 *str = rk_UNCONST(p);
97 return GSS_S_COMPLETE;
98 }
99
100 OM_uint32
_gsskrb5_verify_header(u_char ** str,size_t total_len,const void * type,gss_OID oid)101 _gsskrb5_verify_header(u_char **str,
102 size_t total_len,
103 const void *type,
104 gss_OID oid)
105 {
106 OM_uint32 ret;
107 size_t len;
108 u_char *p = *str;
109
110 ret = _gssapi_verify_mech_header(str, total_len, oid);
111 if (ret)
112 return ret;
113
114 len = total_len - (*str - p);
115
116 if (len < 2)
117 return GSS_S_DEFECTIVE_TOKEN;
118
119 if (ct_memcmp (*str, type, 2) != 0)
120 return GSS_S_DEFECTIVE_TOKEN;
121 *str += 2;
122
123 return 0;
124 }
125
126 /*
127 * Remove the GSS-API wrapping from `in_token' giving `out_data.
128 * Does not copy data, so just free `in_token'.
129 */
130
131 OM_uint32
_gssapi_decapsulate(OM_uint32 * minor_status,gss_buffer_t input_token_buffer,krb5_data * out_data,const gss_OID mech)132 _gssapi_decapsulate(
133 OM_uint32 *minor_status,
134 gss_buffer_t input_token_buffer,
135 krb5_data *out_data,
136 const gss_OID mech
137 )
138 {
139 u_char *p;
140 OM_uint32 ret;
141
142 p = input_token_buffer->value;
143 ret = _gssapi_verify_mech_header(&p,
144 input_token_buffer->length,
145 mech);
146 if (ret) {
147 *minor_status = 0;
148 return ret;
149 }
150
151 out_data->length = input_token_buffer->length -
152 (p - (u_char *)input_token_buffer->value);
153 out_data->data = p;
154 return GSS_S_COMPLETE;
155 }
156
157 /*
158 * Remove the GSS-API wrapping from `in_token' giving `out_data.
159 * Does not copy data, so just free `in_token'.
160 */
161
162 OM_uint32
_gsskrb5_decapsulate(OM_uint32 * minor_status,gss_buffer_t input_token_buffer,krb5_data * out_data,const void * type,gss_OID oid)163 _gsskrb5_decapsulate(OM_uint32 *minor_status,
164 gss_buffer_t input_token_buffer,
165 krb5_data *out_data,
166 const void *type,
167 gss_OID oid)
168 {
169 u_char *p;
170 OM_uint32 ret;
171
172 p = input_token_buffer->value;
173 ret = _gsskrb5_verify_header(&p,
174 input_token_buffer->length,
175 type,
176 oid);
177 if (ret) {
178 *minor_status = 0;
179 return ret;
180 }
181
182 out_data->length = input_token_buffer->length -
183 (p - (u_char *)input_token_buffer->value);
184 out_data->data = p;
185 return GSS_S_COMPLETE;
186 }
187
188 /*
189 * Verify padding of a gss wrapped message and return its length.
190 */
191
192 OM_uint32
_gssapi_verify_pad(gss_buffer_t wrapped_token,size_t datalen,size_t * padlen)193 _gssapi_verify_pad(gss_buffer_t wrapped_token,
194 size_t datalen,
195 size_t *padlen)
196 {
197 u_char *pad;
198 size_t padlength;
199 int i;
200
201 if (wrapped_token->length < 1)
202 return GSS_S_BAD_MECH;
203
204 pad = (u_char *)wrapped_token->value + wrapped_token->length;
205 padlength = pad[-1];
206
207 if (padlength > datalen)
208 return GSS_S_BAD_MECH;
209
210 for (i = padlength; i > 0 && *--pad == padlength; i--)
211 ;
212 if (i != 0)
213 return GSS_S_BAD_MIC;
214
215 *padlen = padlength;
216
217 return 0;
218 }
219