LCOV - code coverage report
Current view: top level - auth/gensec - gensec_util.c (source / functions) Hit Total Coverage
Test: coverage report for master 469b22b8 Lines: 122 146 83.6 %
Date: 2024-06-10 12:05:21 Functions: 20 20 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Generic Authentication Interface
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2006
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "auth/gensec/gensec.h"
      25             : #include "auth/gensec/gensec_internal.h"
      26             : #include "auth/credentials/credentials.h"
      27             : #include "auth/common_auth.h"
      28             : #include "../lib/util/asn1.h"
      29             : #include "param/param.h"
      30             : #include "libds/common/roles.h"
      31             : #include "lib/util/util_net.h"
      32             : 
      33             : #undef strcasecmp
      34             : 
      35             : #undef DBGC_CLASS
      36             : #define DBGC_CLASS DBGC_AUTH
      37             : 
      38       33367 : NTSTATUS gensec_generate_session_info_pac(TALLOC_CTX *mem_ctx,
      39             :                                           struct gensec_security *gensec_security,
      40             :                                           struct smb_krb5_context *smb_krb5_context,
      41             :                                           DATA_BLOB *pac_blob,
      42             :                                           const char *principal_string,
      43             :                                           const struct tsocket_address *remote_address,
      44             :                                           struct auth_session_info **session_info)
      45             : {
      46       33367 :         uint32_t session_info_flags = 0;
      47       33367 :         struct auth4_context *auth_context = NULL;
      48         888 :         NTSTATUS status;
      49             : 
      50       33367 :         if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
      51        8060 :                 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
      52             :         }
      53             : 
      54       33367 :         session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
      55             : 
      56       33367 :         if (!pac_blob) {
      57          13 :                 enum server_role server_role =
      58          13 :                         lpcfg_server_role(gensec_security->settings->lp_ctx);
      59             : 
      60             :                 /*
      61             :                  * For any domain setup (DC or member) we require having
      62             :                  * a PAC, as the service ticket comes from an AD DC,
      63             :                  * which will always provide a PAC, unless
      64             :                  * UF_NO_AUTH_DATA_REQUIRED is configured for our
      65             :                  * account, but that's just an invalid configuration,
      66             :                  * the admin configured for us!
      67             :                  *
      68             :                  * As a legacy case, we still allow kerberos tickets from an MIT
      69             :                  * realm, but only in standalone mode. In that mode we'll only
      70             :                  * ever accept a kerberos authentication with a keytab file
      71             :                  * being explicitly configured via the 'keytab method' option.
      72             :                  */
      73          13 :                 if (server_role != ROLE_STANDALONE) {
      74          13 :                         DBG_WARNING("Unable to find PAC in ticket from %s, "
      75             :                                     "failing to allow access\n",
      76             :                                     principal_string);
      77          13 :                         return NT_STATUS_NO_IMPERSONATION_TOKEN;
      78             :                 }
      79           0 :                 DBG_NOTICE("Unable to find PAC for %s, resorting to local "
      80             :                            "user lookup\n", principal_string);
      81             :         }
      82             : 
      83       33354 :         auth_context = gensec_security->auth_context;
      84             : 
      85       33354 :         if ((auth_context == NULL) ||
      86       33354 :             (auth_context->generate_session_info_pac == NULL)) {
      87           0 :                 DBG_ERR("Cannot generate a session_info without "
      88             :                         "the auth_context\n");
      89           0 :                 return NT_STATUS_INTERNAL_ERROR;
      90             :         }
      91             : 
      92       33354 :         status = auth_context->generate_session_info_pac(
      93             :                 auth_context,
      94             :                 mem_ctx,
      95             :                 smb_krb5_context,
      96             :                 pac_blob,
      97             :                 principal_string,
      98             :                 remote_address,
      99             :                 session_info_flags,
     100             :                 session_info);
     101       33354 :         return status;
     102             : }
     103             : 
     104             : /*
     105             :   magic check a GSS-API wrapper packet for an Kerberos OID
     106             : */
     107         108 : static bool gensec_gssapi_check_oid(const DATA_BLOB *blob, const char *oid)
     108             : {
     109         108 :         bool ret = false;
     110         108 :         struct asn1_data *data = asn1_init(NULL, ASN1_MAX_TREE_DEPTH);
     111             : 
     112         108 :         if (!data) return false;
     113             : 
     114         108 :         if (!asn1_load(data, *blob)) goto err;
     115         108 :         if (!asn1_start_tag(data, ASN1_APPLICATION(0))) goto err;
     116          70 :         if (!asn1_check_OID(data, oid)) goto err;
     117             : 
     118          70 :         ret = !asn1_has_error(data);
     119             : 
     120         108 :   err:
     121             : 
     122         108 :         asn1_free(data);
     123         108 :         return ret;
     124             : }
     125             : 
     126             : /**
     127             :  * Check if the packet is one for the KRB5 mechanism
     128             :  *
     129             :  * NOTE: This is a helper that can be employed by multiple mechanisms, do
     130             :  * not make assumptions about the private_data
     131             :  *
     132             :  * @param gensec_security GENSEC state, unused
     133             :  * @param in The request, as a DATA_BLOB
     134             :  * @return Error, INVALID_PARAMETER if it's not a packet for us
     135             :  *                or NT_STATUS_OK if the packet is ok.
     136             :  */
     137             : 
     138         108 : NTSTATUS gensec_magic_check_krb5_oid(struct gensec_security *unused,
     139             :                                         const DATA_BLOB *blob)
     140             : {
     141         108 :         if (gensec_gssapi_check_oid(blob, GENSEC_OID_KERBEROS5)) {
     142          70 :                 return NT_STATUS_OK;
     143             :         } else {
     144          38 :                 return NT_STATUS_INVALID_PARAMETER;
     145             :         }
     146             : }
     147             : 
     148       50380 : void gensec_child_want_feature(struct gensec_security *gensec_security,
     149             :                                uint32_t feature)
     150             : {
     151       50380 :         struct gensec_security *child_security = gensec_security->child_security;
     152             : 
     153       50380 :         gensec_security->want_features |= feature;
     154       50380 :         if (child_security == NULL) {
     155       43982 :                 return;
     156             :         }
     157        5513 :         gensec_want_feature(child_security, feature);
     158             : }
     159             : 
     160     2660404 : bool gensec_child_have_feature(struct gensec_security *gensec_security,
     161             :                                uint32_t feature)
     162             : {
     163     2660404 :         struct gensec_security *child_security = gensec_security->child_security;
     164             : 
     165     2660404 :         if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
     166             :                 /*
     167             :                  * All mechs with sub (child) mechs need to provide DCERPC
     168             :                  * header signing! This is required because the negotiation
     169             :                  * of header signing is done before the authentication
     170             :                  * is completed.
     171             :                  */
     172       16996 :                 return true;
     173             :         }
     174             : 
     175     2643114 :         if (child_security == NULL) {
     176           0 :                 return false;
     177             :         }
     178             : 
     179     2643114 :         return gensec_have_feature(child_security, feature);
     180             : }
     181             : 
     182      301334 : NTSTATUS gensec_child_unseal_packet(struct gensec_security *gensec_security,
     183             :                                     uint8_t *data, size_t length,
     184             :                                     const uint8_t *whole_pdu, size_t pdu_length,
     185             :                                     const DATA_BLOB *sig)
     186             : {
     187      301334 :         if (gensec_security->child_security == NULL) {
     188           0 :                 return NT_STATUS_INVALID_PARAMETER;
     189             :         }
     190             : 
     191      301334 :         return gensec_unseal_packet(gensec_security->child_security,
     192             :                                     data, length,
     193             :                                     whole_pdu, pdu_length,
     194             :                                     sig);
     195             : }
     196             : 
     197       53718 : NTSTATUS gensec_child_check_packet(struct gensec_security *gensec_security,
     198             :                                    const uint8_t *data, size_t length,
     199             :                                    const uint8_t *whole_pdu, size_t pdu_length,
     200             :                                    const DATA_BLOB *sig)
     201             : {
     202       53718 :         if (gensec_security->child_security == NULL) {
     203           0 :                 return NT_STATUS_INVALID_PARAMETER;
     204             :         }
     205             : 
     206       53718 :         return gensec_check_packet(gensec_security->child_security,
     207             :                                    data, length,
     208             :                                    whole_pdu, pdu_length,
     209             :                                    sig);
     210             : }
     211             : 
     212      301375 : NTSTATUS gensec_child_seal_packet(struct gensec_security *gensec_security,
     213             :                                   TALLOC_CTX *mem_ctx,
     214             :                                   uint8_t *data, size_t length,
     215             :                                   const uint8_t *whole_pdu, size_t pdu_length,
     216             :                                   DATA_BLOB *sig)
     217             : {
     218      301375 :         if (gensec_security->child_security == NULL) {
     219           0 :                 return NT_STATUS_INVALID_PARAMETER;
     220             :         }
     221             : 
     222      301375 :         return gensec_seal_packet(gensec_security->child_security,
     223             :                                   mem_ctx,
     224             :                                   data, length,
     225             :                                   whole_pdu, pdu_length,
     226             :                                   sig);
     227             : }
     228             : 
     229       53800 : NTSTATUS gensec_child_sign_packet(struct gensec_security *gensec_security,
     230             :                                   TALLOC_CTX *mem_ctx,
     231             :                                   const uint8_t *data, size_t length,
     232             :                                   const uint8_t *whole_pdu, size_t pdu_length,
     233             :                                   DATA_BLOB *sig)
     234             : {
     235       53800 :         if (gensec_security->child_security == NULL) {
     236           0 :                 return NT_STATUS_INVALID_PARAMETER;
     237             :         }
     238             : 
     239       53800 :         return gensec_sign_packet(gensec_security->child_security,
     240             :                                   mem_ctx,
     241             :                                   data, length,
     242             :                                   whole_pdu, pdu_length,
     243             :                                   sig);
     244             : }
     245             : 
     246     1476834 : NTSTATUS gensec_child_wrap(struct gensec_security *gensec_security,
     247             :                            TALLOC_CTX *mem_ctx,
     248             :                            const DATA_BLOB *in,
     249             :                            DATA_BLOB *out)
     250             : {
     251     1476834 :         if (gensec_security->child_security == NULL) {
     252           0 :                 return NT_STATUS_INVALID_PARAMETER;
     253             :         }
     254             : 
     255     1476834 :         return gensec_wrap(gensec_security->child_security,
     256             :                            mem_ctx, in, out);
     257             : }
     258             : 
     259     1476558 : NTSTATUS gensec_child_unwrap(struct gensec_security *gensec_security,
     260             :                              TALLOC_CTX *mem_ctx,
     261             :                              const DATA_BLOB *in,
     262             :                              DATA_BLOB *out)
     263             : {
     264     1476558 :         if (gensec_security->child_security == NULL) {
     265           0 :                 return NT_STATUS_INVALID_PARAMETER;
     266             :         }
     267             : 
     268     1476558 :         return gensec_unwrap(gensec_security->child_security,
     269             :                              mem_ctx, in, out);
     270             : }
     271             : 
     272      102370 : size_t gensec_child_sig_size(struct gensec_security *gensec_security,
     273             :                              size_t data_size)
     274             : {
     275      102370 :         if (gensec_security->child_security == NULL) {
     276           0 :                 return 0;
     277             :         }
     278             : 
     279      102370 :         return gensec_sig_size(gensec_security->child_security, data_size);
     280             : }
     281             : 
     282       52019 : size_t gensec_child_max_input_size(struct gensec_security *gensec_security)
     283             : {
     284       52019 :         if (gensec_security->child_security == NULL) {
     285           0 :                 return 0;
     286             :         }
     287             : 
     288       52019 :         return gensec_max_input_size(gensec_security->child_security);
     289             : }
     290             : 
     291       52019 : size_t gensec_child_max_wrapped_size(struct gensec_security *gensec_security)
     292             : {
     293       52019 :         if (gensec_security->child_security == NULL) {
     294           0 :                 return 0;
     295             :         }
     296             : 
     297       52019 :         return gensec_max_wrapped_size(gensec_security->child_security);
     298             : }
     299             : 
     300       42876 : NTSTATUS gensec_child_session_key(struct gensec_security *gensec_security,
     301             :                                   TALLOC_CTX *mem_ctx,
     302             :                                   DATA_BLOB *session_key)
     303             : {
     304       42876 :         if (gensec_security->child_security == NULL) {
     305           0 :                 return NT_STATUS_INVALID_PARAMETER;
     306             :         }
     307             : 
     308       42876 :         return gensec_session_key(gensec_security->child_security,
     309             :                                   mem_ctx,
     310             :                                   session_key);
     311             : }
     312             : 
     313       69350 : NTSTATUS gensec_child_session_info(struct gensec_security *gensec_security,
     314             :                                    TALLOC_CTX *mem_ctx,
     315             :                                    struct auth_session_info **session_info)
     316             : {
     317       69350 :         if (gensec_security->child_security == NULL) {
     318           0 :                 return NT_STATUS_INVALID_PARAMETER;
     319             :         }
     320             : 
     321       69350 :         return gensec_session_info(gensec_security->child_security,
     322             :                                    mem_ctx,
     323             :                                    session_info);
     324             : }
     325             : 
     326       54739 : NTTIME gensec_child_expire_time(struct gensec_security *gensec_security)
     327             : {
     328       54739 :         if (gensec_security->child_security == NULL) {
     329           0 :                 return GENSEC_EXPIRE_TIME_INFINITY;
     330             :         }
     331             : 
     332       54739 :         return gensec_expire_time(gensec_security->child_security);
     333             : }
     334             : 
     335       69276 : const char *gensec_child_final_auth_type(struct gensec_security *gensec_security)
     336             : {
     337       69276 :         if (gensec_security->child_security == NULL) {
     338           0 :                 return "NONE";
     339             :         }
     340             : 
     341       69276 :         return gensec_final_auth_type(gensec_security->child_security);
     342             : }
     343             : 
     344       30924 : char *gensec_get_unparsed_target_principal(struct gensec_security *gensec_security,
     345             :                                            TALLOC_CTX *mem_ctx)
     346             : {
     347       30924 :         const char *target_principal = gensec_get_target_principal(gensec_security);
     348       30924 :         const char *service = gensec_get_target_service(gensec_security);
     349       30924 :         const char *hostname = gensec_get_target_hostname(gensec_security);
     350             : 
     351       30924 :         if (target_principal != NULL) {
     352           0 :                 return talloc_strdup(mem_ctx, target_principal);
     353       30924 :         } else if (service != NULL && hostname != NULL) {
     354       30615 :                 return talloc_asprintf(mem_ctx, "%s/%s", service, hostname);
     355         309 :         } else if (hostname != NULL) {
     356           0 :                 return talloc_strdup(mem_ctx, target_principal);
     357             :         }
     358             : 
     359         309 :         return NULL;
     360             : }
     361             : 
     362       61697 : NTSTATUS gensec_kerberos_possible(struct gensec_security *gensec_security)
     363             : {
     364       61697 :         struct cli_credentials *creds = gensec_get_credentials(gensec_security);
     365       61697 :         bool auth_requested = cli_credentials_authentication_requested(creds);
     366        1048 :         enum credentials_use_kerberos krb5_state =
     367       61697 :                 cli_credentials_get_kerberos_state(creds);
     368       61697 :         char *user_principal = NULL;
     369       61697 :         const char *client_realm = cli_credentials_get_realm(creds);
     370       61697 :         const char *target_principal = gensec_get_target_principal(gensec_security);
     371       61697 :         const char *hostname = gensec_get_target_hostname(gensec_security);
     372             : 
     373       61697 :         if (!auth_requested) {
     374          76 :                 return NT_STATUS_INVALID_PARAMETER;
     375             :         }
     376             : 
     377       61621 :         if (krb5_state == CRED_USE_KERBEROS_DISABLED) {
     378           0 :                 return NT_STATUS_INVALID_PARAMETER;
     379             :         }
     380             : 
     381       61621 :         errno = 0;
     382       61621 :         user_principal = cli_credentials_get_principal(creds, gensec_security);
     383       61621 :         if (errno != 0) {
     384           0 :                 TALLOC_FREE(user_principal);
     385           0 :                 return NT_STATUS_NO_MEMORY;
     386             :         }
     387             : 
     388       61621 :         if (user_principal == NULL) {
     389         159 :                 return NT_STATUS_INVALID_PARAMETER;
     390             :         }
     391       61462 :         TALLOC_FREE(user_principal);
     392             : 
     393       61462 :         if (target_principal != NULL) {
     394         219 :                 return NT_STATUS_OK;
     395             :         }
     396             : 
     397       61243 :         if (client_realm == NULL) {
     398       25399 :                 return NT_STATUS_INVALID_PARAMETER;
     399             :         }
     400             : 
     401       35844 :         if (hostname == NULL) {
     402         291 :                 return NT_STATUS_INVALID_PARAMETER;
     403             :         }
     404             : 
     405       35553 :         if (strcasecmp(hostname, "localhost") == 0) {
     406           0 :                 return NT_STATUS_INVALID_PARAMETER;
     407             :         }
     408             : 
     409             : #define STAR_SMBSERVER "*SMBSERVER"
     410       35553 :         if (strcmp(hostname, STAR_SMBSERVER) == 0) {
     411           0 :                 return NT_STATUS_INVALID_PARAMETER;
     412             :         }
     413             : 
     414       35553 :         if (is_ipaddress(hostname)) {
     415        1782 :                 return NT_STATUS_INVALID_PARAMETER;
     416             :         }
     417             : 
     418       33771 :         return NT_STATUS_OK;
     419             : }

Generated by: LCOV version 1.14