Home | History | Annotate | Download | only in libgss
      1 /*
      2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
      7 
      8 /*
      9  * lib/gssapi/generic/oid_ops.c
     10  *
     11  * Copyright 1995 by the Massachusetts Institute of Technology.
     12  * All Rights Reserved.
     13  *
     14  * Export of this software from the United States of America may
     15  *   require a specific license from the United States Government.
     16  *   It is the responsibility of any person or organization contemplating
     17  *   export to obtain such a license before exporting.
     18  *
     19  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
     20  * distribute this software and its documentation for any purpose and
     21  * without fee is hereby granted, provided that the above copyright
     22  * notice appear in all copies and that both that copyright notice and
     23  * this permission notice appear in supporting documentation, and that
     24  * the name of M.I.T. not be used in advertising or publicity pertaining
     25  * to distribution of the software without specific, written prior
     26  * permission.  M.I.T. makes no representations about the suitability of
     27  * this software for any purpose.  It is provided "as is" without express
     28  * or implied warranty.
     29  *
     30  */
     31 
     32 /*
     33  * oid_ops.c - GSS-API V2 interfaces to manipulate OIDs
     34  */
     35 
     36 #include <mechglueP.h>
     37 #ifdef HAVE_UNISTD_H
     38 #include <unistd.h>
     39 #endif
     40 #include <stdlib.h>
     41 #include <string.h>
     42 #include <stdio.h>
     43 #include <errno.h>
     44 #include <ctype.h>
     45 
     46 /*
     47  * this oid is defined in the oid structure but not exported to
     48  * external callers; we must still ensure that we do not delete it.
     49  */
     50 extern const gss_OID_desc * const gss_nt_service_name;
     51 
     52 
     53 OM_uint32
     54 generic_gss_release_oid(minor_status, oid)
     55 OM_uint32	*minor_status;
     56 gss_OID	*oid;
     57 {
     58 	if (minor_status)
     59 		*minor_status = 0;
     60 
     61 	if (*oid == GSS_C_NO_OID)
     62 		return (GSS_S_COMPLETE);
     63 
     64 	/*
     65 	 * The V2 API says the following!
     66 	 *
     67 	 * gss_release_oid[()] will recognize any of the GSSAPI's own OID
     68 	 * values, and will silently ignore attempts to free these OIDs;
     69 	 * for other OIDs it will call the C free() routine for both the OID
     70 	 * data and the descriptor.  This allows applications to freely mix
     71 	 * their own heap allocated OID values with OIDs returned by GSS-API.
     72 	 */
     73 
     74 	/*
     75 	 * We use the official OID definitions instead of the unofficial OID
     76 	 * defintions. But we continue to support the unofficial OID
     77 	 * gss_nt_service_name just in case if some gss applications use
     78 	 * the old OID.
     79 	 */
     80 
     81 	if ((*oid != GSS_C_NT_USER_NAME) &&
     82 		(*oid != GSS_C_NT_MACHINE_UID_NAME) &&
     83 		(*oid != GSS_C_NT_STRING_UID_NAME) &&
     84 		(*oid != GSS_C_NT_HOSTBASED_SERVICE) &&
     85 		(*oid != GSS_C_NT_ANONYMOUS) &&
     86 		(*oid != GSS_C_NT_EXPORT_NAME) &&
     87 		(*oid != gss_nt_service_name)) {
     88 		free((*oid)->elements);
     89 		free(*oid);
     90 	}
     91 	*oid = GSS_C_NO_OID;
     92 	return (GSS_S_COMPLETE);
     93 }
     94 
     95 OM_uint32
     96 generic_gss_copy_oid(minor_status, oid, new_oid)
     97 	OM_uint32	*minor_status;
     98 	const gss_OID	oid;
     99 	gss_OID		*new_oid;
    100 {
    101 	gss_OID p;
    102 
    103 	if (minor_status)
    104 		*minor_status = 0;
    105 
    106 	if (new_oid == NULL)
    107 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
    108 
    109 	if (oid == GSS_C_NO_OID)
    110 		return (GSS_S_CALL_INACCESSIBLE_READ);
    111 
    112 	p = (gss_OID) malloc(sizeof (gss_OID_desc));
    113 	if (!p) {
    114 		return (GSS_S_FAILURE);
    115 	}
    116 	p->length = oid->length;
    117 	p->elements = malloc(p->length);
    118 	if (!p->elements) {
    119 		free(p);
    120 		return (GSS_S_FAILURE);
    121 	}
    122 	(void) memcpy(p->elements, oid->elements, p->length);
    123 	*new_oid = p;
    124 	return (GSS_S_COMPLETE);
    125 }
    126 
    127 
    128 OM_uint32
    129 generic_gss_create_empty_oid_set(minor_status, oid_set)
    130 OM_uint32 *minor_status;
    131 gss_OID_set *oid_set;
    132 {
    133 	if (minor_status)
    134 		*minor_status = 0;
    135 
    136 	if (oid_set == NULL)
    137 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
    138 
    139 	if ((*oid_set = (gss_OID_set) malloc(sizeof (gss_OID_set_desc)))) {
    140 		(void) memset(*oid_set, 0, sizeof (gss_OID_set_desc));
    141 		return (GSS_S_COMPLETE);
    142 	} else {
    143 		return (GSS_S_FAILURE);
    144 	}
    145 }
    146 
    147 OM_uint32
    148 generic_gss_add_oid_set_member(minor_status, member_oid, oid_set)
    149 OM_uint32 *minor_status;
    150 const gss_OID member_oid;
    151 gss_OID_set *oid_set;
    152 {
    153 	gss_OID elist;
    154 	gss_OID lastel;
    155 
    156 	if (minor_status)
    157 		*minor_status = 0;
    158 
    159 	if (member_oid == GSS_C_NO_OID || member_oid->length == 0 ||
    160 		member_oid->elements == NULL)
    161 		return (GSS_S_CALL_INACCESSIBLE_READ);
    162 
    163 	if (oid_set == NULL)
    164 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
    165 
    166 	elist = (*oid_set)->elements;
    167 	/* Get an enlarged copy of the array */
    168 	if (((*oid_set)->elements = (gss_OID) malloc(((*oid_set)->count+1) *
    169 					sizeof (gss_OID_desc)))) {
    170 		/* Copy in the old junk */
    171 		if (elist)
    172 			(void) memcpy((*oid_set)->elements, elist,
    173 				((*oid_set)->count * sizeof (gss_OID_desc)));
    174 
    175 		/* Duplicate the input element */
    176 		lastel = &(*oid_set)->elements[(*oid_set)->count];
    177 		if ((lastel->elements =
    178 			(void *) malloc(member_oid->length))) {
    179 
    180 			/* Success - copy elements */
    181 			(void) memcpy(lastel->elements, member_oid->elements,
    182 					member_oid->length);
    183 			/* Set length */
    184 			lastel->length = member_oid->length;
    185 
    186 			/* Update count */
    187 			(*oid_set)->count++;
    188 			if (elist)
    189 				free(elist);
    190 			return (GSS_S_COMPLETE);
    191 		} else
    192 			free((*oid_set)->elements);
    193 	}
    194 	/* Failure - restore old contents of list */
    195 	(*oid_set)->elements = elist;
    196 	return (GSS_S_FAILURE);
    197 }
    198 
    199 OM_uint32
    200 generic_gss_test_oid_set_member(minor_status, member, set, present)
    201     OM_uint32		*minor_status;
    202     const gss_OID	member;
    203     const gss_OID_set	set;
    204     int			*present;
    205 {
    206 	OM_uint32 i;
    207 	int result;
    208 
    209 	if (minor_status)
    210 		*minor_status = 0;
    211 
    212 	if (member == GSS_C_NO_OID || set == NULL)
    213 		return (GSS_S_CALL_INACCESSIBLE_READ);
    214 
    215 	if (present == NULL)
    216 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
    217 
    218 	result = 0;
    219 	for (i = 0; i < set->count; i++) {
    220 		if ((set->elements[i].length == member->length) &&
    221 			!memcmp(set->elements[i].elements,
    222 				member->elements, member->length)) {
    223 			result = 1;
    224 			break;
    225 		}
    226 	}
    227 	*present = result;
    228 	return (GSS_S_COMPLETE);
    229 }
    230 
    231 /*
    232  * OID<->string routines.  These are uuuuugly.
    233  */
    234 OM_uint32
    235 generic_gss_oid_to_str(minor_status, oid, oid_str)
    236 OM_uint32 *minor_status;
    237 const gss_OID oid;
    238 gss_buffer_t oid_str;
    239 {
    240 	char numstr[128];
    241 	OM_uint32 number;
    242 	int numshift;
    243 	OM_uint32 string_length;
    244 	OM_uint32 i;
    245 	unsigned char *cp;
    246 	char *bp;
    247 
    248 	if (minor_status)
    249 		*minor_status = 0;
    250 
    251 	if (oid == GSS_C_NO_OID || oid->length == 0 || oid->elements == NULL)
    252 		return (GSS_S_CALL_INACCESSIBLE_READ);
    253 
    254 	if (oid_str == NULL)
    255 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
    256 
    257 	/* First determine the size of the string */
    258 	string_length = 0;
    259 	number = 0;
    260 	numshift = 0;
    261 	cp = (unsigned char *) oid->elements;
    262 	number = (OM_uint32) cp[0];
    263 	(void) sprintf(numstr, "%d ", number/40);
    264 	string_length += strlen(numstr);
    265 	(void) sprintf(numstr, "%d ", number%40);
    266 	string_length += strlen(numstr);
    267 	for (i = 1; i < oid->length; i++) {
    268 		if ((OM_uint32) (numshift+7) < (sizeof (OM_uint32)*8)) {
    269 			number = (number << 7) | (cp[i] & 0x7f);
    270 			numshift += 7;
    271 		} else {
    272 			return (GSS_S_FAILURE);
    273 		}
    274 
    275 		if ((cp[i] & 0x80) == 0) {
    276 			(void) sprintf(numstr, "%d ", number);
    277 			string_length += strlen(numstr);
    278 			number = 0;
    279 			numshift = 0;
    280 		}
    281 	}
    282 	/*
    283 	 * If we get here, we've calculated the length of "n n n ... n ".  Add 4
    284 	 * here for "{ " and "}\0".
    285 	 */
    286 	string_length += 4;
    287 	if ((bp = (char *)malloc(string_length))) {
    288 		(void) strcpy(bp, "{ ");
    289 		number = (OM_uint32) cp[0];
    290 		(void) sprintf(numstr, "%d ", number/40);
    291 		(void) strcat(bp, numstr);
    292 		(void) sprintf(numstr, "%d ", number%40);
    293 		(void) strcat(bp, numstr);
    294 		number = 0;
    295 		cp = (unsigned char *) oid->elements;
    296 		for (i = 1; i < oid->length; i++) {
    297 			number = (number << 7) | (cp[i] & 0x7f);
    298 			if ((cp[i] & 0x80) == 0) {
    299 				(void) sprintf(numstr, "%d ", number);
    300 				(void) strcat(bp, numstr);
    301 				number = 0;
    302 			}
    303 		}
    304 		(void) strcat(bp, "}");
    305 		oid_str->length = strlen(bp)+1;
    306 		oid_str->value = (void *) bp;
    307 		return (GSS_S_COMPLETE);
    308 	}
    309 	return (GSS_S_FAILURE);
    310 }
    311 
    312 /*
    313  * This routine will handle 2 types of oid string formats:
    314  * 	1 - { 1 2 3 4 }  where the braces are optional
    315  *	2 - 1.2.3.4 this is an alernative format
    316  * The first format is mandated by the gss spec.  The
    317  * second format is popular outside of the gss community so
    318  * has been added.
    319  */
    320 OM_uint32
    321 generic_gss_str_to_oid(minor_status, oid_str, oid)
    322 OM_uint32 *minor_status;
    323 const gss_buffer_t oid_str;
    324 gss_OID *oid;
    325 {
    326 	char *cp, *bp, *startp;
    327 	int brace;
    328 	int numbuf;
    329 	int onumbuf;
    330 	OM_uint32 nbytes;
    331 	int index;
    332 	unsigned char *op;
    333 
    334 	if (minor_status)
    335 		*minor_status = 0;
    336 
    337 	if (GSS_EMPTY_BUFFER(oid_str))
    338 		return (GSS_S_CALL_INACCESSIBLE_READ);
    339 
    340 	if (oid == NULL)
    341 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
    342 
    343 	brace = 0;
    344 	bp = (char *)oid_str->value;
    345 	cp = bp;
    346 	/* Skip over leading space */
    347 	while ((bp < &cp[oid_str->length]) && isspace(*bp))
    348 		bp++;
    349 	if (*bp == '{') {
    350 		brace = 1;
    351 		bp++;
    352 	}
    353 	while ((bp < &cp[oid_str->length]) && isspace(*bp))
    354 		bp++;
    355 	startp = bp;
    356 	nbytes = 0;
    357 
    358 	/*
    359 	 * The first two numbers are chewed up by the first octet.
    360 	 */
    361 	if (sscanf(bp, "%d", &numbuf) != 1) {
    362 		return (GSS_S_FAILURE);
    363 	}
    364 	while ((bp < &cp[oid_str->length]) && isdigit(*bp))
    365 		bp++;
    366 	while ((bp < &cp[oid_str->length]) &&
    367 		(isspace(*bp) || *bp == '.'))
    368 		bp++;
    369 	if (sscanf(bp, "%d", &numbuf) != 1) {
    370 		return (GSS_S_FAILURE);
    371 	}
    372 	while ((bp < &cp[oid_str->length]) && isdigit(*bp))
    373 		bp++;
    374 	while ((bp < &cp[oid_str->length]) &&
    375 		(isspace(*bp) || *bp == '.'))
    376 		bp++;
    377 	nbytes++;
    378 	while (isdigit(*bp)) {
    379 		if (sscanf(bp, "%d", &numbuf) != 1) {
    380 			return (GSS_S_FAILURE);
    381 		}
    382 		while (numbuf) {
    383 			nbytes++;
    384 			numbuf >>= 7;
    385 		}
    386 		while ((bp < &cp[oid_str->length]) && isdigit(*bp))
    387 			bp++;
    388 		while ((bp < &cp[oid_str->length]) &&
    389 			(isspace(*bp) || *bp == '.'))
    390 			bp++;
    391 	}
    392 	if (brace && (*bp != '}')) {
    393 		return (GSS_S_FAILURE);
    394 	}
    395 
    396 	/*
    397 	 * Phew!  We've come this far, so the syntax is good.
    398 	 */
    399 	if ((*oid = (gss_OID) malloc(sizeof (gss_OID_desc)))) {
    400 		if (((*oid)->elements = (void *) malloc(nbytes))) {
    401 			(*oid)->length = nbytes;
    402 			op = (unsigned char *) (*oid)->elements;
    403 			bp = startp;
    404 			(void) sscanf(bp, "%d", &numbuf);
    405 			while (isdigit(*bp))
    406 				bp++;
    407 			while (isspace(*bp) || *bp == '.')
    408 				bp++;
    409 			onumbuf = 40*numbuf;
    410 			(void) sscanf(bp, "%d", &numbuf);
    411 			onumbuf += numbuf;
    412 			*op = (unsigned char) onumbuf;
    413 			op++;
    414 			while (isdigit(*bp))
    415 				bp++;
    416 			while (isspace(*bp) || *bp == '.')
    417 				bp++;
    418 			while (isdigit(*bp)) {
    419 				(void) sscanf(bp, "%d", &numbuf);
    420 				nbytes = 0;
    421 		/* Have to fill in the bytes msb-first */
    422 				onumbuf = numbuf;
    423 				while (numbuf) {
    424 					nbytes++;
    425 					numbuf >>= 7;
    426 				}
    427 				numbuf = onumbuf;
    428 				op += nbytes;
    429 				index = -1;
    430 				while (numbuf) {
    431 					op[index] = (unsigned char)
    432 							numbuf & 0x7f;
    433 					if (index != -1)
    434 						op[index] |= 0x80;
    435 					index--;
    436 					numbuf >>= 7;
    437 				}
    438 				while (isdigit(*bp))
    439 					bp++;
    440 				while (isspace(*bp) || *bp == '.')
    441 					bp++;
    442 			}
    443 			return (GSS_S_COMPLETE);
    444 		} else {
    445 			free(*oid);
    446 			*oid = GSS_C_NO_OID;
    447 		}
    448 	}
    449 	return (GSS_S_FAILURE);
    450 }
    451 
    452 /*
    453  * Copyright 1993 by OpenVision Technologies, Inc.
    454  *
    455  * Permission to use, copy, modify, distribute, and sell this software
    456  * and its documentation for any purpose is hereby granted without fee,
    457  * provided that the above copyright notice appears in all copies and
    458  * that both that copyright notice and this permission notice appear in
    459  * supporting documentation, and that the name of OpenVision not be used
    460  * in advertising or publicity pertaining to distribution of the software
    461  * without specific, written prior permission. OpenVision makes no
    462  * representations about the suitability of this software for any
    463  * purpose.  It is provided "as is" without express or implied warranty.
    464  *
    465  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
    466  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
    467  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
    468  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
    469  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    470  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    471  * PERFORMANCE OF THIS SOFTWARE.
    472  */
    473 OM_uint32
    474 gss_copy_oid_set(
    475 	OM_uint32 *minor_status,
    476 	const gss_OID_set_desc * const oidset,
    477 	gss_OID_set *new_oidset
    478 )
    479 {
    480 	gss_OID_set_desc *copy;
    481 	OM_uint32 minor = 0;
    482 	OM_uint32 major = GSS_S_COMPLETE;
    483 	OM_uint32 index;
    484 
    485 	if (minor_status)
    486 		*minor_status = 0;
    487 
    488 	if (oidset == NULL)
    489 		return (GSS_S_CALL_INACCESSIBLE_READ);
    490 
    491 	if (new_oidset == NULL)
    492 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
    493 
    494 	*new_oidset = NULL;
    495 
    496 	if ((copy = (gss_OID_set_desc *) calloc(1, sizeof (*copy))) == NULL) {
    497 		major = GSS_S_FAILURE;
    498 		goto done;
    499 	}
    500 
    501 	if ((copy->elements = (gss_OID_desc *)
    502 	    calloc(oidset->count, sizeof (*copy->elements))) == NULL) {
    503 		major = GSS_S_FAILURE;
    504 		goto done;
    505 	}
    506 	copy->count = oidset->count;
    507 
    508 	for (index = 0; index < copy->count; index++) {
    509 		gss_OID_desc *out = &copy->elements[index];
    510 		gss_OID_desc *in = &oidset->elements[index];
    511 
    512 		if ((out->elements = (void *) malloc(in->length)) == NULL) {
    513 			major = GSS_S_FAILURE;
    514 			goto done;
    515 		}
    516 		(void) memcpy(out->elements, in->elements, in->length);
    517 		out->length = in->length;
    518 	}
    519 
    520 	*new_oidset = copy;
    521 done:
    522 	if (major != GSS_S_COMPLETE) {
    523 		(void) gss_release_oid_set(&minor, &copy);
    524 	}
    525 
    526 	return (major);
    527 }
    528