Home | History | Annotate | Line # | Download | only in mech
      1 /*	$NetBSD: gss_pname_to_uid.c,v 1.4 2023/06/19 21:41:43 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2011, PADL Software Pty Ltd.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  *
     18  * 3. Neither the name of PADL Software nor the names of its contributors
     19  *    may be used to endorse or promote products derived from this software
     20  *    without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
     23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
     26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32  * SUCH DAMAGE.
     33  */
     34 
     35 #include "mech_locl.h"
     36 
     37 static OM_uint32
     38 mech_localname(OM_uint32 *minor_status,
     39                struct _gss_mechanism_name *mn,
     40                gss_buffer_t localname)
     41 {
     42     OM_uint32 major_status = GSS_S_UNAVAILABLE;
     43 
     44     *minor_status = 0;
     45 
     46     if (mn->gmn_mech->gm_localname == NULL)
     47         return GSS_S_UNAVAILABLE;
     48 
     49     major_status = mn->gmn_mech->gm_localname(minor_status,
     50                                               mn->gmn_name,
     51                                               mn->gmn_mech_oid,
     52                                               localname);
     53     if (GSS_ERROR(major_status))
     54         _gss_mg_error(mn->gmn_mech, major_status, *minor_status);
     55 
     56     return major_status;
     57 }
     58 
     59 static OM_uint32
     60 attr_localname(OM_uint32 *minor_status,
     61                struct _gss_mechanism_name *mn,
     62                gss_buffer_t localname)
     63 {
     64     OM_uint32 major_status = GSS_S_UNAVAILABLE;
     65     OM_uint32 tmpMinor;
     66     gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
     67     gss_buffer_desc display_value = GSS_C_EMPTY_BUFFER;
     68     int authenticated = 0, complete = 0;
     69     int more = -1;
     70 
     71     *minor_status = 0;
     72 
     73     localname->length = 0;
     74     localname->value = NULL;
     75 
     76     if (mn->gmn_mech->gm_get_name_attribute == NULL)
     77         return GSS_S_UNAVAILABLE;
     78 
     79     major_status = mn->gmn_mech->gm_get_name_attribute(minor_status,
     80                                                        mn->gmn_name,
     81                                                        GSS_C_ATTR_LOCAL_LOGIN_USER,
     82                                                        &authenticated,
     83                                                        &complete,
     84                                                        &value,
     85                                                        &display_value,
     86                                                        &more);
     87     if (GSS_ERROR(major_status)) {
     88         _gss_mg_error(mn->gmn_mech, major_status, *minor_status);
     89         return major_status;
     90     }
     91 
     92     if (authenticated) {
     93         *localname = value;
     94     } else {
     95         major_status = GSS_S_UNAVAILABLE;
     96         gss_release_buffer(&tmpMinor, &value);
     97     }
     98 
     99     gss_release_buffer(&tmpMinor, &display_value);
    100 
    101     return major_status;
    102 }
    103 
    104 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
    105 gss_localname(OM_uint32 *minor_status,
    106               gss_const_name_t pname,
    107               const gss_OID mech_type,
    108               gss_buffer_t localname)
    109 {
    110     OM_uint32 major_status = GSS_S_UNAVAILABLE;
    111     struct _gss_name *name = (struct _gss_name *) pname;
    112     struct _gss_mechanism_name *mn = NULL;
    113 
    114     *minor_status = 0;
    115 
    116     if (mech_type != GSS_C_NO_OID) {
    117         major_status = _gss_find_mn(minor_status, name, mech_type, &mn);
    118         if (GSS_ERROR(major_status))
    119             return major_status;
    120 
    121         major_status = mech_localname(minor_status, mn, localname);
    122         if (major_status != GSS_S_COMPLETE)
    123             major_status = attr_localname(minor_status, mn, localname);
    124     } else {
    125         HEIM_SLIST_FOREACH(mn, &name->gn_mn, gmn_link) {
    126             major_status = mech_localname(minor_status, mn, localname);
    127             if (major_status != GSS_S_COMPLETE)
    128                 major_status = attr_localname(minor_status, mn, localname);
    129             if (major_status != GSS_S_UNAVAILABLE)
    130                 break;
    131         }
    132     }
    133 
    134     if (major_status != GSS_S_COMPLETE && mn != NULL)
    135         _gss_mg_error(mn->gmn_mech, major_status, *minor_status);
    136 
    137     return major_status;
    138 }
    139 
    140 
    141 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
    142 gss_pname_to_uid(OM_uint32 *minor_status,
    143                  gss_const_name_t pname,
    144                  const gss_OID mech_type,
    145                  uid_t *uidp)
    146 {
    147 #ifdef NO_LOCALNAME
    148     return GSS_S_UNAVAILABLE;
    149 #else
    150     OM_uint32 major, tmpMinor;
    151     gss_buffer_desc localname = GSS_C_EMPTY_BUFFER;
    152     char *szLocalname;
    153     char pwbuf[2048];
    154     struct passwd pw, *pwd;
    155 
    156     major = gss_localname(minor_status, pname, mech_type, &localname);
    157     if (GSS_ERROR(major))
    158         return major;
    159     if (localname.length == 0) {
    160         *minor_status = KRB5_NO_LOCALNAME;
    161         return GSS_S_FAILURE;
    162     }
    163 
    164     szLocalname = malloc(localname.length + 1);
    165     if (szLocalname == NULL) {
    166         gss_release_buffer(&tmpMinor, &localname);
    167         *minor_status = ENOMEM;
    168         return GSS_S_FAILURE;
    169     }
    170 
    171     memcpy(szLocalname, localname.value, localname.length);
    172     szLocalname[localname.length] = '\0';
    173 
    174     if (rk_getpwnam_r(szLocalname, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0)
    175         pwd = NULL;
    176 
    177     gss_release_buffer(&tmpMinor, &localname);
    178     free(szLocalname);
    179 
    180     *minor_status = 0;
    181 
    182     if (pwd != NULL) {
    183         *uidp = pwd->pw_uid;
    184         major = GSS_S_COMPLETE;
    185     } else {
    186         major = GSS_S_UNAVAILABLE;
    187     }
    188 
    189     return major;
    190 #endif
    191 }
    192