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