1 /* 2 * Copyright (C) 1998 by the FundsXpress, INC. 3 * 4 * All rights reserved. 5 * 6 * Export of this software from the United States of America may require 7 * a specific license from the United States Government. It is the 8 * responsibility of any person or organization contemplating export to 9 * obtain such a license before exporting. 10 * 11 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 12 * distribute this software and its documentation for any purpose and 13 * without fee is hereby granted, provided that the above copyright 14 * notice appear in all copies and that both that copyright notice and 15 * this permission notice appear in supporting documentation, and that 16 * the name of FundsXpress. not be used in advertising or publicity pertaining 17 * to distribution of the software without specific, written prior 18 * permission. FundsXpress makes no representations about the suitability of 19 * this software for any purpose. It is provided "as is" without express 20 * or implied warranty. 21 * 22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 24 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 25 */ 26 27 #include <gssapiP_krb5.h> 28 29 /* from the token, flags is stored directly. nctypes/ctypes is 30 allocated and returns the length and list of ctypes in the token. 31 noptions/options lists all the options which the caller cares 32 about. Those which are present in the token are filled in; the 33 order and length are not changed. If an error is returned, the 34 option list is in an indeterminate state. */ 35 36 OM_uint32 37 kg2_parse_token(minor_status, ptr, token_length, flags, nctypes, ctypes, 38 noptions, options, kmsg, mic) 39 OM_uint32 *minor_status; 40 unsigned char *ptr; 41 int token_length; 42 krb5_ui_4 *flags; 43 int *nctypes; /* OUT */ 44 krb5_cksumtype **ctypes; /* OUT */ 45 int noptions; 46 struct kg2_option *options; /* INOUT */ 47 krb5_data *kmsg; 48 krb5_data *mic; 49 { 50 int field_length, i; 51 int opt_id; 52 53 *ctypes = 0; 54 55 /* read the flags */ 56 57 if (token_length < 4) 58 goto defective; 59 *flags = (ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]; 60 ptr += 4; 61 token_length -= 4; 62 63 /* read out the token list */ 64 65 if (token_length < 2) 66 goto defective; 67 field_length = (ptr[0]<<8) | ptr[1]; 68 ptr += 2; 69 token_length -= 2; 70 71 *nctypes = field_length; 72 73 if (*nctypes == 0) { 74 *minor_status = 0; 75 return(GSS_S_DEFECTIVE_TOKEN); 76 } 77 78 if ((*ctypes = (krb5_cksumtype *) 79 malloc((*nctypes) * sizeof(krb5_cksumtype))) == NULL) { 80 *minor_status = ENOMEM; 81 return(GSS_S_FAILURE); 82 } 83 84 for (i=0; i<field_length; i++) { 85 if (token_length < 4) 86 goto defective; 87 88 (*ctypes)[i] = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) | 89 (ptr[2]<<8) | ptr[3]); 90 ptr += 4; 91 token_length -= 4; 92 } 93 94 do { 95 if (token_length < 4) 96 goto defective; 97 opt_id = (ptr[0]<<8) | ptr[1]; 98 field_length = (ptr[2]<<8) | ptr[3]; 99 ptr += 4; 100 token_length -= 4; 101 102 if (token_length < field_length) 103 goto defective; 104 105 for (i=0; i<noptions; i++) { 106 if (options[i].option_id = opt_id) { 107 options[i].length = field_length; 108 options[i].data = ptr; 109 break; 110 } 111 } 112 113 ptr += field_length; 114 token_length -= field_length; 115 } while (opt_id); 116 117 if (token_length < 2) 118 goto defective; 119 field_length = (ptr[0]<<8) | ptr[1]; 120 ptr += 2; 121 token_length -= 2; 122 123 if (token_length < field_length) 124 goto defective; 125 126 kmsg->length = field_length; 127 kmsg->data = (char *) ptr; 128 129 ptr += field_length; 130 token_length -= field_length; 131 132 /* if there's anything left, assume it's a mic. the mic isn't 133 necessarily present */ 134 135 if (mic && token_length) { 136 if (token_length < 2) 137 goto defective; 138 field_length = (ptr[0]<<8) | ptr[1]; 139 ptr += 2; 140 token_length -= 2; 141 142 if (token_length < field_length) 143 goto defective; 144 145 mic->length = field_length; 146 mic->data = (char *) ptr; 147 148 ptr += field_length; 149 token_length -= field_length; 150 } else if (mic) { 151 mic->length = 0; 152 mic->data = (char *) ptr; 153 } 154 155 if (token_length) 156 goto defective; 157 158 return(GSS_S_COMPLETE); 159 160 defective: 161 if (*ctypes) 162 free(*ctypes); 163 164 *minor_status = 0; 165 return(GSS_S_DEFECTIVE_TOKEN); 166 } 167 168 /* nc1/c1 will be modified to contain the intersection of the 169 two lists. */ 170 171 void 172 kg2_intersect_ctypes(nc1, c1, nc2, c2) 173 int *nc1; 174 krb5_cksumtype *c1; 175 int nc2; 176 const krb5_cksumtype *c2; 177 { 178 int i, j, count; 179 krb5_cksumtype tmp; 180 181 count = 0; 182 183 for (i=0; i<*nc1; i++) { 184 /* first, check to make sure that c1[i] isn't a duplicate in c1 */ 185 for (j=0; j<i; j++) 186 if (c1[i] == c1[j]) 187 break; 188 if (j<i) 189 continue; 190 /* check if c1[i] is in c2. If it is, keep it by swapping 191 it into c1[count] and incrementing count. If count < i, then 192 that field has already been looked at and skipped as 193 not intersecting, which is ok. */ 194 195 for (j=0; j<nc2; j++) 196 if (c1[i] == c2[j]) 197 break; 198 if ((j<nc2) && (count != i)) { 199 tmp = c1[count]; 200 c1[count] = c1[i]; 201 c1[i] = tmp; 202 } 203 count++; 204 } 205 206 *nc1 = count; 207 } 208 209