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