17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (C) 1998 by the FundsXpress, INC.
3*1da57d55SToomas Soome  *
47c478bd9Sstevel@tonic-gate  * All rights reserved.
5*1da57d55SToomas Soome  *
67c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may require
77c478bd9Sstevel@tonic-gate  * a specific license from the United States Government.  It is the
87c478bd9Sstevel@tonic-gate  * responsibility of any person or organization contemplating export to
97c478bd9Sstevel@tonic-gate  * obtain such a license before exporting.
10*1da57d55SToomas Soome  *
117c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
127c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
137c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
147c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
157c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
167c478bd9Sstevel@tonic-gate  * the name of FundsXpress. not be used in advertising or publicity pertaining
177c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
187c478bd9Sstevel@tonic-gate  * permission.  FundsXpress makes no representations about the suitability of
197c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
207c478bd9Sstevel@tonic-gate  * or implied warranty.
21*1da57d55SToomas Soome  *
227c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
237c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
247c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <gssapiP_krb5.h>
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /* from the token, flags is stored directly. nctypes/ctypes is
307c478bd9Sstevel@tonic-gate    allocated and returns the length and list of ctypes in the token.
317c478bd9Sstevel@tonic-gate    noptions/options lists all the options which the caller cares
327c478bd9Sstevel@tonic-gate    about.  Those which are present in the token are filled in; the
337c478bd9Sstevel@tonic-gate    order and length are not changed.  If an error is returned, the
347c478bd9Sstevel@tonic-gate    option list is in an indeterminate state. */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate OM_uint32
kg2_parse_token(minor_status,ptr,token_length,flags,nctypes,ctypes,noptions,options,kmsg,mic)377c478bd9Sstevel@tonic-gate kg2_parse_token(minor_status, ptr, token_length, flags, nctypes, ctypes,
387c478bd9Sstevel@tonic-gate 		noptions, options, kmsg, mic)
397c478bd9Sstevel@tonic-gate      OM_uint32 *minor_status;
407c478bd9Sstevel@tonic-gate      unsigned char *ptr;
417c478bd9Sstevel@tonic-gate      int token_length;
427c478bd9Sstevel@tonic-gate      krb5_ui_4 *flags;
437c478bd9Sstevel@tonic-gate      int *nctypes; /* OUT */
447c478bd9Sstevel@tonic-gate      krb5_cksumtype **ctypes; /* OUT */
45*1da57d55SToomas Soome      int noptions;
467c478bd9Sstevel@tonic-gate      struct kg2_option *options; /* INOUT */
477c478bd9Sstevel@tonic-gate      krb5_data *kmsg;
487c478bd9Sstevel@tonic-gate      krb5_data *mic;
497c478bd9Sstevel@tonic-gate {
507c478bd9Sstevel@tonic-gate     int field_length, i;
517c478bd9Sstevel@tonic-gate     int opt_id;
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate     *ctypes = 0;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate     /* read the flags */
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate     if (token_length < 4)
587c478bd9Sstevel@tonic-gate 	goto defective;
597c478bd9Sstevel@tonic-gate     *flags = (ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3];
607c478bd9Sstevel@tonic-gate     ptr += 4;
617c478bd9Sstevel@tonic-gate     token_length -= 4;
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate     /* read out the token list */
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate     if (token_length < 2)
667c478bd9Sstevel@tonic-gate 	goto defective;
677c478bd9Sstevel@tonic-gate     field_length = (ptr[0]<<8) | ptr[1];
687c478bd9Sstevel@tonic-gate     ptr += 2;
697c478bd9Sstevel@tonic-gate     token_length -= 2;
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate     *nctypes = field_length;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate     if (*nctypes == 0) {
747c478bd9Sstevel@tonic-gate 	*minor_status = 0;
757c478bd9Sstevel@tonic-gate 	return(GSS_S_DEFECTIVE_TOKEN);
767c478bd9Sstevel@tonic-gate     }
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate     if ((*ctypes = (krb5_cksumtype *)
797c478bd9Sstevel@tonic-gate 	 malloc((*nctypes) * sizeof(krb5_cksumtype))) == NULL) {
807c478bd9Sstevel@tonic-gate 	*minor_status = ENOMEM;
817c478bd9Sstevel@tonic-gate 	return(GSS_S_FAILURE);
827c478bd9Sstevel@tonic-gate     }
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate     for (i=0; i<field_length; i++) {
857c478bd9Sstevel@tonic-gate 	if (token_length < 4)
867c478bd9Sstevel@tonic-gate 	    goto defective;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	(*ctypes)[i] = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) |
897c478bd9Sstevel@tonic-gate 				      (ptr[2]<<8) | ptr[3]);
907c478bd9Sstevel@tonic-gate 	ptr += 4;
917c478bd9Sstevel@tonic-gate 	token_length -= 4;
927c478bd9Sstevel@tonic-gate     }
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate     do {
957c478bd9Sstevel@tonic-gate 	if (token_length < 4)
967c478bd9Sstevel@tonic-gate 	    goto defective;
977c478bd9Sstevel@tonic-gate 	opt_id = (ptr[0]<<8) | ptr[1];
987c478bd9Sstevel@tonic-gate 	field_length = (ptr[2]<<8) | ptr[3];
997c478bd9Sstevel@tonic-gate 	ptr += 4;
1007c478bd9Sstevel@tonic-gate 	token_length -= 4;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	if (token_length < field_length)
1037c478bd9Sstevel@tonic-gate 	    goto defective;
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	for (i=0; i<noptions; i++) {
1067c478bd9Sstevel@tonic-gate 	    if (options[i].option_id = opt_id) {
1077c478bd9Sstevel@tonic-gate 		options[i].length = field_length;
1087c478bd9Sstevel@tonic-gate 		options[i].data = ptr;
1097c478bd9Sstevel@tonic-gate 	    	break;
1107c478bd9Sstevel@tonic-gate 	    }
1117c478bd9Sstevel@tonic-gate 	}
112*1da57d55SToomas Soome 
1137c478bd9Sstevel@tonic-gate 	ptr += field_length;
1147c478bd9Sstevel@tonic-gate 	token_length -= field_length;
1157c478bd9Sstevel@tonic-gate     } while (opt_id);
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate     if (token_length < 2)
1187c478bd9Sstevel@tonic-gate 	goto defective;
1197c478bd9Sstevel@tonic-gate     field_length = (ptr[0]<<8) | ptr[1];
1207c478bd9Sstevel@tonic-gate     ptr += 2;
1217c478bd9Sstevel@tonic-gate     token_length -= 2;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate     if (token_length < field_length)
1247c478bd9Sstevel@tonic-gate 	goto defective;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate     kmsg->length = field_length;
1277c478bd9Sstevel@tonic-gate     kmsg->data = (char *) ptr;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate     ptr += field_length;
1307c478bd9Sstevel@tonic-gate     token_length -= field_length;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate     /* if there's anything left, assume it's a mic.  the mic isn't
1337c478bd9Sstevel@tonic-gate        necessarily present */
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate     if (mic && token_length) {
1367c478bd9Sstevel@tonic-gate 	if (token_length < 2)
1377c478bd9Sstevel@tonic-gate 	    goto defective;
1387c478bd9Sstevel@tonic-gate 	field_length = (ptr[0]<<8) | ptr[1];
1397c478bd9Sstevel@tonic-gate 	ptr += 2;
1407c478bd9Sstevel@tonic-gate 	token_length -= 2;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	if (token_length < field_length)
1437c478bd9Sstevel@tonic-gate 	    goto defective;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	mic->length = field_length;
1467c478bd9Sstevel@tonic-gate 	mic->data = (char *) ptr;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	ptr += field_length;
1497c478bd9Sstevel@tonic-gate 	token_length -= field_length;
1507c478bd9Sstevel@tonic-gate     } else if (mic) {
1517c478bd9Sstevel@tonic-gate 	mic->length = 0;
1527c478bd9Sstevel@tonic-gate 	mic->data = (char *) ptr;
1537c478bd9Sstevel@tonic-gate     }
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate     if (token_length)
1567c478bd9Sstevel@tonic-gate 	goto defective;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate     return(GSS_S_COMPLETE);
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate defective:
1617c478bd9Sstevel@tonic-gate     if (*ctypes)
1627c478bd9Sstevel@tonic-gate 	free(*ctypes);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate     *minor_status = 0;
1657c478bd9Sstevel@tonic-gate     return(GSS_S_DEFECTIVE_TOKEN);
1667c478bd9Sstevel@tonic-gate }
167*1da57d55SToomas Soome 
1687c478bd9Sstevel@tonic-gate /* nc1/c1 will be modified to contain the intersection of the
1697c478bd9Sstevel@tonic-gate    two lists. */
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate void
kg2_intersect_ctypes(nc1,c1,nc2,c2)1727c478bd9Sstevel@tonic-gate kg2_intersect_ctypes(nc1, c1, nc2, c2)
1737c478bd9Sstevel@tonic-gate      int *nc1;
1747c478bd9Sstevel@tonic-gate      krb5_cksumtype *c1;
1757c478bd9Sstevel@tonic-gate      int nc2;
1767c478bd9Sstevel@tonic-gate      const krb5_cksumtype *c2;
1777c478bd9Sstevel@tonic-gate {
1787c478bd9Sstevel@tonic-gate     int i, j, count;
1797c478bd9Sstevel@tonic-gate     krb5_cksumtype tmp;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate     count = 0;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate     for (i=0; i<*nc1; i++) {
1847c478bd9Sstevel@tonic-gate 	/* first, check to make sure that c1[i] isn't a duplicate in c1 */
1857c478bd9Sstevel@tonic-gate 	for (j=0; j<i; j++)
1867c478bd9Sstevel@tonic-gate 	    if (c1[i] == c1[j])
1877c478bd9Sstevel@tonic-gate 		break;
1887c478bd9Sstevel@tonic-gate 	if (j<i)
1897c478bd9Sstevel@tonic-gate 	    continue;
1907c478bd9Sstevel@tonic-gate 	/* check if c1[i] is in c2.  If it is, keep it by swapping
1917c478bd9Sstevel@tonic-gate 	   it into c1[count] and incrementing count.  If count < i, then
1927c478bd9Sstevel@tonic-gate 	   that field has already been looked at and skipped as
1937c478bd9Sstevel@tonic-gate 	   not intersecting, which is ok. */
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	for (j=0; j<nc2; j++)
1967c478bd9Sstevel@tonic-gate 	    if (c1[i] == c2[j])
1977c478bd9Sstevel@tonic-gate 		break;
1987c478bd9Sstevel@tonic-gate 	if ((j<nc2) && (count != i)) {
1997c478bd9Sstevel@tonic-gate 	    tmp = c1[count];
2007c478bd9Sstevel@tonic-gate 	    c1[count] = c1[i];
2017c478bd9Sstevel@tonic-gate 	    c1[i] = tmp;
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate 	count++;
2047c478bd9Sstevel@tonic-gate     }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate     *nc1 = count;
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate 
209