Coverage Report

Created: 2026-07-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/auth/user_krb5.c
Line
Count
Source
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
0
#define DBGC_CLASS DBGC_AUTH
29
30
#ifdef HAVE_KRB5
31
NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
32
             const char *cli_name,
33
             const char *princ_name,
34
             bool *is_mapped,
35
             bool *mapped_to_guest,
36
             char **ntuser,
37
             char **ntdomain,
38
             char **username,
39
             struct passwd **_pw)
40
0
{
41
0
  NTSTATUS status;
42
0
  const char *domain = NULL;
43
0
  const char *realm = NULL;
44
0
  char *user = NULL;
45
0
  const char *p = NULL;
46
0
  char *fuser = NULL;
47
0
  char *unixuser = NULL;
48
0
  struct passwd *pw = NULL;
49
0
  bool may_retry = false;
50
51
0
  DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name));
52
53
0
  p = strchr_m(princ_name, '@');
54
0
  if (!p) {
55
0
    DEBUG(3, ("[%s] Doesn't look like a valid principal\n",
56
0
        princ_name));
57
0
    return NT_STATUS_LOGON_FAILURE;
58
0
  }
59
60
0
  user = talloc_strndup(mem_ctx, princ_name, p - princ_name);
61
0
  if (!user) {
62
0
    return NT_STATUS_NO_MEMORY;
63
0
  }
64
65
0
  realm = p + 1;
66
67
0
  if (!strequal(realm, lp_realm())) {
68
0
    DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm));
69
0
    if (!lp_allow_trusted_domains()) {
70
0
      return NT_STATUS_LOGON_FAILURE;
71
0
    }
72
0
    domain = realm;
73
0
  } else {
74
0
    domain = lp_workgroup();
75
0
    may_retry = true;
76
0
  }
77
78
0
  fuser = talloc_asprintf(mem_ctx,
79
0
        "%s%c%s",
80
0
        domain,
81
0
        *lp_winbind_separator(),
82
0
        user);
83
0
  if (!fuser) {
84
0
    return NT_STATUS_NO_MEMORY;
85
0
  }
86
87
0
  *is_mapped = map_username(mem_ctx, fuser, &fuser);
88
0
  if (!fuser) {
89
0
    return NT_STATUS_NO_MEMORY;
90
0
  }
91
0
  *mapped_to_guest = false;
92
93
0
  pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
94
0
  if (may_retry && pw == NULL && !*is_mapped) {
95
0
    fuser = talloc_strdup(mem_ctx, user);
96
0
    if (!fuser) {
97
0
      return NT_STATUS_NO_MEMORY;
98
0
    }
99
0
    pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
100
0
  }
101
0
  if (pw) {
102
0
    if (!unixuser) {
103
0
      return NT_STATUS_NO_MEMORY;
104
0
    }
105
    /* if a real user check pam account restrictions */
106
    /* only really performed if "obey pam restriction" is true */
107
    /* do this before an eventual mapping to guest occurs */
108
0
    status = smb_pam_accountcheck(pw->pw_name, cli_name);
109
0
    if (!NT_STATUS_IS_OK(status)) {
110
0
      DEBUG(1, ("PAM account restrictions prevent user "
111
0
          "[%s] login\n", unixuser));
112
0
      return status;
113
0
    }
114
0
  }
115
0
  if (!pw) {
116
117
    /* this was originally the behavior of Samba 2.2, if a user
118
       did not have a local uid but has been authenticated, then
119
       map them to a guest account */
120
121
0
    if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
122
0
      *mapped_to_guest = true;
123
0
      fuser = talloc_strdup(mem_ctx, lp_guest_account());
124
0
      if (!fuser) {
125
0
        return NT_STATUS_NO_MEMORY;
126
0
      }
127
0
      pw = smb_getpwnam(mem_ctx, fuser, &unixuser, false);
128
0
    }
129
130
    /* extra sanity check that the guest account is valid */
131
0
    if (!pw) {
132
0
      DBG_NOTICE("Username %s is invalid on this system\n",
133
0
          fuser);
134
0
      return NT_STATUS_LOGON_FAILURE;
135
0
    }
136
0
  }
137
138
0
  if (!unixuser) {
139
0
    return NT_STATUS_NO_MEMORY;
140
0
  }
