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