#include "mglueP.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <gssapi/gssapi_generic.h>
#include <errno.h>
#include <ctype.h>
OM_uint32
generic_gss_release_oid(minor_status, oid)
OM_uint32 *minor_status;
gss_OID *oid;
{
if (minor_status)
*minor_status = 0;
if (oid == NULL || *oid == GSS_C_NO_OID)
return(GSS_S_COMPLETE);
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_desc * const oid;
gss_OID *new_oid;
{
gss_OID p;
*minor_status = 0;
p = (gss_OID) malloc(sizeof(gss_OID_desc));
if (!p) {
*minor_status = ENOMEM;
return GSS_S_FAILURE;
}
p->length = oid->length;
p->elements = malloc(p->length);
if (!p->elements) {
free(p);
return GSS_S_FAILURE;
}
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;
{
*minor_status = 0;
if ((*oid_set = (gss_OID_set) malloc(sizeof(gss_OID_set_desc)))) {
memset(*oid_set, 0, sizeof(gss_OID_set_desc));
return(GSS_S_COMPLETE);
}
else {
*minor_status = ENOMEM;
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_desc * const member_oid;
gss_OID_set *oid_set;
{
gss_OID elist;
gss_OID lastel;
*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;
if (((*oid_set)->elements = (gss_OID) malloc(((*oid_set)->count+1) *
sizeof(gss_OID_desc)))) {
if (elist)
memcpy((*oid_set)->elements,
elist,
((*oid_set)->count * sizeof(gss_OID_desc)));
lastel = &(*oid_set)->elements[(*oid_set)->count];
if ((lastel->elements =
(void *) malloc((size_t) member_oid->length))) {
memcpy(lastel->elements, member_oid->elements,
(size_t) member_oid->length);
lastel->length = member_oid->length;
(*oid_set)->count++;
if (elist)
free(elist);
*minor_status = 0;
return(GSS_S_COMPLETE);
}
else
free((*oid_set)->elements);
}
(*oid_set)->elements = elist;
*minor_status = ENOMEM;
return(GSS_S_FAILURE);
}
OM_uint32
generic_gss_test_oid_set_member(minor_status, member, set, present)
OM_uint32 *minor_status;
const gss_OID_desc * const member;
gss_OID_set set;
int *present;
{
OM_uint32 i;
int result;
*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,
(size_t) member->length)) {
result = 1;
break;
}
}
*present = result;
return(GSS_S_COMPLETE);
}
OM_uint32
generic_gss_oid_to_str(minor_status, oid, oid_str)
OM_uint32 *minor_status;
const gss_OID_desc * const 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 != NULL)
*minor_status = 0;
if (oid_str != GSS_C_NO_BUFFER) {
oid_str->length = 0;
oid_str->value = NULL;
}
if (oid == NULL || oid->length == 0 || oid->elements == NULL)
return (GSS_S_CALL_INACCESSIBLE_READ);
if (oid_str == GSS_C_NO_BUFFER)
return (GSS_S_CALL_INACCESSIBLE_WRITE);
string_length = 0;
number = 0;
numshift = 0;
cp = (unsigned char *) oid->elements;
number = (unsigned long) cp[0];
sprintf(numstr, "%lu ", (unsigned long)number/40);
string_length += strlen(numstr);
sprintf(numstr, "%lu ", (unsigned long)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) {
sprintf(numstr, "%lu ", (unsigned long)number);
string_length += strlen(numstr);
number = 0;
numshift = 0;
}
}
string_length += 4;
if ((bp = (char *) malloc(string_length))) {
strcpy(bp, "{ ");
number = (OM_uint32) cp[0];
sprintf(numstr, "%lu ", (unsigned long)number/40);
strcat(bp, numstr);
sprintf(numstr, "%lu ", (unsigned long)number%40);
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) {
sprintf(numstr, "%lu ", (unsigned long)number);
strcat(bp, numstr);
number = 0;
}
}
strcat(bp, "}");
oid_str->length = strlen(bp)+1;
oid_str->value = (void *) bp;
return(GSS_S_COMPLETE);
}
*minor_status = ENOMEM;
return(GSS_S_FAILURE);
}
OM_uint32
generic_gss_str_to_oid(minor_status, oid_str, oid)
OM_uint32 *minor_status;
gss_buffer_t oid_str;
gss_OID *oid;
{
unsigned char *cp, *bp, *startp;
int brace;
long numbuf;
long onumbuf;
OM_uint32 nbytes;
int index;
unsigned char *op;
if (minor_status != NULL)
*minor_status = 0;
if (oid != NULL)
*oid = GSS_C_NO_OID;
if (GSS_EMPTY_BUFFER(oid_str))
return (GSS_S_CALL_INACCESSIBLE_READ);
if (oid == NULL)
return (GSS_S_CALL_INACCESSIBLE_WRITE);
brace = 0;
bp = oid_str->value;
cp = bp;
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;
if (sscanf((char *)bp, "%ld", &numbuf) != 1) {
*minor_status = EINVAL;
return(GSS_S_FAILURE);
}
while ((bp < &cp[oid_str->length]) && isdigit(*bp))
bp++;
while ((bp < &cp[oid_str->length]) && isspace(*bp))
bp++;
if (sscanf((char *)bp, "%ld", &numbuf) != 1) {
*minor_status = EINVAL;
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((char *)bp, "%ld", &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);
}
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((char *)bp, "%ld", &numbuf);
while (isdigit(*bp))
bp++;
while (isspace(*bp) || *bp == '.')
bp++;
onumbuf = 40*numbuf;
(void) sscanf((char *)bp, "%ld", &numbuf);
onumbuf += numbuf;
*op = (unsigned char) onumbuf;
op++;
while (isdigit(*bp))
bp++;
while (isspace(*bp) || *bp == '.')
bp++;
while (isdigit(*bp)) {
(void) sscanf((char *)bp, "%ld", &numbuf);
nbytes = 0;
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);
}
OM_uint32
gssint_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 != NULL)
*minor_status = 0;
if (new_oidset != NULL)
*new_oidset = GSS_C_NO_OID_SET;
if (oidset == GSS_C_NO_OID_SET)
return (GSS_S_CALL_INACCESSIBLE_READ);
if (new_oidset == NULL)
return (GSS_S_CALL_INACCESSIBLE_WRITE);
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);
}