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