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
kg2_parse_token(minor_status,ptr,token_length,flags,nctypes,ctypes,noptions,options,kmsg,mic)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
kg2_intersect_ctypes(nc1,c1,nc2,c2)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