LCOV - code coverage report
Current view: top level - source3/auth - user_krb5.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 50 107 46.7 %
Date: 2021-09-23 10:06:22 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Authentication utility functions
       4             :    Copyright (C) Simo Sorce 2010
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "auth.h"
      22             : #include "librpc/gen_ndr/krb5pac.h"
      23             : #include "nsswitch/libwbclient/wbclient.h"
      24             : #include "passdb.h"
      25             : #include "lib/param/loadparm.h"
      26             : 
      27             : #undef DBGC_CLASS
      28             : #define DBGC_CLASS DBGC_AUTH
      29             : 
      30             : #ifdef HAVE_KRB5
      31         554 : NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
      32             :                                      const char *cli_name,
      33             :                                      const char *princ_name,
      34             :                                      struct PAC_LOGON_INFO *logon_info,
      35             :                                      bool *is_mapped,
      36             :                                      bool *mapped_to_guest,
      37             :                                      char **ntuser,
      38             :                                      char **ntdomain,
      39             :                                      char **username,
      40             :                                      struct passwd **_pw)
      41             : {
      42             :         NTSTATUS status;
      43         554 :         char *domain = NULL;
      44         554 :         char *realm = NULL;
      45         554 :         char *user = NULL;
      46             :         char *p;
      47         554 :         char *fuser = NULL;
      48         554 :         char *unixuser = NULL;
      49         554 :         struct passwd *pw = NULL;
      50             : 
      51         554 :         DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name));
      52             : 
      53         554 :         p = strchr_m(princ_name, '@');
      54         554 :         if (!p) {
      55           0 :                 DEBUG(3, ("[%s] Doesn't look like a valid principal\n",
      56             :                           princ_name));
      57           0 :                 return NT_STATUS_LOGON_FAILURE;
      58             :         }
      59             : 
      60         554 :         user = talloc_strndup(mem_ctx, princ_name, p - princ_name);
      61         554 :         if (!user) {
      62           0 :                 return NT_STATUS_NO_MEMORY;
      63             :         }
      64             : 
      65         554 :         realm = talloc_strdup(talloc_tos(), p + 1);
      66         554 :         if (!realm) {
      67           0 :                 return NT_STATUS_NO_MEMORY;
      68             :         }
      69             : 
      70         554 :         if (!strequal(realm, lp_realm())) {
      71           2 :                 DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm));
      72           2 :                 if (!lp_allow_trusted_domains()) {
      73           0 :                         return NT_STATUS_LOGON_FAILURE;
      74             :                 }
      75             :         }
      76             : 
      77         554 :         if (logon_info && logon_info->info3.base.logon_domain.string) {
      78         554 :                 domain = talloc_strdup(mem_ctx,
      79             :                                         logon_info->info3.base.logon_domain.string);
      80         554 :                 if (!domain) {
      81           0 :                         return NT_STATUS_NO_MEMORY;
      82             :                 }
      83         554 :                 DEBUG(10, ("Domain is [%s] (using PAC)\n", domain));
      84             :         } else {
      85             : 
      86             :                 /* If we have winbind running, we can (and must) shorten the
      87             :                    username by using the short netbios name. Otherwise we will
      88             :                    have inconsistent user names. With Kerberos, we get the
      89             :                    fully qualified realm, with ntlmssp we get the short
      90             :                    name. And even w2k3 does use ntlmssp if you for example
      91             :                    connect to an ip address. */
      92             : 
      93             :                 wbcErr wbc_status;
      94           0 :                 struct wbcDomainInfo *info = NULL;
      95             : 
      96           0 :                 DEBUG(10, ("Mapping [%s] to short name using winbindd\n",
      97             :                            realm));
      98             : 
      99           0 :                 wbc_status = wbcDomainInfo(realm, &info);
     100             : 
     101           0 :                 if (WBC_ERROR_IS_OK(wbc_status)) {
     102           0 :                         domain = talloc_strdup(mem_ctx,
     103           0 :                                                 info->short_name);
     104           0 :                         wbcFreeMemory(info);
     105             :                 } else {
     106           0 :                         DEBUG(3, ("Could not find short name: %s\n",
     107             :                                   wbcErrorString(wbc_status)));
     108           0 :                         domain = talloc_strdup(mem_ctx, realm);
     109             :                 }
     110           0 :                 if (!domain) {
     111           0 :                         return NT_STATUS_NO_MEMORY;
     112             :                 }
     113           0 :                 DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain));
     114             :         }
     115             : 
     116         810 :         fuser = talloc_asprintf(mem_ctx,
     117             :                                 "%s%c%s",
     118             :                                 domain,
     119         554 :                                 *lp_winbind_separator(),
     120             :                                 user);
     121         554 :         if (!fuser) {
     122           0 :                 return NT_STATUS_NO_MEMORY;
     123             :         }
     124             : 
     125         554 :         *is_mapped = map_username(mem_ctx, fuser, &fuser);
     126         554 :         if (!fuser) {
     127           0 :                 return NT_STATUS_NO_MEMORY;
     128             :         }
     129         554 :         *mapped_to_guest = false;
     130             : 
     131         554 :         pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
     132         554 :         if (pw) {
     133         554 :                 if (!unixuser) {
     134           0 :                         return NT_STATUS_NO_MEMORY;
     135             :                 }
     136             :                 /* if a real user check pam account restrictions */
     137             :                 /* only really performed if "obey pam restriction" is true */
     138             :                 /* do this before an eventual mapping to guest occurs */
     139         554 :                 status = smb_pam_accountcheck(pw->pw_name, cli_name);
     140         554 :                 if (!NT_STATUS_IS_OK(status)) {
     141           0 :                         DEBUG(1, ("PAM account restrictions prevent user "
     142             :                                   "[%s] login\n", unixuser));
     143           0 :                         return status;
     144             :                 }
     145             :         }
     146         554 :         if (!pw) {
     147             : 
     148             :                 /* this was originally the behavior of Samba 2.2, if a user
     149             :                    did not have a local uid but has been authenticated, then
     150             :                    map them to a guest account */
     151             : 
     152           0 :                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
     153           0 :                         *mapped_to_guest = true;
     154           0 :                         fuser = talloc_strdup(mem_ctx, lp_guest_account());
     155           0 :                         if (!fuser) {
     156           0 :                                 return NT_STATUS_NO_MEMORY;
     157             :                         }
     158           0 :                         pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
     159             :                 }
     160             : 
     161             :                 /* extra sanity check that the guest account is valid */
     162           0 :                 if (!pw) {
     163           0 :                         DBG_NOTICE("Username %s is invalid on this system\n",
     164             :                                   fuser);
     165           0 :                         return NT_STATUS_LOGON_FAILURE;
     166             :                 }
     167             :         }
     168             : 
     169         554 :         if (!unixuser) {
     170           0 :                 return NT_STATUS_NO_MEMORY;
     171             :         }
     172             : 
     173         554 :         *username = talloc_strdup(mem_ctx, unixuser);
     174         554 :         if (!*username) {
     175           0 :                 return NT_STATUS_NO_MEMORY;
     176             :         }
     177         554 :         *ntuser = user;
     178         554 :         *ntdomain = domain;
     179         554 :         *_pw = pw;
     180             : 
     181         554 :         return NT_STATUS_OK;
     182             : }
     183             : 
     184         554 : NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
     185             :                                 char *ntuser,
     186             :                                 char *ntdomain,
     187             :                                 char *username,
     188             :                                 struct passwd *pw,
     189             :                                 const struct netr_SamInfo3 *info3,
     190             :                                 bool mapped_to_guest, bool username_was_mapped,
     191             :                                 DATA_BLOB *session_key,
     192             :                                 struct auth_session_info **session_info)
     193             : {
     194             :         NTSTATUS status;
     195             :         struct auth_serversupplied_info *server_info;
     196             : 
     197         554 :         if (mapped_to_guest) {
     198           0 :                 status = make_server_info_guest(mem_ctx, &server_info);
     199           0 :                 if (!NT_STATUS_IS_OK(status)) {
     200           0 :                         DEBUG(1, ("make_server_info_guest failed: %s!\n",
     201             :                                   nt_errstr(status)));
     202           0 :                         return status;
     203             :                 }
     204             : 
     205         554 :         } else if (info3) {
     206             :                 /* pass the unmapped username here since map_username()
     207             :                    will be called again in make_server_info_info3() */
     208             : 
     209         554 :                 status = make_server_info_info3(mem_ctx,
     210             :                                                 ntuser, ntdomain,
     211             :                                                 &server_info,
     212             :                                                 info3);
     213         554 :                 if (!NT_STATUS_IS_OK(status)) {
     214           0 :                         DEBUG(1, ("make_server_info_info3 failed: %s!\n",
     215             :                                   nt_errstr(status)));
     216           0 :                         return status;
     217             :                 }
     218             : 
     219             :         } else {
     220             :                 /*
     221             :                  * We didn't get a PAC, we have to make up the user
     222             :                  * ourselves. Try to ask the pdb backend to provide
     223             :                  * SID consistency with ntlmssp session setup
     224             :                  */
     225             :                 struct samu *sampass;
     226             : 
     227           0 :                 sampass = samu_new(talloc_tos());
     228           0 :                 if (sampass == NULL) {
     229           0 :                         return NT_STATUS_NO_MEMORY;
     230             :                 }
     231             : 
     232           0 :                 if (pdb_getsampwnam(sampass, username)) {
     233           0 :                         DEBUG(10, ("found user %s in passdb, calling "
     234             :                                    "make_server_info_sam\n", username));
     235           0 :                         status = make_server_info_sam(mem_ctx,
     236             :                                                       sampass,
     237             :                                                       &server_info);
     238             :                 } else {
     239             :                         /*
     240             :                          * User not in passdb, make it up artificially
     241             :                          */
     242           0 :                         DEBUG(10, ("didn't find user %s in passdb, calling "
     243             :                                    "make_server_info_pw\n", username));
     244           0 :                         status = make_server_info_pw(mem_ctx,
     245             :                                                      username,
     246             :                                                      pw,
     247             :                                                      &server_info);
     248             :                 }
     249             : 
     250           0 :                 TALLOC_FREE(sampass);
     251             : 
     252           0 :                 if (!NT_STATUS_IS_OK(status)) {
     253           0 :                         DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n",
     254             :                                   nt_errstr(status)));
     255           0 :                         return status;
     256             :                 }
     257             : 
     258             :                 /* make_server_info_pw does not set the domain. Without this
     259             :                  * we end up with the local netbios name in substitutions for
     260             :                  * %D. */
     261             : 
     262           0 :                 if (server_info->info3 != NULL) {
     263           0 :                         server_info->info3->base.logon_domain.string =
     264           0 :                                 talloc_strdup(server_info->info3, ntdomain);
     265             :                 }
     266             :         }
     267             : 
     268         554 :         server_info->nss_token |= username_was_mapped;
     269             : 
     270         554 :         status = create_local_token(mem_ctx, server_info, session_key, ntuser, session_info);
     271         554 :         talloc_free(server_info);
     272         554 :         if (!NT_STATUS_IS_OK(status)) {
     273           0 :                 DEBUG(10,("failed to create local token: %s\n",
     274             :                           nt_errstr(status)));
     275           0 :                 return status;
     276             :         }
     277             : 
     278         554 :         return NT_STATUS_OK;
     279             : }
     280             : 
     281             : #else /* HAVE_KRB5 */
     282             : NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
     283             :                                      const char *cli_name,
     284             :                                      const char *princ_name,
     285             :                                      struct PAC_LOGON_INFO *logon_info,
     286             :                                      bool *is_mapped,
     287             :                                      bool *mapped_to_guest,
     288             :                                      char **ntuser,
     289             :                                      char **ntdomain,
     290             :                                      char **username,
     291             :                                      struct passwd **_pw)
     292             : {
     293             :         return NT_STATUS_NOT_IMPLEMENTED;
     294             : }
     295             : 
     296             : NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
     297             :                                 char *ntuser,
     298             :                                 char *ntdomain,
     299             :                                 char *username,
     300             :                                 struct passwd *pw,
     301             :                                 const struct netr_SamInfo3 *info3,
     302             :                                 bool mapped_to_guest, bool username_was_mapped,
     303             :                                 DATA_BLOB *session_key,
     304             :                                 struct auth_session_info **session_info)
     305             : {
     306             :         return NT_STATUS_NOT_IMPLEMENTED;
     307             : }
     308             : 
     309             : #endif /* HAVE_KRB5 */

Generated by: LCOV version 1.13