diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libgss/oid_ops.c | |
download | illumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libgss/oid_ops.c')
-rw-r--r-- | usr/src/lib/libgss/oid_ops.c | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/usr/src/lib/libgss/oid_ops.c b/usr/src/lib/libgss/oid_ops.c new file mode 100644 index 0000000000..135b45deea --- /dev/null +++ b/usr/src/lib/libgss/oid_ops.c @@ -0,0 +1,516 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * lib/gssapi/generic/oid_ops.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * oid_ops.c - GSS-API V2 interfaces to manipulate OIDs + */ + +#include <mechglueP.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <ctype.h> + +/* + * this oid is defined in the oid structure but not exported to + * external callers; we must still ensure that we do not delete it. + */ +extern const gss_OID_desc * const gss_nt_service_name; + + +OM_uint32 +generic_gss_release_oid(minor_status, oid) +OM_uint32 *minor_status; +gss_OID *oid; +{ + if (minor_status) + *minor_status = 0; + + if (*oid == GSS_C_NO_OID) + return (GSS_S_COMPLETE); + + /* + * The V2 API says the following! + * + * gss_release_oid[()] will recognize any of the GSSAPI's own OID + * values, and will silently ignore attempts to free these OIDs; + * for other OIDs it will call the C free() routine for both the OID + * data and the descriptor. This allows applications to freely mix + * their own heap allocated OID values with OIDs returned by GSS-API. + */ + + /* + * We use the official OID definitions instead of the unofficial OID + * defintions. But we continue to support the unofficial OID + * gss_nt_service_name just in case if some gss applications use + * the old OID. + */ + + if ((*oid != GSS_C_NT_USER_NAME) && + (*oid != GSS_C_NT_MACHINE_UID_NAME) && + (*oid != GSS_C_NT_STRING_UID_NAME) && + (*oid != GSS_C_NT_HOSTBASED_SERVICE) && + (*oid != GSS_C_NT_ANONYMOUS) && + (*oid != GSS_C_NT_EXPORT_NAME) && + (*oid != gss_nt_service_name)) { + free((*oid)->elements); + free(*oid); + } + *oid = GSS_C_NO_OID; + return (GSS_S_COMPLETE); +} + +OM_uint32 +generic_gss_copy_oid(minor_status, oid, new_oid) + OM_uint32 *minor_status; + const gss_OID oid; + gss_OID *new_oid; +{ + gss_OID p; + + if (minor_status) + *minor_status = 0; + + p = (gss_OID) malloc(sizeof (gss_OID_desc)); + if (!p) { + return (GSS_S_FAILURE); + } + p->length = oid->length; + p->elements = malloc(p->length); + if (!p->elements) { + free(p); + return (GSS_S_FAILURE); + } + (void) memcpy(p->elements, oid->elements, p->length); + *new_oid = p; + return (GSS_S_COMPLETE); +} + + +OM_uint32 +generic_gss_create_empty_oid_set(minor_status, oid_set) +OM_uint32 *minor_status; +gss_OID_set *oid_set; +{ + if (minor_status) + *minor_status = 0; + + if ((*oid_set = (gss_OID_set) malloc(sizeof (gss_OID_set_desc)))) { + (void) memset(*oid_set, 0, sizeof (gss_OID_set_desc)); + return (GSS_S_COMPLETE); + } else { + return (GSS_S_FAILURE); + } +} + +OM_uint32 +generic_gss_add_oid_set_member(minor_status, member_oid, oid_set) +OM_uint32 *minor_status; +const gss_OID member_oid; +gss_OID_set *oid_set; +{ + gss_OID elist; + gss_OID lastel; + + if (minor_status) + *minor_status = 0; + + if (member_oid == NULL || member_oid->length == 0 || + member_oid->elements == NULL) + return (GSS_S_CALL_INACCESSIBLE_READ); + + elist = (*oid_set)->elements; + /* Get an enlarged copy of the array */ + if (((*oid_set)->elements = (gss_OID) malloc(((*oid_set)->count+1) * + sizeof (gss_OID_desc)))) { + /* Copy in the old junk */ + if (elist) + (void) memcpy((*oid_set)->elements, elist, + ((*oid_set)->count * sizeof (gss_OID_desc))); + + /* Duplicate the input element */ + lastel = &(*oid_set)->elements[(*oid_set)->count]; + if ((lastel->elements = + (void *) malloc(member_oid->length))) { + /* Success - copy elements */ + (void) memcpy(lastel->elements, member_oid->elements, + member_oid->length); + /* Set length */ + lastel->length = member_oid->length; + + /* Update count */ + (*oid_set)->count++; + if (elist) + free(elist); + return (GSS_S_COMPLETE); + } else + free((*oid_set)->elements); + } + /* Failure - restore old contents of list */ + (*oid_set)->elements = elist; + return (GSS_S_FAILURE); +} + +OM_uint32 +generic_gss_test_oid_set_member(minor_status, member, set, present) + OM_uint32 *minor_status; + const gss_OID member; + const gss_OID_set set; + int *present; +{ + OM_uint32 i; + int result; + + if (minor_status) + *minor_status = 0; + + if (member == NULL || set == NULL) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (present == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + result = 0; + for (i = 0; i < set->count; i++) { + if ((set->elements[i].length == member->length) && + !memcmp(set->elements[i].elements, + member->elements, member->length)) { + result = 1; + break; + } + } + *present = result; + return (GSS_S_COMPLETE); +} + +/* + * OID<->string routines. These are uuuuugly. + */ +OM_uint32 +generic_gss_oid_to_str(minor_status, oid, oid_str) +OM_uint32 *minor_status; +const gss_OID oid; +gss_buffer_t oid_str; +{ + char numstr[128]; + OM_uint32 number; + int numshift; + OM_uint32 string_length; + OM_uint32 i; + unsigned char *cp; + char *bp; + + if (minor_status) + *minor_status = 0; + + if (oid == NULL || oid->length == 0 || oid->elements == NULL) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (oid_str == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + /* Decoded according to krb5/gssapi_krb5.c */ + + /* First determine the size of the string */ + string_length = 0; + number = 0; + numshift = 0; + cp = (unsigned char *) oid->elements; + number = (OM_uint32) cp[0]; + (void) sprintf(numstr, "%d ", number/40); + string_length += strlen(numstr); + (void) sprintf(numstr, "%d ", number%40); + string_length += strlen(numstr); + for (i = 1; i < oid->length; i++) { + if ((OM_uint32) (numshift+7) < (sizeof (OM_uint32)*8)) { + number = (number << 7) | (cp[i] & 0x7f); + numshift += 7; + } else { + return (GSS_S_FAILURE); + } + + if ((cp[i] & 0x80) == 0) { + (void) sprintf(numstr, "%d ", number); + string_length += strlen(numstr); + number = 0; + numshift = 0; + } + } + /* + * If we get here, we've calculated the length of "n n n ... n ". Add 4 + * here for "{ " and "}\0". + */ + string_length += 4; + if ((bp = (char *)malloc(string_length))) { + (void) strcpy(bp, "{ "); + number = (OM_uint32) cp[0]; + (void) sprintf(numstr, "%d ", number/40); + (void) strcat(bp, numstr); + (void) sprintf(numstr, "%d ", number%40); + (void) strcat(bp, numstr); + number = 0; + cp = (unsigned char *) oid->elements; + for (i = 1; i < oid->length; i++) { + number = (number << 7) | (cp[i] & 0x7f); + if ((cp[i] & 0x80) == 0) { + (void) sprintf(numstr, "%d ", number); + (void) strcat(bp, numstr); + number = 0; + } + } + (void) strcat(bp, "}"); + oid_str->length = strlen(bp)+1; + oid_str->value = (void *) bp; + return (GSS_S_COMPLETE); + } + return (GSS_S_FAILURE); +} + +/* + * This routine will handle 2 types of oid string formats: + * 1 - { 1 2 3 4 } where the braces are optional + * 2 - 1.2.3.4 this is an alernative format + * The first format is mandated by the gss spec. The + * second format is popular outside of the gss community so + * has been added. + */ +OM_uint32 +generic_gss_str_to_oid(minor_status, oid_str, oid) +OM_uint32 *minor_status; +const gss_buffer_t oid_str; +gss_OID *oid; +{ + char *cp, *bp, *startp; + int brace; + int numbuf; + int onumbuf; + OM_uint32 nbytes; + int index; + unsigned char *op; + + if (minor_status) + *minor_status = 0; + + if (GSS_EMPTY_BUFFER(oid_str)) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (oid == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + brace = 0; + bp = (char *)oid_str->value; + cp = bp; + /* Skip over leading space */ + while ((bp < &cp[oid_str->length]) && isspace(*bp)) + bp++; + if (*bp == '{') { + brace = 1; + bp++; + } + while ((bp < &cp[oid_str->length]) && isspace(*bp)) + bp++; + startp = bp; + nbytes = 0; + + /* + * The first two numbers are chewed up by the first octet. + */ + if (sscanf(bp, "%d", &numbuf) != 1) { + return (GSS_S_FAILURE); + } + while ((bp < &cp[oid_str->length]) && isdigit(*bp)) + bp++; + while ((bp < &cp[oid_str->length]) && + (isspace(*bp) || *bp == '.')) + bp++; + if (sscanf(bp, "%d", &numbuf) != 1) { + return (GSS_S_FAILURE); + } + while ((bp < &cp[oid_str->length]) && isdigit(*bp)) + bp++; + while ((bp < &cp[oid_str->length]) && + (isspace(*bp) || *bp == '.')) + bp++; + nbytes++; + while (isdigit(*bp)) { + if (sscanf(bp, "%d", &numbuf) != 1) { + return (GSS_S_FAILURE); + } + while (numbuf) { + nbytes++; + numbuf >>= 7; + } + while ((bp < &cp[oid_str->length]) && isdigit(*bp)) + bp++; + while ((bp < &cp[oid_str->length]) && + (isspace(*bp) || *bp == '.')) + bp++; + } + if (brace && (*bp != '}')) { + return (GSS_S_FAILURE); + } + + /* + * Phew! We've come this far, so the syntax is good. + */ + if ((*oid = (gss_OID) malloc(sizeof (gss_OID_desc)))) { + if (((*oid)->elements = (void *) malloc(nbytes))) { + (*oid)->length = nbytes; + op = (unsigned char *) (*oid)->elements; + bp = startp; + (void) sscanf(bp, "%d", &numbuf); + while (isdigit(*bp)) + bp++; + while (isspace(*bp) || *bp == '.') + bp++; + onumbuf = 40*numbuf; + (void) sscanf(bp, "%d", &numbuf); + onumbuf += numbuf; + *op = (unsigned char) onumbuf; + op++; + while (isdigit(*bp)) + bp++; + while (isspace(*bp) || *bp == '.') + bp++; + while (isdigit(*bp)) { + (void) sscanf(bp, "%d", &numbuf); + nbytes = 0; + /* Have to fill in the bytes msb-first */ + onumbuf = numbuf; + while (numbuf) { + nbytes++; + numbuf >>= 7; + } + numbuf = onumbuf; + op += nbytes; + index = -1; + while (numbuf) { + op[index] = (unsigned char) + numbuf & 0x7f; + if (index != -1) + op[index] |= 0x80; + index--; + numbuf >>= 7; + } + while (isdigit(*bp)) + bp++; + while (isspace(*bp) || *bp == '.') + bp++; + } + return (GSS_S_COMPLETE); + } else { + free(*oid); + *oid = GSS_C_NO_OID; + } + } + return (GSS_S_FAILURE); +} + +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +OM_uint32 +gss_copy_oid_set( + OM_uint32 *minor_status, + const gss_OID_set_desc * const oidset, + gss_OID_set *new_oidset +) +{ + gss_OID_set_desc *copy; + OM_uint32 minor = 0; + OM_uint32 major = GSS_S_COMPLETE; + OM_uint32 index; + + if (minor_status) + *minor_status = 0; + + if (oidset == NULL) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (new_oidset == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + *new_oidset = NULL; + + if ((copy = (gss_OID_set_desc *) calloc(1, sizeof (*copy))) == NULL) { + major = GSS_S_FAILURE; + goto done; + } + + if ((copy->elements = (gss_OID_desc *) + calloc(oidset->count, sizeof (*copy->elements))) == NULL) { + major = GSS_S_FAILURE; + goto done; + } + copy->count = oidset->count; + + for (index = 0; index < copy->count; index++) { + gss_OID_desc *out = ©->elements[index]; + gss_OID_desc *in = &oidset->elements[index]; + + if ((out->elements = (void *) malloc(in->length)) == NULL) { + major = GSS_S_FAILURE; + goto done; + } + (void) memcpy(out->elements, in->elements, in->length); + out->length = in->length; + } + + *new_oidset = copy; +done: + if (major != GSS_S_COMPLETE) { + (void) gss_release_oid_set(&minor, ©); + } + + return (major); +} |