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