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
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
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