lib/util: usec_time_diff takes arguments the other way round than TvalDiff did
[Samba.git] / source3 / auth / user_krb5.c
blob9d6b6a445bf47fa82f4921e26dc697f535c06bb5
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 fstring fuser;
44 fstring unixuser;
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 /* We have to use fstring for this - map_username requires it. */
113 fstr_sprintf(fuser, "%s%c%s", domain, *lp_winbind_separator(), user);
115 *is_mapped = map_username(fuser);
117 pw = smb_getpwnam(mem_ctx, fuser, unixuser, true);
118 if (pw) {
119 /* if a real user check pam account restrictions */
120 /* only really perfomed if "obey pam restriction" is true */
121 /* do this before an eventual mapping to guest occurs */
122 status = smb_pam_accountcheck(pw->pw_name, cli_name);
123 if (!NT_STATUS_IS_OK(status)) {
124 DEBUG(1, ("PAM account restrictions prevent user "
125 "[%s] login\n", unixuser));
126 return status;
129 if (!pw) {
131 /* this was originally the behavior of Samba 2.2, if a user
132 did not have a local uid but has been authenticated, then
133 map them to a guest account */
135 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
136 *mapped_to_guest = true;
137 fstrcpy(fuser, lp_guestaccount());
138 pw = smb_getpwnam(mem_ctx, fuser, unixuser, true);
141 /* extra sanity check that the guest account is valid */
142 if (!pw) {
143 DEBUG(1, ("Username %s is invalid on this system\n",
144 fuser));
145 return NT_STATUS_LOGON_FAILURE;
149 *username = talloc_strdup(mem_ctx, unixuser);
150 if (!*username) {
151 return NT_STATUS_NO_MEMORY;
153 *ntuser = user;
154 *ntdomain = domain;
155 *_pw = pw;
157 return NT_STATUS_OK;
160 NTSTATUS make_server_info_krb5(TALLOC_CTX *mem_ctx,
161 char *ntuser,
162 char *ntdomain,
163 char *username,
164 struct passwd *pw,
165 struct PAC_LOGON_INFO *logon_info,
166 bool mapped_to_guest,
167 struct auth_serversupplied_info **server_info)
169 NTSTATUS status;
171 if (mapped_to_guest) {
172 status = make_server_info_guest(mem_ctx, server_info);
173 if (!NT_STATUS_IS_OK(status)) {
174 DEBUG(1, ("make_server_info_guest failed: %s!\n",
175 nt_errstr(status)));
176 return status;
179 } else if (logon_info) {
180 /* pass the unmapped username here since map_username()
181 will be called again in make_server_info_info3() */
183 status = make_server_info_info3(mem_ctx,
184 ntuser, ntdomain,
185 server_info,
186 &logon_info->info3);
187 if (!NT_STATUS_IS_OK(status)) {
188 DEBUG(1, ("make_server_info_info3 failed: %s!\n",
189 nt_errstr(status)));
190 return status;
193 } else {
195 * We didn't get a PAC, we have to make up the user
196 * ourselves. Try to ask the pdb backend to provide
197 * SID consistency with ntlmssp session setup
199 struct samu *sampass;
200 /* The stupid make_server_info_XX functions here
201 don't take a talloc context. */
202 struct auth_serversupplied_info *tmp = NULL;
204 sampass = samu_new(talloc_tos());
205 if (sampass == NULL) {
206 return NT_STATUS_NO_MEMORY;
209 if (pdb_getsampwnam(sampass, username)) {
210 DEBUG(10, ("found user %s in passdb, calling "
211 "make_server_info_sam\n", username));
212 status = make_server_info_sam(&tmp, sampass);
213 } else {
215 * User not in passdb, make it up artificially
217 DEBUG(10, ("didn't find user %s in passdb, calling "
218 "make_server_info_pw\n", username));
219 status = make_server_info_pw(&tmp, username, pw);
221 TALLOC_FREE(sampass);
223 if (!NT_STATUS_IS_OK(status)) {
224 DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n",
225 nt_errstr(status)));
226 return status;
229 /* Steal tmp server info into the server_info pointer. */
230 *server_info = talloc_move(mem_ctx, &tmp);
232 /* make_server_info_pw does not set the domain. Without this
233 * we end up with the local netbios name in substitutions for
234 * %D. */
236 if ((*server_info)->info3 != NULL) {
237 (*server_info)->info3->base.domain.string =
238 talloc_strdup((*server_info)->info3, ntdomain);
243 return NT_STATUS_OK;
246 #else /* HAVE_KRB5 */
247 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
248 const char *cli_name,
249 const char *princ_name,
250 struct PAC_LOGON_INFO *logon_info,
251 bool *is_mapped,
252 bool *mapped_to_guest,
253 char **ntuser,
254 char **ntdomain,
255 char **username,
256 struct passwd **_pw)
258 return NT_STATUS_NOT_IMPLEMENTED;
261 NTSTATUS make_server_info_krb5(TALLOC_CTX *mem_ctx,
262 char *ntuser,
263 char *ntdomain,
264 char *username,
265 struct passwd *pw,
266 struct PAC_LOGON_INFO *logon_info,
267 bool mapped_to_guest,
268 struct auth_serversupplied_info **server_info)
270 return NT_STATUS_NOT_IMPLEMENTED;
273 #endif /* HAVE_KRB5 */