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 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 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 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 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 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 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