script: sign library releases with Samba Library Distribution Key
[Samba.git] / source3 / auth / user_krb5.c
blob50716fd56b20e5e17e3af3f6532672b311915513
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 "librpc/gen_ndr/krb5pac.h"
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_AUTH
26 #ifdef HAVE_KRB5
27 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
28 const char *cli_name,
29 const char *princ_name,
30 struct PAC_LOGON_INFO *logon_info,
31 bool *is_mapped,
32 bool *mapped_to_guest,
33 char **ntuser,
34 char **ntdomain,
35 char **username,
36 struct passwd **_pw)
38 NTSTATUS status;
39 char *domain = NULL;
40 char *realm = NULL;
41 char *user = NULL;
42 char *p;
43 char *fuser = NULL;
44 char *unixuser = NULL;
45 struct passwd *pw = NULL;
47 DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name));
49 p = strchr_m(princ_name, '@');
50 if (!p) {
51 DEBUG(3, ("[%s] Doesn't look like a valid principal\n",
52 princ_name));
53 return NT_STATUS_LOGON_FAILURE;
56 user = talloc_strndup(mem_ctx, princ_name, p - princ_name);
57 if (!user) {
58 return NT_STATUS_NO_MEMORY;
61 realm = talloc_strdup(talloc_tos(), p + 1);
62 if (!realm) {
63 return NT_STATUS_NO_MEMORY;
66 if (!strequal(realm, lp_realm())) {
67 DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm));
68 if (!lp_allow_trusted_domains()) {
69 return NT_STATUS_LOGON_FAILURE;
73 if (logon_info && logon_info->info3.base.domain.string) {
74 domain = talloc_strdup(mem_ctx,
75 logon_info->info3.base.domain.string);
76 if (!domain) {
77 return NT_STATUS_NO_MEMORY;
79 DEBUG(10, ("Domain is [%s] (using PAC)\n", domain));
80 } else {
82 /* If we have winbind running, we can (and must) shorten the
83 username by using the short netbios name. Otherwise we will
84 have inconsistent user names. With Kerberos, we get the
85 fully qualified realm, with ntlmssp we get the short
86 name. And even w2k3 does use ntlmssp if you for example
87 connect to an ip address. */
89 wbcErr wbc_status;
90 struct wbcDomainInfo *info = NULL;
92 DEBUG(10, ("Mapping [%s] to short name using winbindd\n",
93 realm));
95 wbc_status = wbcDomainInfo(realm, &info);
97 if (WBC_ERROR_IS_OK(wbc_status)) {
98 domain = talloc_strdup(mem_ctx,
99 info->short_name);
100 wbcFreeMemory(info);
101 } else {
102 DEBUG(3, ("Could not find short name: %s\n",
103 wbcErrorString(wbc_status)));
104 domain = talloc_strdup(mem_ctx, realm);
106 if (!domain) {
107 return NT_STATUS_NO_MEMORY;
109 DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain));
112 fuser = talloc_asprintf(mem_ctx,
113 "%s%c%s",
114 domain,
115 *lp_winbind_separator(),
116 user);
117 if (!fuser) {
118 return NT_STATUS_NO_MEMORY;
121 *is_mapped = map_username(mem_ctx, fuser, &fuser);
122 if (!fuser) {
123 return NT_STATUS_NO_MEMORY;
126 pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
127 if (pw) {
128 if (!unixuser) {
129 return NT_STATUS_NO_MEMORY;
131 /* if a real user check pam account restrictions */
132 /* only really perfomed if "obey pam restriction" is true */
133 /* do this before an eventual mapping to guest occurs */
134 status = smb_pam_accountcheck(pw->pw_name, cli_name);
135 if (!NT_STATUS_IS_OK(status)) {
136 DEBUG(1, ("PAM account restrictions prevent user "
137 "[%s] login\n", unixuser));
138 return status;
141 if (!pw) {
143 /* this was originally the behavior of Samba 2.2, if a user
144 did not have a local uid but has been authenticated, then
145 map them to a guest account */
147 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
148 *mapped_to_guest = true;
149 fuser = talloc_strdup(mem_ctx, lp_guestaccount());
150 if (!fuser) {
151 return NT_STATUS_NO_MEMORY;
153 pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
156 /* extra sanity check that the guest account is valid */
157 if (!pw) {
158 DEBUG(1, ("Username %s is invalid on this system\n",
159 fuser));
160 return NT_STATUS_LOGON_FAILURE;
164 if (!unixuser) {
165 return NT_STATUS_NO_MEMORY;
168 *username = talloc_strdup(mem_ctx, unixuser);
169 if (!*username) {
170 return NT_STATUS_NO_MEMORY;
172 *ntuser = user;
173 *ntdomain = domain;
174 *_pw = pw;
176 return NT_STATUS_OK;
179 NTSTATUS make_server_info_krb5(TALLOC_CTX *mem_ctx,
180 char *ntuser,
181 char *ntdomain,
182 char *username,
183 struct passwd *pw,
184 struct PAC_LOGON_INFO *logon_info,
185 bool mapped_to_guest,
186 struct auth_serversupplied_info **server_info)
188 NTSTATUS status;
190 if (mapped_to_guest) {
191 status = make_server_info_guest(mem_ctx, server_info);
192 if (!NT_STATUS_IS_OK(status)) {
193 DEBUG(1, ("make_server_info_guest failed: %s!\n",
194 nt_errstr(status)));
195 return status;
198 } else if (logon_info) {
199 /* pass the unmapped username here since map_username()
200 will be called again in make_server_info_info3() */
202 status = make_server_info_info3(mem_ctx,
203 ntuser, ntdomain,
204 server_info,
205 &logon_info->info3);
206 if (!NT_STATUS_IS_OK(status)) {
207 DEBUG(1, ("make_server_info_info3 failed: %s!\n",
208 nt_errstr(status)));
209 return status;
212 } else {
214 * We didn't get a PAC, we have to make up the user
215 * ourselves. Try to ask the pdb backend to provide
216 * SID consistency with ntlmssp session setup
218 struct samu *sampass;
219 /* The stupid make_server_info_XX functions here
220 don't take a talloc context. */
221 struct auth_serversupplied_info *tmp = NULL;
223 sampass = samu_new(talloc_tos());
224 if (sampass == NULL) {
225 return NT_STATUS_NO_MEMORY;
228 if (pdb_getsampwnam(sampass, username)) {
229 DEBUG(10, ("found user %s in passdb, calling "
230 "make_server_info_sam\n", username));
231 status = make_server_info_sam(&tmp, sampass);
232 } else {
234 * User not in passdb, make it up artificially
236 DEBUG(10, ("didn't find user %s in passdb, calling "
237 "make_server_info_pw\n", username));
238 status = make_server_info_pw(&tmp, username, pw);
240 TALLOC_FREE(sampass);
242 if (!NT_STATUS_IS_OK(status)) {
243 DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n",
244 nt_errstr(status)));
245 return status;
248 /* Steal tmp server info into the server_info pointer. */
249 *server_info = talloc_move(mem_ctx, &tmp);
251 /* make_server_info_pw does not set the domain. Without this
252 * we end up with the local netbios name in substitutions for
253 * %D. */
255 if ((*server_info)->info3 != NULL) {
256 (*server_info)->info3->base.domain.string =
257 talloc_strdup((*server_info)->info3, ntdomain);
262 return NT_STATUS_OK;
265 #else /* HAVE_KRB5 */
266 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
267 const char *cli_name,
268 const char *princ_name,
269 struct PAC_LOGON_INFO *logon_info,
270 bool *is_mapped,
271 bool *mapped_to_guest,
272 char **ntuser,
273 char **ntdomain,
274 char **username,
275 struct passwd **_pw)
277 return NT_STATUS_NOT_IMPLEMENTED;
280 NTSTATUS make_server_info_krb5(TALLOC_CTX *mem_ctx,
281 char *ntuser,
282 char *ntdomain,
283 char *username,
284 struct passwd *pw,
285 struct PAC_LOGON_INFO *logon_info,
286 bool mapped_to_guest,
287 struct auth_serversupplied_info **server_info)
289 return NT_STATUS_NOT_IMPLEMENTED;
292 #endif /* HAVE_KRB5 */