LCOV - code coverage report
Current view: top level - lib/krb5_wrap - gss_samba.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 40 72 55.6 %
Date: 2024-05-31 13:13:24 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *
       4             :  *  Simple GSSAPI wrappers
       5             :  *
       6             :  *  Copyright (c) 2012      Andreas Schneider <asn@samba.org>
       7             :  *
       8             :  *  This program is free software; you can redistribute it and/or modify
       9             :  *  it under the terms of the GNU General Public License as published by
      10             :  *  the Free Software Foundation; either version 3 of the License, or
      11             :  *  (at your option) any later version.
      12             :  *
      13             :  *  This program is distributed in the hope that it will be useful,
      14             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  *  GNU General Public License for more details.
      17             :  *
      18             :  *  You should have received a copy of the GNU General Public License
      19             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include "includes.h"
      23             : #include "gss_samba.h"
      24             : 
      25             : #ifdef HAVE_GSSAPI
      26             : 
      27             : #if !defined(HAVE_GSS_OID_EQUAL)
      28             : int smb_gss_oid_equal(const gss_OID first_oid, const gss_OID second_oid)
      29             : {
      30             :         if (first_oid == GSS_C_NO_OID || second_oid == GSS_C_NO_OID) {
      31             :                 return 0;
      32             :         }
      33             : 
      34             :         if (first_oid == second_oid) {
      35             :                 return 1;
      36             :         }
      37             : 
      38             :         if ((first_oid)->length != (second_oid)->length) {
      39             :                 return 0;
      40             :         }
      41             : 
      42             :         if (memcmp((first_oid)->elements, (second_oid)->elements,
      43             :                    (first_oid)->length) == 0) {
      44             :                 return 1;
      45             :         }
      46             : 
      47             :         return 0;
      48             : }
      49             : #endif /* !HAVE_GSS_OID_EQUAL */
      50             : 
      51             : /* wrapper around gss_krb5_import_cred() that prefers to use gss_acquire_cred_from()
      52             :  * if this GSSAPI extension is available. gss_acquire_cred_from() is properly
      53             :  * interposed by GSSPROXY while gss_krb5_import_cred() is not.
      54             :  *
      55             :  * This wrapper requires a proper krb5_context to resolve ccache name.
      56             :  * All gss_krb5_import_cred() callers in Samba already have krb5_context available. */
      57       64632 : uint32_t smb_gss_krb5_import_cred(uint32_t *minor_status,
      58             :                                   krb5_context ctx,
      59             :                                   krb5_ccache id,
      60             :                                   krb5_principal keytab_principal,
      61             :                                   krb5_keytab keytab,
      62             :                                   gss_cred_id_t *cred)
      63             : {
      64       64632 :         return smb_gss_mech_import_cred(minor_status,
      65             :                                         ctx,
      66             :                                         id,
      67             :                                         keytab_principal,
      68             :                                         keytab,
      69             :                                         gss_mech_krb5,
      70             :                                         cred);
      71             : }
      72             : 
      73       68185 : uint32_t smb_gss_mech_import_cred(OM_uint32 *minor_status,
      74             :                                   krb5_context ctx,
      75             :                                   krb5_ccache id,
      76             :                                   krb5_principal keytab_principal,
      77             :                                   krb5_keytab keytab,
      78             :                                   const struct gss_OID_desc_struct *mech,
      79             :                                   gss_cred_id_t *cred)
      80             : {
      81       68185 :         uint32_t major_status = 0;
      82             : 
      83             : #ifdef HAVE_GSS_ACQUIRE_CRED_FROM
      84       18664 :         uint32_t minor = 0;
      85       18664 :         gss_key_value_element_desc ccache_element = {
      86             :                 .key = "ccache",
      87             :                 .value = NULL,
      88             :         };
      89             : 
      90       18664 :         gss_key_value_element_desc keytab_element = {
      91             :                 .key = "keytab",
      92             :                 .value = NULL,
      93             :         };
      94             : 
      95             :         gss_key_value_element_desc elements[2];
      96             : 
      97       18664 :         gss_key_value_set_desc cred_store = {
      98             :                 .elements = &ccache_element,
      99             :                 .count = 1,
     100             :         };
     101             : 
     102             :         /* we are interested exclusively in krb5 credentials,
     103             :          * indicate to GSSAPI that we are not interested in any other
     104             :          * mechanism here */
     105       18664 :         gss_OID_set_desc mech_set = {
     106             :                 .count = 1,
     107             :                 .elements = discard_const_p(struct gss_OID_desc_struct,
     108             :                                             mech),
     109             :         };
     110             : 
     111       18664 :         gss_cred_usage_t cred_usage = GSS_C_INITIATE;
     112       18664 :         gss_name_t name = NULL;
     113       18664 :         gss_buffer_desc pr_name = {
     114             :                 .value = NULL,
     115             :                 .length = 0,
     116             :         };
     117             : 
     118       18664 :         if (id != NULL) {
     119        4484 :                 major_status = krb5_cc_get_full_name(ctx,
     120             :                                                      id,
     121             :                                                      discard_const(&ccache_element.value));
     122        4484 :                 if (major_status != 0) {
     123           0 :                         return major_status;
     124             :                 }
     125             :         }
     126             : 
     127       18664 :         if (keytab != NULL) {
     128       14180 :                 keytab_element.value = malloc(4096);
     129       14180 :                 if (!keytab_element.value) {
     130           0 :                         return ENOMEM;
     131             :                 }
     132       28360 :                 major_status = krb5_kt_get_name(ctx,
     133             :                                                 keytab,
     134       14180 :                                                 discard_const(keytab_element.value), 4096);
     135       14180 :                 if (major_status != 0) {
     136           0 :                         free(discard_const(keytab_element.value));
     137           0 :                         return major_status;
     138             :                 }
     139       14180 :                 cred_usage = GSS_C_ACCEPT;
     140       14180 :                 cred_store.elements = &keytab_element;
     141             : 
     142       14180 :                 if (keytab_principal != NULL) {
     143       12422 :                         major_status = krb5_unparse_name(ctx, keytab_principal, (char**)&pr_name.value);
     144       12422 :                         if (major_status != 0) {
     145           0 :                                 free(discard_const(keytab_element.value));
     146           0 :                                 return major_status;
     147             :                         }
     148       12422 :                         pr_name.length = strlen(pr_name.value);
     149             : 
     150       12422 :                         major_status = gss_import_name(minor_status,
     151             :                                                        &pr_name,
     152             :                                                        discard_const(GSS_KRB5_NT_PRINCIPAL_NAME),
     153             :                                                        &name);
     154       12422 :                         if (major_status != 0) {
     155           0 :                                 krb5_free_unparsed_name(ctx, pr_name.value);
     156           0 :                                 free(discard_const(keytab_element.value));
     157           0 :                                 return major_status;
     158             :                         }
     159             :                 }
     160             :         }
     161             : 
     162       18664 :         if (id != NULL && keytab != NULL) {
     163           0 :                 elements[0] = ccache_element;
     164           0 :                 elements[1] = keytab_element;
     165             : 
     166           0 :                 cred_store.elements = elements;
     167           0 :                 cred_store.count = 2;
     168           0 :                 cred_usage = GSS_C_BOTH;
     169             :         }
     170             : 
     171       18664 :         major_status = gss_acquire_cred_from(minor_status,
     172             :                                              name,
     173             :                                              0,
     174             :                                              &mech_set,
     175             :                                              cred_usage,
     176             :                                              &cred_store,
     177             :                                              cred,
     178             :                                              NULL,
     179             :                                              NULL);
     180             : 
     181       18664 :         if (pr_name.value != NULL) {
     182       12422 :                 (void)gss_release_name(&minor, &name);
     183       12422 :                 krb5_free_unparsed_name(ctx, pr_name.value);
     184             :         }
     185       18664 :         if (keytab_element.value != NULL) {
     186       14180 :                 free(discard_const(keytab_element.value));
     187             :         }
     188       18664 :         krb5_free_string(ctx, discard_const(ccache_element.value));
     189             : #else
     190       49521 :         major_status = gss_krb5_import_cred(minor_status,
     191             :                                             id,
     192             :                                             keytab_principal,
     193             :                                             keytab, cred);
     194             : 
     195       49521 :         if (major_status == (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME)) {
     196           0 :                 if ((keytab_principal == NULL) && (keytab != NULL)) {
     197             :                         /* No principal was specified and MIT krb5 1.9 version failed.
     198             :                          * We have to fall back to set global acceptor identity */
     199           0 :                         gss_OID_set_desc mech_set;
     200           0 :                         char *kt_name = NULL;
     201             : 
     202           0 :                         kt_name = malloc(4096);
     203           0 :                         if (!kt_name) {
     204           0 :                                 return ENOMEM;
     205             :                         }
     206             : 
     207           0 :                         major_status = krb5_kt_get_name(ctx,
     208             :                                                         keytab,
     209             :                                                         kt_name, 4096);
     210           0 :                         if (major_status != 0) {
     211           0 :                                 free(kt_name);
     212           0 :                                 return major_status;
     213             :                         }
     214             : 
     215           0 :                         major_status = gsskrb5_register_acceptor_identity(kt_name);
     216           0 :                         if (major_status) {
     217           0 :                                 free(kt_name);
     218           0 :                                 return major_status;
     219             :                         }
     220             : 
     221             :                         /* We are dealing with krb5 GSSAPI mech in this fallback */
     222           0 :                         mech_set.count = 1;
     223           0 :                         mech_set.elements =
     224             :                                 discard_const_p(struct gss_OID_desc_struct,
     225             :                                                 gss_mech_krb5);
     226           0 :                         major_status = gss_acquire_cred(minor_status,
     227             :                                                         GSS_C_NO_NAME,
     228             :                                                         GSS_C_INDEFINITE,
     229             :                                                         &mech_set,
     230             :                                                         GSS_C_ACCEPT,
     231             :                                                         cred,
     232             :                                                         NULL, NULL);
     233           0 :                         free(kt_name);
     234             :                 }
     235             :         }
     236             : #endif
     237       65409 :         return major_status;
     238             : }
     239             : 
     240             : 
     241             : #endif /* HAVE_GSSAPI */

Generated by: LCOV version 1.14