Home | History | Annotate | Download | only in mech
      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