/src/samba/source3/auth/user_krb5.c
Line | Count | Source |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | Authentication utility functions |
4 | | Copyright (C) Simo Sorce 2010 |
5 | | |
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. |
10 | | |
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. |
15 | | |
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/>. |
18 | | */ |
19 | | |
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" |
26 | | |
27 | | #undef DBGC_CLASS |
28 | 0 | #define DBGC_CLASS DBGC_AUTH |
29 | | |
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 | | bool *is_mapped, |
35 | | bool *mapped_to_guest, |
36 | | char **ntuser, |
37 | | char **ntdomain, |
38 | | char **username, |
39 | | struct passwd **_pw) |
40 | 0 | { |
41 | 0 | NTSTATUS status; |
42 | 0 | const char *domain = NULL; |
43 | 0 | const char *realm = NULL; |
44 | 0 | char *user = NULL; |
45 | 0 | const char *p = NULL; |
46 | 0 | char *fuser = NULL; |
47 | 0 | char *unixuser = NULL; |
48 | 0 | struct passwd *pw = NULL; |
49 | 0 | bool may_retry = false; |
50 | |
|
51 | 0 | DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name)); |
52 | |
|
53 | 0 | p = strchr_m(princ_name, '@'); |
54 | 0 | if (!p) { |
55 | 0 | DEBUG(3, ("[%s] Doesn't look like a valid principal\n", |
56 | 0 | princ_name)); |
57 | 0 | return NT_STATUS_LOGON_FAILURE; |
58 | 0 | } |
59 | | |
60 | 0 | user = talloc_strndup(mem_ctx, princ_name, p - princ_name); |
61 | 0 | if (!user) { |
62 | 0 | return NT_STATUS_NO_MEMORY; |
63 | 0 | } |
64 | | |
65 | 0 | realm = p + 1; |
66 | |
|
67 | 0 | if (!strequal(realm, lp_realm())) { |
68 | 0 | DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm)); |
69 | 0 | if (!lp_allow_trusted_domains()) { |
70 | 0 | return NT_STATUS_LOGON_FAILURE; |
71 | 0 | } |
72 | 0 | domain = realm; |
73 | 0 | } else { |
74 | 0 | domain = lp_workgroup(); |
75 | 0 | may_retry = true; |
76 | 0 | } |
77 | | |
78 | 0 | fuser = talloc_asprintf(mem_ctx, |
79 | 0 | "%s%c%s", |
80 | 0 | domain, |
81 | 0 | *lp_winbind_separator(), |
82 | 0 | user); |
83 | 0 | if (!fuser) { |
84 | 0 | return NT_STATUS_NO_MEMORY; |
85 | 0 | } |
86 | | |
87 | 0 | *is_mapped = map_username(mem_ctx, fuser, &fuser); |
88 | 0 | if (!fuser) { |
89 | 0 | return NT_STATUS_NO_MEMORY; |
90 | 0 | } |
91 | 0 | *mapped_to_guest = false; |
92 | |
|
93 | 0 | pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true); |
94 | 0 | if (may_retry && pw == NULL && !*is_mapped) { |
95 | 0 | fuser = talloc_strdup(mem_ctx, user); |
96 | 0 | if (!fuser) { |
97 | 0 | return NT_STATUS_NO_MEMORY; |
98 | 0 | } |
99 | 0 | pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true); |
100 | 0 | } |
101 | 0 | if (pw) { |
102 | 0 | if (!unixuser) { |
103 | 0 | return NT_STATUS_NO_MEMORY; |
104 | 0 | } |
105 | | /* if a real user check pam account restrictions */ |
106 | | /* only really performed if "obey pam restriction" is true */ |
107 | | /* do this before an eventual mapping to guest occurs */ |
108 | 0 | status = smb_pam_accountcheck(pw->pw_name, cli_name); |
109 | 0 | if (!NT_STATUS_IS_OK(status)) { |
110 | 0 | DEBUG(1, ("PAM account restrictions prevent user " |
111 | 0 | "[%s] login\n", unixuser)); |
112 | 0 | return status; |
113 | 0 | } |
114 | 0 | } |
115 | 0 | if (!pw) { |
116 | | |
117 | | /* this was originally the behavior of Samba 2.2, if a user |
118 | | did not have a local uid but has been authenticated, then |
119 | | map them to a guest account */ |
120 | |
|
121 | 0 | if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) { |
122 | 0 | *mapped_to_guest = true; |
123 | 0 | fuser = talloc_strdup(mem_ctx, lp_guest_account()); |
124 | 0 | if (!fuser) { |
125 | 0 | return NT_STATUS_NO_MEMORY; |
126 | 0 | } |
127 | 0 | pw = smb_getpwnam(mem_ctx, fuser, &unixuser, false); |
128 | 0 | } |
129 | | |
130 | | /* extra sanity check that the guest account is valid */ |
131 | 0 | if (!pw) { |
132 | 0 | DBG_NOTICE("Username %s is invalid on this system\n", |
133 | 0 | fuser); |
134 | 0 | return NT_STATUS_LOGON_FAILURE; |
135 | 0 | } |
136 | 0 | } |
137 | | |
138 | 0 | if (!unixuser) { |
139 | 0 | return NT_STATUS_NO_MEMORY; |
140 | 0 | } |
141 | | |
142 | 0 | *username = talloc_strdup(mem_ctx, unixuser); |
143 | 0 | if (!*username) { |
144 | 0 | return NT_STATUS_NO_MEMORY; |
145 | 0 | } |
146 | 0 | *ntuser = user; |
147 | 0 | *ntdomain = talloc_strdup(mem_ctx, domain); |
148 | 0 | if (*ntdomain == NULL) { |
149 | 0 | return NT_STATUS_NO_MEMORY; |
150 | 0 | } |
151 | | |
152 | 0 | *_pw = pw; |
153 | |
|
154 | 0 | return NT_STATUS_OK; |
155 | 0 | } |
156 | | |
157 | | NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, |
158 | | char *ntuser, |
159 | | char *ntdomain, |
160 | | char *username, |
161 | | struct passwd *pw, |
162 | | bool mapped_to_guest, bool username_was_mapped, |
163 | | struct auth_session_info **session_info) |
164 | 0 | { |
165 | 0 | NTSTATUS status; |
166 | 0 | struct auth_serversupplied_info *server_info; |
167 | |
|
168 | 0 | if (mapped_to_guest) { |
169 | 0 | status = make_server_info_guest(mem_ctx, &server_info); |
170 | 0 | if (!NT_STATUS_IS_OK(status)) { |
171 | 0 | DEBUG(1, ("make_server_info_guest failed: %s!\n", |
172 | 0 | nt_errstr(status))); |
173 | 0 | return status; |
174 | 0 | } |
175 | |
|
176 | 0 | } else { |
177 | | /* |
178 | | * We didn't get a PAC, we have to make up the user |
179 | | * ourselves. Try to ask the pdb backend to provide |
180 | | * SID consistency with ntlmssp session setup |
181 | | */ |
182 | 0 | struct samu *sampass; |
183 | |
|
184 | 0 | sampass = samu_new(talloc_tos()); |
185 | 0 | if (sampass == NULL) { |
186 | 0 | return NT_STATUS_NO_MEMORY; |
187 | 0 | } |
188 | | |
189 | 0 | if (pdb_getsampwnam(sampass, username)) { |
190 | 0 | DEBUG(10, ("found user %s in passdb, calling " |
191 | 0 | "make_server_info_sam\n", username)); |
192 | 0 | status = make_server_info_sam(mem_ctx, |
193 | 0 | sampass, |
194 | 0 | &server_info); |
195 | 0 | } else { |
196 | | /* |
197 | | * User not in passdb, make it up artificially |
198 | | */ |
199 | 0 | DEBUG(10, ("didn't find user %s in passdb, calling " |
200 | 0 | "make_server_info_pw\n", username)); |
201 | 0 | status = make_server_info_pw(mem_ctx, |
202 | 0 | username, |
203 | 0 | pw, |
204 | 0 | &server_info); |
205 | 0 | } |
206 | |
|
207 | 0 | TALLOC_FREE(sampass); |
208 | |
|
209 | 0 | if (!NT_STATUS_IS_OK(status)) { |
210 | 0 | DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n", |
211 | 0 | nt_errstr(status))); |
212 | 0 | return status; |
213 | 0 | } |
214 | | |
215 | | /* make_server_info_pw does not set the domain. Without this |
216 | | * we end up with the local netbios name in substitutions for |
217 | | * %D. */ |
218 | | |
219 | 0 | if (server_info->info3 != NULL) { |
220 | 0 | server_info->info3->base.logon_domain.string = |
221 | 0 | talloc_strdup(server_info->info3, ntdomain); |
222 | 0 | } |
223 | 0 | } |
224 | | |
225 | 0 | server_info->nss_token |= username_was_mapped; |
226 | |
|
227 | 0 | status = create_local_token(mem_ctx, server_info, NULL, ntuser, session_info); |
228 | 0 | talloc_free(server_info); |
229 | 0 | if (!NT_STATUS_IS_OK(status)) { |
230 | 0 | DEBUG(10,("failed to create local token: %s\n", |
231 | 0 | nt_errstr(status))); |
232 | 0 | return status; |
233 | 0 | } |
234 | | |
235 | 0 | return NT_STATUS_OK; |
236 | 0 | } |
237 | | |
238 | | #else /* HAVE_KRB5 */ |
239 | | NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx, |
240 | | const char *cli_name, |
241 | | const char *princ_name, |
242 | | bool *is_mapped, |
243 | | bool *mapped_to_guest, |
244 | | char **ntuser, |
245 | | char **ntdomain, |
246 | | char **username, |
247 | | struct passwd **_pw) |
248 | | { |
249 | | return NT_STATUS_NOT_IMPLEMENTED; |
250 | | } |
251 | | |
252 | | NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, |
253 | | char *ntuser, |
254 | | char *ntdomain, |
255 | | char *username, |
256 | | struct passwd *pw, |
257 | | bool mapped_to_guest, bool username_was_mapped, |
258 | | struct auth_session_info **session_info) |
259 | | { |
260 | | return NT_STATUS_NOT_IMPLEMENTED; |
261 | | } |
262 | | |
263 | | #endif /* HAVE_KRB5 */ |