s3-auth: add helper to get server_info out of kerberos info
[Samba.git] / source3 / auth / user_krb5.c
blob580e71af86d8637e5d6dd59cbdb4db45e988e607
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"
22 #undef DBGC_CLASS
23 #define DBGC_CLASS DBGC_AUTH
25 #ifdef HAVE_KRB5
26 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
27 const char *cli_name,
28 const char *princ_name,
29 struct PAC_LOGON_INFO *logon_info,
30 bool *is_mapped,
31 bool *mapped_to_guest,
32 char **ntuser,
33 char **ntdomain,
34 char **username,
35 struct passwd **_pw)
37 NTSTATUS status;
38 char *domain = NULL;
39 char *realm = NULL;
40 char *user = NULL;
41 char *p;
42 fstring fuser;
43 fstring unixuser;
44 struct passwd *pw = NULL;
46 DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name));
48 p = strchr_m(princ_name, '@');
49 if (!p) {
50 DEBUG(3, ("[%s] Doesn't look like a valid principal\n",
51 princ_name));
52 return NT_STATUS_LOGON_FAILURE;
55 user = talloc_strndup(mem_ctx, princ_name, p - princ_name);
56 if (!user) {
57 return NT_STATUS_NO_MEMORY;
60 realm = talloc_strdup(talloc_tos(), p + 1);
61 if (!realm) {
62 return NT_STATUS_NO_MEMORY;
65 if (!strequal(realm, lp_realm())) {
66 DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm));
67 if (!lp_allow_trusted_domains()) {
68 return NT_STATUS_LOGON_FAILURE;
72 if (logon_info && logon_info->info3.base.domain.string) {
73 domain = talloc_strdup(mem_ctx,
74 logon_info->info3.base.domain.string);
75 if (!domain) {
76 return NT_STATUS_NO_MEMORY;
78 DEBUG(10, ("Domain is [%s] (using PAC)\n", domain));
79 } else {
81 /* If we have winbind running, we can (and must) shorten the
82 username by using the short netbios name. Otherwise we will
83 have inconsistent user names. With Kerberos, we get the
84 fully qualified realm, with ntlmssp we get the short
85 name. And even w2k3 does use ntlmssp if you for example
86 connect to an ip address. */
88 wbcErr wbc_status;
89 struct wbcDomainInfo *info = NULL;
91 DEBUG(10, ("Mapping [%s] to short name using winbindd\n",
92 realm));
94 wbc_status = wbcDomainInfo(realm, &info);
96 if (WBC_ERROR_IS_OK(wbc_status)) {
97 domain = talloc_strdup(mem_ctx,
98 info->short_name);
99 wbcFreeMemory(info);
100 } else {
101 DEBUG(3, ("Could not find short name: %s\n",
102 wbcErrorString(wbc_status)));
103 domain = talloc_strdup(mem_ctx, realm);
105 if (!domain) {
106 return NT_STATUS_NO_MEMORY;
108 DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain));
111 /* We have to use fstring for this - map_username requires it. */
112 fstr_sprintf(fuser, "%s%c%s", domain, *lp_winbind_separator(), user);
114 *is_mapped = map_username(fuser);
116 pw = smb_getpwnam(mem_ctx, fuser, unixuser, true);
117 if (pw) {
118 /* if a real user check pam account restrictions */
119 /* only really perfomed if "obey pam restriction" is true */
120 /* do this before an eventual mapping to guest occurs */
121 status = smb_pam_accountcheck(pw->pw_name, cli_name);
122 if (!NT_STATUS_IS_OK(status)) {
123 DEBUG(1, ("PAM account restrictions prevent user "
124 "[%s] login\n", unixuser));
125 return status;
128 if (!pw) {
130 /* this was originally the behavior of Samba 2.2, if a user
131 did not have a local uid but has been authenticated, then
132 map them to a guest account */
134 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
135 *mapped_to_guest = true;
136 fstrcpy(fuser, lp_guestaccount());
137 pw = smb_getpwnam(mem_ctx, fuser, unixuser, true);
140 /* extra sanity check that the guest account is valid */
141 if (!pw) {
142 DEBUG(1, ("Username %s is invalid on this system\n",
143 fuser));
144 return NT_STATUS_LOGON_FAILURE;
148 *username = talloc_strdup(mem_ctx, unixuser);
149 if (!*username) {
150 return NT_STATUS_NO_MEMORY;
152 *ntuser = user;
153 *ntdomain = domain;
154 *_pw = pw;
156 return NT_STATUS_OK;
159 NTSTATUS make_server_info_krb5(TALLOC_CTX *mem_ctx,
160 char *ntuser,
161 char *ntdomain,
162 char *username,
163 struct passwd *pw,
164 struct PAC_LOGON_INFO *logon_info,
165 bool mapped_to_guest,
166 struct auth_serversupplied_info **server_info)
168 NTSTATUS status;
170 if (mapped_to_guest) {
171 status = make_server_info_guest(mem_ctx, server_info);
172 if (!NT_STATUS_IS_OK(status)) {
173 DEBUG(1, ("make_server_info_guest failed: %s!\n",
174 nt_errstr(status)));
175 return status;
178 } else if (logon_info) {
179 /* pass the unmapped username here since map_username()
180 will be called again in make_server_info_info3() */
182 status = make_server_info_info3(mem_ctx,
183 ntuser, ntdomain,
184 server_info,
185 &logon_info->info3);
186 if (!NT_STATUS_IS_OK(status)) {
187 DEBUG(1, ("make_server_info_info3 failed: %s!\n",
188 nt_errstr(status)));
189 return status;
192 } else {
194 * We didn't get a PAC, we have to make up the user
195 * ourselves. Try to ask the pdb backend to provide
196 * SID consistency with ntlmssp session setup
198 struct samu *sampass;
199 /* The stupid make_server_info_XX functions here
200 don't take a talloc context. */
201 struct auth_serversupplied_info *tmp = NULL;
203 sampass = samu_new(talloc_tos());
204 if (sampass == NULL) {
205 return NT_STATUS_NO_MEMORY;
208 if (pdb_getsampwnam(sampass, username)) {
209 DEBUG(10, ("found user %s in passdb, calling "
210 "make_server_info_sam\n", username));
211 status = make_server_info_sam(&tmp, sampass);
212 } else {
214 * User not in passdb, make it up artificially
216 DEBUG(10, ("didn't find user %s in passdb, calling "
217 "make_server_info_pw\n", username));
218 status = make_server_info_pw(&tmp, username, pw);
220 TALLOC_FREE(sampass);
222 if (!NT_STATUS_IS_OK(status)) {
223 DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n",
224 nt_errstr(status)));
225 return status;
228 /* Steal tmp server info into the server_info pointer. */
229 *server_info = talloc_move(mem_ctx, &tmp);
231 /* make_server_info_pw does not set the domain. Without this
232 * we end up with the local netbios name in substitutions for
233 * %D. */
235 if ((*server_info)->info3 != NULL) {
236 (*server_info)->info3->base.domain.string =
237 talloc_strdup((*server_info)->info3, ntdomain);
242 return NT_STATUS_OK;
245 #else /* HAVE_KRB5 */
246 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
247 const char *cli_name,
248 const char *princ_name,
249 struct PAC_LOGON_INFO *logon_info,
250 bool *is_mapped,
251 bool *mapped_to_guest,
252 char **ntuser,
253 char **ntdomain,
254 char **username,
255 struct passwd **_pw)
257 return NT_STATUS_NOT_IMPLEMENTED;
260 NTSTATUS make_server_info_krb5(TALLOC_CTX *mem_ctx,
261 char *ntuser,
262 char *ntdomain,
263 char *username,
264 struct passwd *pw,
265 struct PAC_LOGON_INFO *logon_info,
266 bool mapped_to_guest,
267 struct auth_serversupplied_info **server_info)
269 return NT_STATUS_NOT_IMPLEMENTED;
272 #endif /* HAVE_KRB5 */