141
142
0
  *username = talloc_strdup(mem_ctx, unixuser);
143
0
  if (!*username) {
144
0
    return NT_STATUS_NO_MEMORY;
145
0
  }
146
0
  *ntuser = user;
147
0
  *ntdomain = talloc_strdup(mem_ctx, domain);
148
0
  if (*ntdomain == NULL) {
149
0
    return NT_STATUS_NO_MEMORY;
150
0
  }
151
152
0
  *_pw = pw;
153
154
0
  return NT_STATUS_OK;
155
0
}
156
157
NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
158
        char *ntuser,
159
        char *ntdomain,
160
        char *username,
161
        struct passwd *pw,
162
        bool mapped_to_guest, bool username_was_mapped,
163
        struct auth_session_info **session_info)
164
0
{
165
0
  NTSTATUS status;
166
0
  struct auth_serversupplied_info *server_info;
167
168
0
  if (mapped_to_guest) {
169
0
    status = make_server_info_guest(mem_ctx, &server_info);
170
0
    if (!NT_STATUS_IS_OK(status)) {
171
0
      DEBUG(1, ("make_server_info_guest failed: %s!\n",
172
0
          nt_errstr(status)));
173
0
      return status;
174
0
    }
175
176
0
  } else {
177
    /*
178
     * We didn't get a PAC, we have to make up the user
179
     * ourselves. Try to ask the pdb backend to provide
180
     * SID consistency with ntlmssp session setup
181
     */
182
0
    struct samu *sampass;
183
184
0
    sampass = samu_new(talloc_tos());
185
0
    if (sampass == NULL) {
186
0
      return NT_STATUS_NO_MEMORY;
187
0
    }
188
189
0
    if (pdb_getsampwnam(sampass, username)) {
190
0
      DEBUG(10, ("found user %s in passdb, calling "
191
0
           "make_server_info_sam\n", username));
192
0
      status = make_server_info_sam(mem_ctx,
193
0
                  sampass,
194
0
                  &server_info);
195
0
    } else {
196
      /*
197
       * User not in passdb, make it up artificially
198
       */
199
0
      DEBUG(10, ("didn't find user %s in passdb, calling "
200
0
           "make_server_info_pw\n", username));
201
0
      status = make_server_info_pw(mem_ctx,
202
0
                 username,
203
0
                 pw,
204
0
                 &server_info);
205
0
    }
206
207
0
    TALLOC_FREE(sampass);
208
209
0
    if (!NT_STATUS_IS_OK(status)) {
210
0
      DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n",
211
0
          nt_errstr(status)));
212
0
      return status;
213
0
                }
214
215
    /* make_server_info_pw does not set the domain. Without this
216
     * we end up with the local netbios name in substitutions for
217
     * %D. */
218
219
0
    if (server_info->info3 != NULL) {
220
0
      server_info->info3->base.logon_domain.string =
221
0
        talloc_strdup(server_info->info3, ntdomain);
222
0
    }
223
0
  }
224
225
0
  server_info->nss_token |= username_was_mapped;
226
227
0
  status = create_local_token(mem_ctx, server_info, NULL, ntuser, session_info);
228
0
  talloc_free(server_info);
229
0
  if (!NT_STATUS_IS_OK(status)) {
230
0
    DEBUG(10,("failed to create local token: %s\n",
231
0
        nt_errstr(status)));
232
0
    return status;
233
0
  }
234
235
0
  return NT_STATUS_OK;
236
0
}
237
238
#else /* HAVE_KRB5 */
239
NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
240
             const char *cli_name,
241
             const char *princ_name,
242
             bool *is_mapped,
243
             bool *mapped_to_guest,
244
             char **ntuser,
245
             char **ntdomain,
246
             char **username,
247
             struct passwd **_pw)
248
{
249
  return NT_STATUS_NOT_IMPLEMENTED;
250
}
251
252
NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
253
        char *ntuser,
254
        char *ntdomain,
255
        char *username,
256
        struct passwd *pw,
257
        bool mapped_to_guest, bool username_was_mapped,
258
        struct auth_session_info **session_info)
259
{
260
  return NT_STATUS_NOT_IMPLEMENTED;
261
}
262
263
#endif /* HAVE_KRB5 */