1   /*
   2    * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
   3    * Use is subject to license terms.
   4    */
   5   
   6 | #pragma ident        "@(#)oid_ops.c        1.20        04/09/08 SMI"
   6 | #pragma ident        "@(#)oid_ops.c        1.19        04/02/23 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   
  73 |         if ((*oid != gss_nt_user_name) &&
  74 |                 (*oid != gss_nt_machine_uid_name) &&
  75 |                 (*oid != gss_nt_string_uid_name) &&
  76 |                 (*oid != gss_nt_service_name) &&
  77 |                 (*oid != gss_nt_exported_name) &&
  78 |                 (*oid != gss_nt_service_name_v2)) {
  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           p = (gss_OID) malloc(sizeof (gss_OID_desc));
  96 -                 *minor_status = ENOMEM;
 107           if (!p) {
 108                   return (GSS_S_FAILURE);
 109           }
 110           p->length = oid->length;
 111           p->elements = malloc(p->length);
 112           if (!p->elements) {
 103 -                 *minor_status = ENOMEM;
 113                   free(p);
 114                   return (GSS_S_FAILURE);
 115           }
 116           (void) memcpy(p->elements, oid->elements, p->length);
 117           *new_oid = p;
 118           return (GSS_S_COMPLETE);
 119   }
 120   
 121   
 122   OM_uint32
 123   generic_gss_create_empty_oid_set(minor_status, oid_set)
 124   OM_uint32 *minor_status;
 125   gss_OID_set *oid_set;
 126   {
 127 +         if (minor_status)
 128 +                 *minor_status = 0;
 129 + 
 130           if ((*oid_set = (gss_OID_set) malloc(sizeof (gss_OID_set_desc)))) {
 119 -                 *minor_status = 0;
 131                   (void) memset(*oid_set, 0, sizeof (gss_OID_set_desc));
 132                   return (GSS_S_COMPLETE);
 122 -                 *minor_status = ENOMEM;
 133           } else {
 134                   return (GSS_S_FAILURE);
 135           }
 136   }
 137   
 138   OM_uint32
 139   generic_gss_add_oid_set_member(minor_status, member_oid, oid_set)
 140   OM_uint32 *minor_status;
 141   const gss_OID member_oid;
 142   gss_OID_set *oid_set;
 143   {
 144           gss_OID elist;
 145           gss_OID lastel;
 146   
 147 +         if (minor_status)
 148 +                 *minor_status = 0;
 149 + 
 150 +         if (member_oid == NULL || member_oid->length == 0 ||
 151 +                 member_oid->elements == NULL)
 152 +                 return (GSS_S_CALL_INACCESSIBLE_READ);
 153 + 
 154           elist = (*oid_set)->elements;
 155           /* Get an enlarged copy of the array */
 156           if (((*oid_set)->elements = (gss_OID) malloc(((*oid_set)->count+1) *
 157                                           sizeof (gss_OID_desc)))) {
 158           /* Copy in the old junk */
 159                   if (elist)
 160                           (void) memcpy((*oid_set)->elements, elist,
 161                                   ((*oid_set)->count * sizeof (gss_OID_desc)));
 162   
 163           /* Duplicate the input element */
 164                   lastel = &(*oid_set)->elements[(*oid_set)->count];
 165                   if ((lastel->elements =
 166                           (void *) malloc(member_oid->length))) {
 167                   /* Success - copy elements */
 168                           (void) memcpy(lastel->elements, member_oid->elements,
 169                                           member_oid->length);
 170                   /* Set length */
 171                           lastel->length = member_oid->length;
 172   
 173                   /* Update count */
 174                           (*oid_set)->count++;
 175                           if (elist)
 176                                   free(elist);
 177                           return (GSS_S_COMPLETE);
 178                   } else
 179                           free((*oid_set)->elements);
 180           }
 181           /* Failure - restore old contents of list */
 165 -         *minor_status = ENOMEM;
 182           (*oid_set)->elements = elist;
 183           return (GSS_S_FAILURE);
 184   }
 185   
 186   OM_uint32
 187   generic_gss_test_oid_set_member(minor_status, member, set, present)
 188       OM_uint32                *minor_status;
 189       const gss_OID        member;
 190       const gss_OID_set        set;
 191       int                        *present;
 192   {
 176 |         size_t i;
 193 |         OM_uint32 i;
 194           int result;
 195   
 196 +         if (minor_status)
 197 +                 *minor_status = 0;
 198 + 
 199 +         if (member == NULL || set == NULL)
 200 +                 return (GSS_S_CALL_INACCESSIBLE_READ);
 201 + 
 202 +         if (present == NULL)
 203 +                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
 204 + 
 205           result = 0;
 206           for (i = 0; i < set->count; i++) {
 207                   if ((set->elements[i].length == member->length) &&
 208                           !memcmp(set->elements[i].elements,
 209                                   member->elements, member->length)) {
 210                           result = 1;
 211                           break;
 212                   }
 213           }
 189 -         *minor_status = 0;
 214           *present = result;
 215           return (GSS_S_COMPLETE);
 216   }
 217   
 218   /*
 219    * OID<->string routines.  These are uuuuugly.
 220    */
 221   OM_uint32
 222   generic_gss_oid_to_str(minor_status, oid, oid_str)
 223   OM_uint32 *minor_status;
 224   const gss_OID oid;
 225   gss_buffer_t oid_str;
 226   {
 227           char numstr[128];
 203 |         unsigned long number;
 228 |         OM_uint32 number;
 229           int numshift;
 205 |         size_t string_length;
 206 |         size_t i;
 230 |         OM_uint32 string_length;
 231 |         OM_uint32 i;
 232           unsigned char *cp;
 233           char *bp;
 234   
 235 +         if (minor_status)
 236 +                 *minor_status = 0;
 237 + 
 238 +         if (oid == NULL || oid->length == 0 || oid->elements == NULL)
 239 +                 return (GSS_S_CALL_INACCESSIBLE_READ);
 240 + 
 241 +         if (oid_str == NULL)
 242 +                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
 243 + 
 244           /* Decoded according to krb5/gssapi_krb5.c */
 245   
 246           /* First determine the size of the string */
 247           string_length = 0;
 248           number = 0;
 249           numshift = 0;
 250           cp = (unsigned char *) oid->elements;
 251           number = (OM_uint32) cp[0];
 252           (void) sprintf(numstr, "%d ", number/40);
 253           string_length += strlen(numstr);
 254           (void) sprintf(numstr, "%d ", number%40);
 255           string_length += strlen(numstr);
 256           for (i = 1; i < oid->length; i++) {
 223 |                 if ((size_t) (numshift+7) < (sizeof (unsigned long)*8)) {
 257 |                 if ((OM_uint32) (numshift+7) < (sizeof (OM_uint32)*8)) {
 258                           number = (number << 7) | (cp[i] & 0x7f);
 259                           numshift += 7;
 227 -                         *minor_status = EINVAL;
 260                   } else {
 261                           return (GSS_S_FAILURE);
 262                   }
 263   
 264                   if ((cp[i] & 0x80) == 0) {
 265                           (void) sprintf(numstr, "%d ", number);
 266                           string_length += strlen(numstr);
 267                           number = 0;
 268                           numshift = 0;
 269                   }
 270           }
 271           /*
 272           * If we get here, we've calculated the length of "n n n ... n ".  Add 4
 273           * here for "{ " and "}\0".
 274           */
 275           string_length += 4;
 276           if ((bp = (char *)malloc(string_length))) {
 277                   (void) strcpy(bp, "{ ");
 245 |                 number = (unsigned long) cp[0];
 278 |                 number = (OM_uint32) cp[0];
 279                   (void) sprintf(numstr, "%d ", number/40);
 280                   (void) strcat(bp, numstr);
 281                   (void) sprintf(numstr, "%d ", number%40);
 282                   (void) strcat(bp, numstr);
 283                   number = 0;
 284                   cp = (unsigned char *) oid->elements;
 285                   for (i = 1; i < oid->length; i++) {
 286                           number = (number << 7) | (cp[i] & 0x7f);
 287                           if ((cp[i] & 0x80) == 0) {
 288                                   (void) sprintf(numstr, "%d ", number);
 289                                   (void) strcat(bp, numstr);
 290                                   number = 0;
 291                           }
 292                   }
 293                   (void) strcat(bp, "}");
 294                   oid_str->length = strlen(bp)+1;
 263 -                 *minor_status = 0;
 295                   oid_str->value = (void *) bp;
 296                   return (GSS_S_COMPLETE);
 266 -         *minor_status = ENOMEM;
 297           }
 298           return (GSS_S_FAILURE);
 299   }
 300   
 301   /*
 302    * This routine will handle 2 types of oid string formats:
 303    *         1 - { 1 2 3 4 }  where the braces are optional
 304    *        2 - 1.2.3.4 this is an alernative format
 305    * The first format is mandated by the gss spec.  The
 306    * second format is popular outside of the gss community so
 307    * has been added.
 308    */
 309   OM_uint32
 310   generic_gss_str_to_oid(minor_status, oid_str, oid)
 311   OM_uint32 *minor_status;
 312   const gss_buffer_t oid_str;
 313   gss_OID *oid;
 314   {
 315           char *cp, *bp, *startp;
 316           int brace;
 317           int numbuf;
 318           int onumbuf;
 319           OM_uint32 nbytes;
 289 |         int idx;
 320 |         int index;
 321           unsigned char *op;
 322   
 323 +         if (minor_status)
 324 +                 *minor_status = 0;
 325 + 
 326 +         if (GSS_EMPTY_BUFFER(oid_str))
 327 +                 return (GSS_S_CALL_INACCESSIBLE_READ);
 328 + 
 329 +         if (oid == NULL)
 330 +                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
 331 + 
 332           brace = 0;
 333           bp = (char *)oid_str->value;
 334           cp = bp;
 335           /* Skip over leading space */
 336           while ((bp < &cp[oid_str->length]) && isspace(*bp))
 337                   bp++;
 338           if (*bp == '{') {
 339                   brace = 1;
 340                   bp++;
 341           }
 342           while ((bp < &cp[oid_str->length]) && isspace(*bp))
 343                   bp++;
 344           startp = bp;
 345           nbytes = 0;
 346   
 347           /*
 348           * The first two numbers are chewed up by the first octet.
 349           */
 311 -                 *minor_status = EINVAL;
 350           if (sscanf(bp, "%d", &numbuf) != 1) {
 351                   return (GSS_S_FAILURE);
 352           }
 353           while ((bp < &cp[oid_str->length]) && isdigit(*bp))
 354                   bp++;
 355           while ((bp < &cp[oid_str->length]) &&
 356                   (isspace(*bp) || *bp == '.'))
 357                   bp++;
 320 -                 *minor_status = EINVAL;
 358           if (sscanf(bp, "%d", &numbuf) != 1) {
 359                   return (GSS_S_FAILURE);
 360           }
 323 |         while ((bp < &cp[oid_str->length]) && isdigit((int) *bp))
 361 |         while ((bp < &cp[oid_str->length]) && isdigit(*bp))
 362                   bp++;
 325 |         while ((bp < &cp[oid_str->length]) && isspace((int) *bp)
 363 |         while ((bp < &cp[oid_str->length]) &&
 364 +                 (isspace(*bp) || *bp == '.'))
 365                   bp++;
 366           nbytes++;
 328 |         while (isdigit((int) *bp)) {
 329 |                 if (sscanf(bp, "%ld", &numbuf) != 1) {
 367 |         while (isdigit(*bp)) {
 368 |                 if (sscanf(bp, "%d", &numbuf) != 1) {
 330 -                         *minor_status = EINVAL;
 369                           return (GSS_S_FAILURE);
 370                   }
 371                   while (numbuf) {
 372                           nbytes++;
 373                           numbuf >>= 7;
 374                   }
 337 |                 while ((bp < &cp[oid_str->length]) && isdigit((int) *bp))
 375 |                 while ((bp < &cp[oid_str->length]) && isdigit(*bp))
 376                           bp++;
 339 |                 while ((bp < &cp[oid_str->length]) && isspace((int) *bp))
 377 |                 while ((bp < &cp[oid_str->length]) &&
 378 +                         (isspace(*bp) || *bp == '.'))
 379                           bp++;
 380           }
 343 -                 *minor_status = EINVAL;
 381           if (brace && (*bp != '}')) {
 382                   return (GSS_S_FAILURE);
 383           }
 384   
 385           /*
 386            * Phew!  We've come this far, so the syntax is good.
 387            */
 388           if ((*oid = (gss_OID) malloc(sizeof (gss_OID_desc)))) {
 351 |                 if (((*oid)->elements = (void *) malloc((size_t) nbytes))) {
 389 |                 if (((*oid)->elements = (void *) malloc(nbytes))) {
 390                           (*oid)->length = nbytes;
 391                           op = (unsigned char *) (*oid)->elements;
 392                           bp = startp;
 355 |                         (void) sscanf(bp, "%ld", &numbuf);
 356 |                         while (isdigit((int) *bp))
 393 |                         (void) sscanf(bp, "%d", &numbuf);
 394 |                         while (isdigit(*bp))
 395                                   bp++;
 358 |                         while (isspace((int) *bp) || *bp == '.')
 396 |                         while (isspace(*bp) || *bp == '.')
 397                                   bp++;
 398                           onumbuf = 40*numbuf;
 361 |                         (void) sscanf(bp, "%ld", &numbuf);
 399 |                         (void) sscanf(bp, "%d", &numbuf);
 400                           onumbuf += numbuf;
 401                           *op = (unsigned char) onumbuf;
 402                           op++;
 365 |                         while (isdigit((int) *bp))
 403 |                         while (isdigit(*bp))
 404                                   bp++;
 367 |                         while (isspace((int) *bp))
 405 |                         while (isspace(*bp) || *bp == '.')
 406                                   bp++;
 369 |                         while (isdigit((int) *bp)) {
 370 |                                 (void) sscanf(bp, "%ld", &numbuf);
 407 |                         while (isdigit(*bp)) {
 408 |                                 (void) sscanf(bp, "%d", &numbuf);
 409                                   nbytes = 0;
 410                   /* Have to fill in the bytes msb-first */
 411                                   onumbuf = numbuf;
 412                                   while (numbuf) {
 413                                           nbytes++;
 414                                           numbuf >>= 7;
 415                                   }
 416                                   numbuf = onumbuf;
 417                                   op += nbytes;
 418                                   index = -1;
 419                                   while (numbuf) {
 420                                           op[index] = (unsigned char)
 421                                                           numbuf & 0x7f;
 422                                           if (index != -1)
 423                                                   op[index] |= 0x80;
 424                                           index--;
 425                                           numbuf >>= 7;
 426                                   }
 389 |                                 while (isdigit((int) *bp))
 427 |                                 while (isdigit(*bp))
 428                                           bp++;
 391 |                                 while (isspace((int) *bp))
 429 |                                 while (isspace(*bp) || *bp == '.')
 430                                           bp++;
 394 -                         *minor_status = 0;
 431                           }
 432                           return (GSS_S_COMPLETE);
 433                   } else {
 434                           free(*oid);
 435                           *oid = GSS_C_NO_OID;
 436                   }
 401 -         *minor_status = ENOMEM;
 437           }
 438           return (GSS_S_FAILURE);
 439   }
 440   
 441 + /*
 442 +  * Copyright 1993 by OpenVision Technologies, Inc.
 443 +  *
 444 +  * Permission to use, copy, modify, distribute, and sell this software
 445 +  * and its documentation for any purpose is hereby granted without fee,
 446 +  * provided that the above copyright notice appears in all copies and
 447 +  * that both that copyright notice and this permission notice appear in
 448 +  * supporting documentation, and that the name of OpenVision not be used
 449 +  * in advertising or publicity pertaining to distribution of the software
 450 +  * without specific, written prior permission. OpenVision makes no
 451 +  * representations about the suitability of this software for any
 452 +  * purpose.  It is provided "as is" without express or implied warranty.
 453 +  *
 454 +  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 455 +  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 456 +  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 457 +  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
 458 +  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 459 +  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 460 +  * PERFORMANCE OF THIS SOFTWARE.
 461 +  */
 462 + OM_uint32
 463 + gss_copy_oid_set(
 464 +         OM_uint32 *minor_status,
 465 +         const gss_OID_set_desc * const oidset,
 466 +         gss_OID_set *new_oidset
 467 + )
 468 + {
 469 +         gss_OID_set_desc *copy;
 470 +         OM_uint32 minor = 0;
 471 +         OM_uint32 major = GSS_S_COMPLETE;
 472 +         OM_uint32 index;
 473 + 
 474 +         if (minor_status)
 475 +                 *minor_status = 0;
 476 + 
 477 +         if (oidset == NULL)
 478 +                 return (GSS_S_CALL_INACCESSIBLE_READ);
 479 + 
 480 +         if (new_oidset == NULL)
 481 +                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
 482 + 
 483 +         *new_oidset = NULL;
 484 + 
 485 +         if ((copy = (gss_OID_set_desc *) calloc(1, sizeof (*copy))) == NULL) {
 486 +                 major = GSS_S_FAILURE;
 487 +                 goto done;
 488 +         }
 489 + 
 490 +         if ((copy->elements = (gss_OID_desc *)
 491 +             calloc(oidset->count, sizeof (*copy->elements))) == NULL) {
 492 +                 major = GSS_S_FAILURE;
 493 +                 goto done;
 494 +         }
 495 +         copy->count = oidset->count;
 496 + 
 497 +         for (index = 0; index < copy->count; index++) {
 498 +                 gss_OID_desc *out = &copy->elements[index];
 499 +                 gss_OID_desc *in = &oidset->elements[index];
 500 + 
 501 +                 if ((out->elements = (void *) malloc(in->length)) == NULL) {
 502 +                         major = GSS_S_FAILURE;
 503 +                         goto done;
 504 +                 }
 505 +                 (void) memcpy(out->elements, in->elements, in->length);
 506 +                 out->length = in->length;
 507 +         }
 508 + 
 509 +         *new_oidset = copy;
 510 + done:
 511 +         if (major != GSS_S_COMPLETE) {
 512 +                 (void) gss_release_oid_set(&minor, &copy);
 513 +         }
 514 + 
 515 +         return (major);
 516 + }