waf: Build with RELRO if supported by the compiler.
[Samba.git] / source3 / auth / user_krb5.c
blob974a8aa2f815e3a5e26e0d59d88643266897babf
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"
25 #include "lib/param/loadparm.h"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_AUTH
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 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)
42 NTSTATUS status;
43 char *domain = NULL;
44 char *realm = NULL;
45 char *user = NULL;
46 char *p;
47 char *fuser = NULL;
48 char *unixuser = NULL;
49 struct passwd *pw = NULL;
51 DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name));
53 p = strchr_m(princ_name, '@');
54 if (!p) {
55 DEBUG(3, ("[%s] Doesn't look like a valid principal\n",
56 princ_name));
57 return NT_STATUS_LOGON_FAILURE;
60 user = talloc_strndup(mem_ctx, princ_name, p - princ_name);
61 if (!user) {
62 return NT_STATUS_NO_MEMORY;
65 realm = talloc_strdup(talloc_tos(), p + 1);
66 if (!realm) {
67 return NT_STATUS_NO_MEMORY;
70 if (!strequal(realm, lp_realm())) {
71 DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm));
72 if (!lp_allow_trusted_domains()) {
73 return NT_STATUS_LOGON_FAILURE;
77 if (logon_info && logon_info->info3.base.logon_domain.string) {
78 domain = talloc_strdup(mem_ctx,
79 logon_info->info3.base.logon_domain.string);
80 if (!domain) {
81 return NT_STATUS_NO_MEMORY;
83 DEBUG(10, ("Domain is [%s] (using PAC)\n", domain));
84 } else {
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. */
93 wbcErr wbc_status;
94 struct wbcDomainInfo *info = NULL;
96 DEBUG(10, ("Mapping [%s] to short name using winbindd\n",
97 realm));
99 wbc_status = wbcDomainInfo(realm, &info);
101 if (WBC_ERROR_IS_OK(wbc_status)) {
102 domain = talloc_strdup(mem_ctx,
103 info->short_name);
104 wbcFreeMemory(info);
105 } else {
106 DEBUG(3, ("Could not find short name: %s\n",
107 wbcErrorString(wbc_status)));
108 domain = talloc_strdup(mem_ctx, realm);
110 if (!domain) {
111 return NT_STATUS_NO_MEMORY;
113 DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain));
116 fuser = talloc_asprintf(mem_ctx,
117 "%s%c%s",
118 domain,
119 *lp_winbind_separator(),
120 user);
121 if (!fuser) {
122 return NT_STATUS_NO_MEMORY;
125 *is_mapped = map_username(mem_ctx, fuser, &fuser);
126 if (!fuser) {
127 return NT_STATUS_NO_MEMORY;
129 *mapped_to_guest = false;
131 pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
132 if (pw) {
133 if (!unixuser) {
134 return NT_STATUS_NO_MEMORY;
136 /* if a real user check pam account restrictions */
137 /* only really perfomed if "obey pam restriction" is true */
138 /* do this before an eventual mapping to guest occurs */
139 status = smb_pam_accountcheck(pw->pw_name, cli_name);
140 if (!NT_STATUS_IS_OK(status)) {
141 DEBUG(1, ("PAM account restrictions prevent user "
142 "[%s] login\n", unixuser));
143 return status;
146 if (!pw) {
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 */
152 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
153 *mapped_to_guest = true;
154 fuser = talloc_strdup(mem_ctx, lp_guestaccount());
155 if (!fuser) {
156 return NT_STATUS_NO_MEMORY;
158 pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
161 /* extra sanity check that the guest account is valid */
162 if (!pw) {
163 DEBUG(1, ("Username %s is invalid on this system\n",
164 fuser));
165 return NT_STATUS_LOGON_FAILURE;
169 if (!unixuser) {
170 return NT_STATUS_NO_MEMORY;
173 *username = talloc_strdup(mem_ctx, unixuser);
174 if (!*username) {
175 return NT_STATUS_NO_MEMORY;
177 *ntuser = user;
178 *ntdomain = domain;
179 *_pw = pw;
181 return NT_STATUS_OK;
184 NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
185 char *ntuser,
186 char *ntdomain,
187 char *username,
188 struct passwd *pw,
189 struct PAC_LOGON_INFO *logon_info,
190 bool mapped_to_guest, bool username_was_mapped,
191 DATA_BLOB *session_key,
192 struct auth_session_info **session_info)
194 NTSTATUS status;
195 struct auth_serversupplied_info *server_info;
197 if (mapped_to_guest) {
198 status = make_server_info_guest(mem_ctx, &server_info);
199 if (!NT_STATUS_IS_OK(status)) {
200 DEBUG(1, ("make_server_info_guest failed: %s!\n",
201 nt_errstr(status)));
202 return status;
205 } else if (logon_info) {
206 /* pass the unmapped username here since map_username()
207 will be called again in make_server_info_info3() */
209 status = make_server_info_info3(mem_ctx,
210 ntuser, ntdomain,
211 &server_info,
212 &logon_info->info3);
213 if (!NT_STATUS_IS_OK(status)) {
214 DEBUG(1, ("make_server_info_info3 failed: %s!\n",
215 nt_errstr(status)));
216 return status;
219 } else {
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
225 struct samu *sampass;
226 /* The stupid make_server_info_XX functions here
227 don't take a talloc context. */
228 struct auth_serversupplied_info *tmp = NULL;
230 sampass = samu_new(talloc_tos());
231 if (sampass == NULL) {
232 return NT_STATUS_NO_MEMORY;
235 if (pdb_getsampwnam(sampass, username)) {
236 DEBUG(10, ("found user %s in passdb, calling "
237 "make_server_info_sam\n", username));
238 status = make_server_info_sam(&tmp, sampass);
239 } else {
241 * User not in passdb, make it up artificially
243 DEBUG(10, ("didn't find user %s in passdb, calling "
244 "make_server_info_pw\n", username));
245 status = make_server_info_pw(&tmp, username, pw);
248 TALLOC_FREE(sampass);
250 if (!NT_STATUS_IS_OK(status)) {
251 DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n",
252 nt_errstr(status)));
253 return status;
256 /* Steal tmp server info into the server_info pointer. */
257 server_info = talloc_move(mem_ctx, &tmp);
259 /* make_server_info_pw does not set the domain. Without this
260 * we end up with the local netbios name in substitutions for
261 * %D. */
263 if (server_info->info3 != NULL) {
264 server_info->info3->base.logon_domain.string =
265 talloc_strdup(server_info->info3, ntdomain);
269 server_info->nss_token |= username_was_mapped;
271 status = create_local_token(mem_ctx, server_info, session_key, ntuser, session_info);
272 talloc_free(server_info);
273 if (!NT_STATUS_IS_OK(status)) {
274 DEBUG(10,("failed to create local token: %s\n",
275 nt_errstr(status)));
276 return status;
279 return NT_STATUS_OK;
282 #else /* HAVE_KRB5 */
283 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
284 const char *cli_name,
285 const char *princ_name,
286 struct PAC_LOGON_INFO *logon_info,
287 bool *is_mapped,
288 bool *mapped_to_guest,
289 char **ntuser,
290 char **ntdomain,
291 char **username,
292 struct passwd **_pw)
294 return NT_STATUS_NOT_IMPLEMENTED;
297 NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
298 char *ntuser,
299 char *ntdomain,
300 char *username,
301 struct passwd *pw,
302 struct PAC_LOGON_INFO *logon_info,
303 bool mapped_to_guest, bool username_was_mapped,
304 DATA_BLOB *session_key,
305 struct auth_session_info **session_info)
307 return NT_STATUS_NOT_IMPLEMENTED;
310 #endif /* HAVE_KRB5 */