LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/gssapi/mech - gss_import_name.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 42 142 29.6 %
Date: 2024-04-21 15:09:00 Functions: 1 2 50.0 %

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2005 Doug Rabson
       3             :  * All rights reserved.
       4             :  *
       5             :  * Redistribution and use in source and binary forms, with or without
       6             :  * modification, are permitted provided that the following conditions
       7             :  * are met:
       8             :  * 1. Redistributions of source code must retain the above copyright
       9             :  *    notice, this list of conditions and the following disclaimer.
      10             :  * 2. Redistributions in binary form must reproduce the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer in the
      12             :  *    documentation and/or other materials provided with the distribution.
      13             :  *
      14             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      15             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      16             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      17             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      18             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      19             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      20             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      21             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      22             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      23             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      24             :  * SUCH DAMAGE.
      25             :  *
      26             :  *      $FreeBSD: src/lib/libgssapi/gss_import_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $
      27             :  */
      28             : 
      29             : #include "mech_locl.h"
      30             : 
      31             : static OM_uint32
      32           0 : _gss_import_export_name(OM_uint32 *minor_status,
      33             :     const gss_buffer_t input_name_buffer,
      34             :     const gss_OID name_type,
      35             :     gss_name_t *output_name)
      36             : {
      37           0 :         OM_uint32 major_status;
      38           0 :         unsigned char *p = input_name_buffer->value;
      39           0 :         size_t len = input_name_buffer->length;
      40           0 :         size_t t;
      41           0 :         gss_OID_desc mech_oid;
      42           0 :         gssapi_mech_interface m;
      43           0 :         struct _gss_name *name;
      44           0 :         gss_name_t new_canonical_name;
      45           0 :         int composite = 0;
      46             : 
      47           0 :         *minor_status = 0;
      48           0 :         *output_name = 0;
      49             : 
      50             :         /*
      51             :          * Make sure that TOK_ID is {4, 1}.
      52             :          */
      53           0 :         if (len < 2)
      54           0 :                 return (GSS_S_BAD_NAME);
      55           0 :         if (p[0] != 4)
      56           0 :                 return (GSS_S_BAD_NAME);
      57           0 :         switch (p[1]) {
      58           0 :         case 1: /* non-composite name */
      59           0 :                 break;
      60           0 :         case 2: /* composite name */
      61           0 :                 composite = 1;
      62           0 :                 break;
      63           0 :         default:
      64           0 :                 return (GSS_S_BAD_NAME);
      65             :         }
      66           0 :         p += 2;
      67           0 :         len -= 2;
      68             : 
      69             :         /*
      70             :          * If the name token is a composite token (TOK_ID 0x04 0x02) then per
      71             :          * RFC6680 everything after that is implementation-specific.  This
      72             :          * mech-glue is pluggable however, so we need the format of the rest of
      73             :          * the header to be stable, otherwise we couldn't reliably determine
      74             :          * what mechanism the token is for and we'd have to try all of them.
      75             :          *
      76             :          * So... we keep the same format for the exported composite name token
      77             :          * as for normal exported name tokens (see RFC2743, section 3.2), with
      78             :          * the TOK_ID 0x04 0x02, but only up to the mechanism OID.  We don't
      79             :          * enforce that there be a NAME_LEN in the exported composite name
      80             :          * token, or that it match the length of the remainder of the token.
      81             :          *
      82             :          * FYI, at least one out-of-tree mechanism implements exported
      83             :          * composite name tokens as the same as exported name tokens with
      84             :          * attributes appended and the NAME_LEN not modified to match.
      85             :          */
      86             : 
      87             :         /*
      88             :          * Get the mech length and the name length and sanity
      89             :          * check the size of of the buffer.
      90             :          */
      91           0 :         if (len < 2)
      92           0 :                 return (GSS_S_BAD_NAME);
      93           0 :         t = (p[0] << 8) + p[1];
      94           0 :         p += 2;
      95           0 :         len -= 2;
      96             : 
      97             :         /*
      98             :          * Check the DER encoded OID to make sure it agrees with the
      99             :          * length we just decoded.
     100             :          */
     101           0 :         if (p[0] != 6)          /* 6=OID */
     102           0 :                 return (GSS_S_BAD_NAME);
     103           0 :         p++;
     104           0 :         len--;
     105           0 :         t--;
     106           0 :         if (p[0] & 0x80) {
     107           0 :                 int digits = p[0];
     108           0 :                 p++;
     109           0 :                 len--;
     110           0 :                 t--;
     111           0 :                 mech_oid.length = 0;
     112           0 :                 while (digits--) {
     113           0 :                         mech_oid.length = (mech_oid.length << 8) | p[0];
     114           0 :                         p++;
     115           0 :                         len--;
     116           0 :                         t--;
     117             :                 }
     118             :         } else {
     119           0 :                 mech_oid.length = p[0];
     120           0 :                 p++;
     121           0 :                 len--;
     122           0 :                 t--;
     123             :         }
     124           0 :         if (mech_oid.length != t)
     125           0 :                 return (GSS_S_BAD_NAME);
     126             : 
     127           0 :         mech_oid.elements = p;
     128             : 
     129           0 :         if (!composite) {
     130           0 :                 if (len < t + 4)
     131           0 :                         return (GSS_S_BAD_NAME);
     132           0 :                 p += t;
     133           0 :                 len -= t;
     134             : 
     135           0 :                 t = ((unsigned long)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
     136             :                 /* p += 4; // we're done using `p' now */
     137           0 :                 len -= 4;
     138             : 
     139           0 :                 if (len != t)
     140           0 :                         return (GSS_S_BAD_NAME);
     141             :         }
     142             : 
     143           0 :         m = __gss_get_mechanism(&mech_oid);
     144           0 :         if (!m || !m->gm_import_name)
     145           0 :                 return (GSS_S_BAD_MECH);
     146             : 
     147             :         /*
     148             :          * Ask the mechanism to import the name.
     149             :          */
     150           0 :         major_status = m->gm_import_name(minor_status,
     151             :             input_name_buffer, name_type, &new_canonical_name);
     152           0 :         if (major_status != GSS_S_COMPLETE) {
     153           0 :                 _gss_mg_error(m, *minor_status);
     154           0 :                 return major_status;
     155             :         }
     156             : 
     157             :         /*
     158             :          * Now we make a new name and mark it as an MN.
     159             :          */
     160           0 :         name = _gss_create_name(new_canonical_name, m);
     161           0 :         if (!name) {
     162           0 :                 m->gm_release_name(minor_status, &new_canonical_name);
     163           0 :                 return (GSS_S_FAILURE);
     164             :         }
     165             : 
     166           0 :         *output_name = (gss_name_t) name;
     167             : 
     168           0 :         *minor_status = 0;
     169           0 :         return (GSS_S_COMPLETE);
     170             : }
     171             : 
     172             : /**
     173             :  * Convert a GGS-API name from contiguous string to internal form.
     174             :  *
     175             :  * Type of name and their format:
     176             :  * - GSS_C_NO_OID
     177             :  * - GSS_C_NT_USER_NAME
     178             :  * - GSS_C_NT_HOSTBASED_SERVICE
     179             :  * - GSS_C_NT_EXPORT_NAME
     180             :  * - GSS_C_NT_COMPOSITE_EXPORT
     181             :  * - GSS_C_NT_ANONYMOUS
     182             :  * - GSS_KRB5_NT_PRINCIPAL_NAME
     183             :  *
     184             :  * @sa gss_export_name(), @ref internalVSmechname.
     185             :  *
     186             :  * @param minor_status       minor status code
     187             :  * @param input_name_buffer  import name buffer
     188             :  * @param input_name_type    type of the import name buffer
     189             :  * @param output_name        the resulting type, release with
     190             :  *        gss_release_name(), independent of input_name
     191             :  *
     192             :  * @returns a gss_error code, see gss_display_status() about printing
     193             :  *        the error code.
     194             :  *
     195             :  * @ingroup gssapi
     196             :  */
     197             : 
     198             : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
     199       24237 : gss_import_name(OM_uint32 *minor_status,
     200             :     const gss_buffer_t input_name_buffer,
     201             :     const gss_OID input_name_type,
     202             :     gss_name_t *output_name)
     203             : {
     204        1035 :         struct _gss_mechanism_name *mn;
     205       24237 :         gss_OID                 name_type = input_name_type;
     206        1035 :         OM_uint32               major_status, ms;
     207        1035 :         struct _gss_name        *name;
     208        1035 :         struct _gss_mech_switch *m;
     209        1035 :         gss_name_t              rname;
     210             : 
     211       24237 :         if (input_name_buffer == GSS_C_NO_BUFFER)
     212           0 :                 return GSS_S_CALL_INACCESSIBLE_READ;
     213       24237 :         if (output_name == NULL)
     214           0 :                 return GSS_S_CALL_INACCESSIBLE_WRITE;
     215             : 
     216       24237 :         *output_name = GSS_C_NO_NAME;
     217             : 
     218             :         /* Allow empty names since that's valid (ANONYMOUS for example) */
     219             : 
     220       24237 :         _gss_load_mech();
     221             : 
     222             :         /*
     223             :          * If this is an exported name, we need to parse it to find
     224             :          * the mechanism and then import it as an MN. See RFC 2743
     225             :          * section 3.2 for a description of the format.
     226             :          */
     227       48474 :         if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME) ||
     228       24237 :             gss_oid_equal(name_type, GSS_C_NT_COMPOSITE_EXPORT)) {
     229           0 :                 return _gss_import_export_name(minor_status, input_name_buffer,
     230             :                                                name_type, output_name);
     231             :         }
     232             : 
     233             : 
     234       24237 :         *minor_status = 0;
     235       24237 :         name = _gss_create_name(NULL, NULL);
     236       24237 :         if (!name) {
     237           0 :                 *minor_status = ENOMEM;
     238           0 :                 return (GSS_S_FAILURE);
     239             :         }
     240             : 
     241       24237 :         if (name_type != GSS_C_NO_OID) {
     242       24116 :                 major_status = _gss_intern_oid(minor_status,
     243             :                                                name_type, &name->gn_type);
     244       24116 :                 if (major_status) {
     245           0 :                         rname = (gss_name_t)name;
     246           0 :                         gss_release_name(&ms, (gss_name_t *)&rname);
     247           0 :                         return (GSS_S_FAILURE);
     248             :                 }
     249             :         } else
     250         121 :                 name->gn_type = GSS_C_NO_OID;
     251             : 
     252       25272 :         major_status = _gss_copy_buffer(minor_status,
     253       24237 :             input_name_buffer, &name->gn_value);
     254       24237 :         if (major_status)
     255           0 :                 goto out;
     256             : 
     257             :         /*
     258             :          * Walk over the mechs and import the name into a mech name
     259             :          * for those supported this nametype.
     260             :          */
     261             : 
     262       72711 :         HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
     263       48474 :                 int present = 0;
     264             : 
     265       48474 :                 if ((m->gm_mech.gm_flags & GM_USE_MG_NAME))
     266       24237 :                     continue;
     267             : 
     268       24237 :                 if (name_type != GSS_C_NO_OID) {
     269       24116 :                             major_status = gss_test_oid_set_member(minor_status,
     270             :                                     name_type, m->gm_name_types, &present);
     271             : 
     272       24116 :                             if (GSS_ERROR(major_status) || present == 0)
     273           0 :                                         continue;
     274             :                 }
     275             : 
     276       24237 :                 mn = malloc(sizeof(struct _gss_mechanism_name));
     277       24237 :                 if (!mn) {
     278           0 :                         *minor_status = ENOMEM;
     279           0 :                         major_status = GSS_S_FAILURE;
     280           0 :                         goto out;
     281             :                 }
     282             : 
     283       24237 :                 major_status = (*m->gm_mech.gm_import_name)(minor_status,
     284       23202 :                     &name->gn_value,
     285             :                     name->gn_type,
     286             :                     &mn->gmn_name);
     287       24237 :                 if (major_status != GSS_S_COMPLETE) {
     288           0 :                         _gss_mg_error(&m->gm_mech, *minor_status);
     289           0 :                         free(mn);
     290             :                         /**
     291             :                          * If we failed to import the name in a mechanism, it
     292             :                          * will be ignored as long as its possible to import
     293             :                          * name in some other mechanism. We will catch the
     294             :                          * failure later though in gss_init_sec_context() or
     295             :                          * another function.
     296             :                          */
     297           0 :                         continue;
     298             :                 }
     299             : 
     300       24237 :                 mn->gmn_mech = &m->gm_mech;
     301       24237 :                 mn->gmn_mech_oid = m->gm_mech_oid;
     302       24237 :                 HEIM_TAILQ_INSERT_TAIL(&name->gn_mn, mn, gmn_link);
     303             :         }
     304             : 
     305             :         /*
     306             :          * If we can't find a mn for the name, bail out already here.
     307             :          */
     308             : 
     309       24237 :         mn = HEIM_TAILQ_FIRST(&name->gn_mn);
     310       24237 :         if (!mn) {
     311           0 :                 *minor_status = 0;
     312           0 :                 major_status = GSS_S_NAME_NOT_MN;
     313           0 :                 goto out;
     314             :         }
     315             : 
     316       24237 :         *output_name = (gss_name_t) name;
     317       24237 :         return (GSS_S_COMPLETE);
     318             : 
     319           0 :  out:
     320           0 :         rname = (gss_name_t)name;
     321           0 :         gss_release_name(&ms, &rname);
     322           0 :         return major_status;
     323             : }

Generated by: LCOV version 1.14