1c19800e8SDoug Rabson /* 2ae771770SStanislav Sedov * 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 34ae771770SStanislav Sedov #include "gsskrb5_locl.h" 35c19800e8SDoug Rabson 36c19800e8SDoug Rabson /* 37c19800e8SDoug Rabson * return the length of the mechanism in token or -1 38c19800e8SDoug Rabson * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN 39c19800e8SDoug Rabson */ 40c19800e8SDoug Rabson 41c19800e8SDoug Rabson ssize_t 42c19800e8SDoug Rabson _gsskrb5_get_mech (const u_char *ptr, 43c19800e8SDoug Rabson size_t total_len, 44c19800e8SDoug Rabson const u_char **mech_ret) 45c19800e8SDoug Rabson { 46c19800e8SDoug Rabson size_t len, len_len, mech_len, foo; 47c19800e8SDoug Rabson const u_char *p = ptr; 48c19800e8SDoug Rabson int e; 49c19800e8SDoug Rabson 50c19800e8SDoug Rabson if (total_len < 1) 51c19800e8SDoug Rabson return -1; 52c19800e8SDoug Rabson if (*p++ != 0x60) 53c19800e8SDoug Rabson return -1; 54c19800e8SDoug Rabson e = der_get_length (p, total_len - 1, &len, &len_len); 55c19800e8SDoug Rabson if (e || 1 + len_len + len != total_len) 56c19800e8SDoug Rabson return -1; 57*ed549cb0SCy Schubert if (total_len < 1 + len_len + 1) 58*ed549cb0SCy Schubert 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; 85*ed549cb0SCy Schubert if (mech_len > total_len) 86*ed549cb0SCy Schubert return GSS_S_BAD_MECH; 87*ed549cb0SCy Schubert if (p - *str > total_len - mech_len) 88*ed549cb0SCy Schubert return GSS_S_BAD_MECH; 89ae771770SStanislav Sedov if (ct_memcmp(p, 90c19800e8SDoug Rabson mech->elements, 91c19800e8SDoug Rabson mech->length) != 0) 92c19800e8SDoug Rabson return GSS_S_BAD_MECH; 93c19800e8SDoug Rabson p += mech_len; 94c19800e8SDoug Rabson *str = rk_UNCONST(p); 95c19800e8SDoug Rabson return GSS_S_COMPLETE; 96c19800e8SDoug Rabson } 97c19800e8SDoug Rabson 98c19800e8SDoug Rabson OM_uint32 99c19800e8SDoug Rabson _gsskrb5_verify_header(u_char **str, 100c19800e8SDoug Rabson size_t total_len, 101c19800e8SDoug Rabson const void *type, 102c19800e8SDoug Rabson gss_OID oid) 103c19800e8SDoug Rabson { 104c19800e8SDoug Rabson OM_uint32 ret; 105c19800e8SDoug Rabson size_t len; 106c19800e8SDoug Rabson u_char *p = *str; 107c19800e8SDoug Rabson 108c19800e8SDoug Rabson ret = _gssapi_verify_mech_header(str, total_len, oid); 109c19800e8SDoug Rabson if (ret) 110c19800e8SDoug Rabson return ret; 111c19800e8SDoug Rabson 112c19800e8SDoug Rabson len = total_len - (*str - p); 113c19800e8SDoug Rabson 114c19800e8SDoug Rabson if (len < 2) 115c19800e8SDoug Rabson return GSS_S_DEFECTIVE_TOKEN; 116c19800e8SDoug Rabson 117ae771770SStanislav Sedov if (ct_memcmp (*str, type, 2) != 0) 118c19800e8SDoug Rabson return GSS_S_DEFECTIVE_TOKEN; 119c19800e8SDoug Rabson *str += 2; 120c19800e8SDoug Rabson 121c19800e8SDoug Rabson return 0; 122c19800e8SDoug Rabson } 123c19800e8SDoug Rabson 124c19800e8SDoug Rabson /* 125c19800e8SDoug Rabson * Remove the GSS-API wrapping from `in_token' giving `out_data. 126c19800e8SDoug Rabson * Does not copy data, so just free `in_token'. 127c19800e8SDoug Rabson */ 128c19800e8SDoug Rabson 129c19800e8SDoug Rabson OM_uint32 130c19800e8SDoug Rabson _gssapi_decapsulate( 131c19800e8SDoug Rabson OM_uint32 *minor_status, 132c19800e8SDoug Rabson gss_buffer_t input_token_buffer, 133c19800e8SDoug Rabson krb5_data *out_data, 134c19800e8SDoug Rabson const gss_OID mech 135c19800e8SDoug Rabson ) 136c19800e8SDoug Rabson { 137c19800e8SDoug Rabson u_char *p; 138c19800e8SDoug Rabson OM_uint32 ret; 139c19800e8SDoug Rabson 140c19800e8SDoug Rabson p = input_token_buffer->value; 141c19800e8SDoug Rabson ret = _gssapi_verify_mech_header(&p, 142c19800e8SDoug Rabson input_token_buffer->length, 143c19800e8SDoug Rabson mech); 144c19800e8SDoug Rabson if (ret) { 145c19800e8SDoug Rabson *minor_status = 0; 146c19800e8SDoug Rabson return ret; 147c19800e8SDoug Rabson } 148c19800e8SDoug Rabson 149c19800e8SDoug Rabson out_data->length = input_token_buffer->length - 150c19800e8SDoug Rabson (p - (u_char *)input_token_buffer->value); 151c19800e8SDoug Rabson out_data->data = p; 152c19800e8SDoug Rabson return GSS_S_COMPLETE; 153c19800e8SDoug Rabson } 154c19800e8SDoug Rabson 155c19800e8SDoug Rabson /* 156c19800e8SDoug Rabson * Remove the GSS-API wrapping from `in_token' giving `out_data. 157c19800e8SDoug Rabson * Does not copy data, so just free `in_token'. 158c19800e8SDoug Rabson */ 159c19800e8SDoug Rabson 160c19800e8SDoug Rabson OM_uint32 161c19800e8SDoug Rabson _gsskrb5_decapsulate(OM_uint32 *minor_status, 162c19800e8SDoug Rabson gss_buffer_t input_token_buffer, 163c19800e8SDoug Rabson krb5_data *out_data, 164c19800e8SDoug Rabson const void *type, 165c19800e8SDoug Rabson gss_OID oid) 166c19800e8SDoug Rabson { 167c19800e8SDoug Rabson u_char *p; 168c19800e8SDoug Rabson OM_uint32 ret; 169c19800e8SDoug Rabson 170c19800e8SDoug Rabson p = input_token_buffer->value; 171c19800e8SDoug Rabson ret = _gsskrb5_verify_header(&p, 172c19800e8SDoug Rabson input_token_buffer->length, 173c19800e8SDoug Rabson type, 174c19800e8SDoug Rabson oid); 175c19800e8SDoug Rabson if (ret) { 176c19800e8SDoug Rabson *minor_status = 0; 177c19800e8SDoug Rabson return ret; 178c19800e8SDoug Rabson } 179c19800e8SDoug Rabson 180c19800e8SDoug Rabson out_data->length = input_token_buffer->length - 181c19800e8SDoug Rabson (p - (u_char *)input_token_buffer->value); 182c19800e8SDoug Rabson out_data->data = p; 183c19800e8SDoug Rabson return GSS_S_COMPLETE; 184c19800e8SDoug Rabson } 185c19800e8SDoug Rabson 186c19800e8SDoug Rabson /* 187c19800e8SDoug Rabson * Verify padding of a gss wrapped message and return its length. 188c19800e8SDoug Rabson */ 189c19800e8SDoug Rabson 190c19800e8SDoug Rabson OM_uint32 191c19800e8SDoug Rabson _gssapi_verify_pad(gss_buffer_t wrapped_token, 192c19800e8SDoug Rabson size_t datalen, 193c19800e8SDoug Rabson size_t *padlen) 194c19800e8SDoug Rabson { 195c19800e8SDoug Rabson u_char *pad; 196c19800e8SDoug Rabson size_t padlength; 197c19800e8SDoug Rabson int i; 198c19800e8SDoug Rabson 199*ed549cb0SCy Schubert pad = (u_char *)wrapped_token->value + wrapped_token->length; 200*ed549cb0SCy Schubert padlength = pad[-1]; 201c19800e8SDoug Rabson 202c19800e8SDoug Rabson if (padlength > datalen) 203c19800e8SDoug Rabson return GSS_S_BAD_MECH; 204c19800e8SDoug Rabson 205*ed549cb0SCy Schubert for (i = padlength; i > 0 && *--pad == padlength; i--) 206c19800e8SDoug Rabson ; 207c19800e8SDoug Rabson if (i != 0) 208c19800e8SDoug Rabson return GSS_S_BAD_MIC; 209c19800e8SDoug Rabson 210c19800e8SDoug Rabson *padlen = padlength; 211c19800e8SDoug Rabson 212c19800e8SDoug Rabson return 0; 213c19800e8SDoug Rabson } 214