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