s4:libcli/smb2: allow smb2_session_setup_spnego to handle reauth
[Samba/wip.git] / source3 / auth / user_krb5.c
blob0939c70b5a1361b30d33cf0163426e0f4acbe72e
1 /*
2 Unix SMB/CIFS implementation.
3 Authentication utility functions
4 Copyright (C) Simo Sorce 2010
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.
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.
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/>.
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"
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_AUTH
29 #ifdef HAVE_KRB5
30 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
31 const char *cli_name,
32 const char *princ_name,
33 struct PAC_LOGON_INFO *logon_info,
34 bool *is_mapped,
35 bool *mapped_to_guest,
36 char **ntuser,
37 char **ntdomain,
38 char **username,
39 struct passwd **_pw)
41 NTSTATUS status;
42 char *domain = NULL;
43 char *realm = NULL;
44 char *user = NULL;
45 char *p;
46 char *fuser = NULL;
47 char *unixuser = NULL;
48 struct passwd *pw = NULL;
50 DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name));
52 p = strchr_m(princ_name, '@');
53 if (!p) {
54 DEBUG(3, ("[%s] Doesn't look like a valid principal\n",
55 princ_name));
56 return NT_STATUS_LOGON_FAILURE;
59 user = talloc_strndup(mem_ctx, princ_name, p - princ_name);
60 if (!user) {
61 return NT_STATUS_NO_MEMORY;
64 realm = talloc_strdup(talloc_tos(), p + 1);
65 if (!realm) {
66 return NT_STATUS_NO_MEMORY;
69 if (!strequal(realm, lp_realm())) {
70 DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm));
71 if (!lp_allow_trusted_domains()) {
72 return NT_STATUS_LOGON_FAILURE;
76 if (logon_info && logon_info->info3.base.logon_domain.string) {
77 domain = talloc_strdup(mem_ctx,
78 logon_info->info3.base.logon_domain.string);
79 if (!domain) {
80 return NT_STATUS_NO_MEMORY;
82 DEBUG(10, ("Domain is [%s] (using PAC)\n", domain));
83 } else {
85 /* If we have winbind running, we can (and must) shorten the
86 username by using the short netbios name. Otherwise we will
87 have inconsistent user names. With Kerberos, we get the
88 fully qualified realm, with ntlmssp we get the short
89 name. And even w2k3 does use ntlmssp if you for example
90 connect to an ip address. */
92 wbcErr wbc_status;
93 struct wbcDomainInfo *info = NULL;
95 DEBUG(10, ("Mapping [%s] to short name using winbindd\n",
96 realm));
98 wbc_status = wbcDomainInfo(realm, &info);
100 if (WBC_ERROR_IS_OK(wbc_status)) {
101 domain = talloc_strdup(mem_ctx,
102 info->short_name);
103 wbcFreeMemory(info);
104 } else {
105 DEBUG(3, ("Could not find short name: %s\n",
106 wbcErrorString(wbc_status)));
107 domain = talloc_strdup(mem_ctx, realm);
109 if (!domain) {
110 return NT_STATUS_NO_MEMORY;
112 DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain));
115 fuser = talloc_asprintf(mem_ctx,
116 "%s%c%s",
117 domain,
118 *lp_winbind_separator(),
119 user);
120 if (!fuser) {
121 return NT_STATUS_NO_MEMORY;
124 *is_mapped = map_username(mem_ctx, fuser, &fuser);
125 if (!fuser) {
126 return NT_STATUS_NO_MEMORY;
128 *mapped_to_guest = false;
130 pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
131 if (pw) {
132 if (!unixuser) {
133 return NT_STATUS_NO_MEMORY;
135 /* if a real user check pam account restrictions */
136 /* only really perfomed if "obey pam restriction" is true */
137 /* do this before an eventual mapping to guest occurs */
138 status = smb_pam_accountcheck(pw->pw_name, cli_name);
139 if (!NT_STATUS_IS_OK(status)) {
140 DEBUG(1, ("PAM account restrictions prevent user "
141 "[%s] login\n", unixuser));
142 return status;
145 if (!pw) {
147 /* this was originally the behavior of Samba 2.2, if a user
148 did not have a local uid but has been authenticated, then
149 map them to a guest account */
151 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
152 *mapped_to_guest = true;
153 fuser = talloc_strdup(mem_ctx, lp_guestaccount());
154 if (!fuser) {
155 return NT_STATUS_NO_MEMORY;
157 pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
160 /* extra sanity check that the guest account is valid */
161 if (!pw) {
162 DEBUG(1, ("Username %s is invalid on this system\n",
163 fuser));
164 return NT_STATUS_LOGON_FAILURE;
168 if (!unixuser) {
169 return NT_STATUS_NO_MEMORY;
172 *username = talloc_strdup(mem_ctx, unixuser);
173 if (!*username) {
174 return NT_STATUS_NO_MEMORY;
176 *ntuser = user;
177 *ntdomain = domain;
178 *_pw = pw;
180 return NT_STATUS_OK;
183 NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
184 char *ntuser,
185 char *ntdomain,
186 char *username,
187 struct passwd *pw,
188 struct PAC_LOGON_INFO *logon_info,
189 bool mapped_to_guest, bool username_was_mapped,
190 DATA_BLOB *session_key,
191 struct auth_session_info **session_info)
193 NTSTATUS status;
194 struct auth_serversupplied_info *server_info;
196 if (mapped_to_guest) {
197 status = make_server_info_guest(mem_ctx, &server_info);
198 if (!NT_STATUS_IS_OK(status)) {
199 DEBUG(1, ("make_server_info_guest failed: %s!\n",
200 nt_errstr(status)));
201 return status;
204 } else if (logon_info) {
205 /* pass the unmapped username here since map_username()
206 will be called again in make_server_info_info3() */
208 status = make_server_info_info3(mem_ctx,
209 ntuser, ntdomain,
210 &server_info,
211 &logon_info->info3);
212 if (!NT_STATUS_IS_OK(status)) {
213 DEBUG(1, ("make_server_info_info3 failed: %s!\n",
214 nt_errstr(status)));
215 return status;
218 } else {
220 * We didn't get a PAC, we have to make up the user
221 * ourselves. Try to ask the pdb backend to provide
222 * SID consistency with ntlmssp session setup
224 struct samu *sampass;
225 /* The stupid make_server_info_XX functions here
226 don't take a talloc context. */
227 struct auth_serversupplied_info *tmp = NULL;
229 sampass = samu_new(talloc_tos());
230 if (sampass == NULL) {
231 return NT_STATUS_NO_MEMORY;
234 if (pdb_getsampwnam(sampass, username)) {
235 DEBUG(10, ("found user %s in passdb, calling "
236 "make_server_info_sam\n", username));
237 status = make_server_info_sam(&tmp, sampass);
238 } else {
240 * User not in passdb, make it up artificially
242 DEBUG(10, ("didn't find user %s in passdb, calling "
243 "make_server_info_pw\n", username));
244 status = make_server_info_pw(&tmp, username, pw);
247 TALLOC_FREE(sampass);
249 if (!NT_STATUS_IS_OK(status)) {
250 DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n",
251 nt_errstr(status)));
252 return status;
255 /* Steal tmp server info into the server_info pointer. */
256 server_info = talloc_move(mem_ctx, &tmp);
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. */
262 if (server_info->info3 != NULL) {
263 server_info->info3->base.logon_domain.string =
264 talloc_strdup(server_info->info3, ntdomain);
268 server_info->nss_token |= username_was_mapped;
270 status = create_local_token(mem_ctx, server_info, session_key, ntuser, session_info);
271 talloc_free(server_info);
272 if (!NT_STATUS_IS_OK(status)) {
273 DEBUG(10,("failed to create local token: %s\n",
274 nt_errstr(status)));
275 return status;
278 return NT_STATUS_OK;
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)
293 return NT_STATUS_NOT_IMPLEMENTED;
296 NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
297 char *ntuser,
298 char *ntdomain,
299 char *username,
300 struct passwd *pw,
301 struct PAC_LOGON_INFO *logon_info,
302 bool mapped_to_guest, bool username_was_mapped,
303 DATA_BLOB *session_key,
304 struct auth_session_info **session_info)
306 return NT_STATUS_NOT_IMPLEMENTED;
309 #endif /* HAVE_KRB5 */