Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Generic Authentication Interface
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2006
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "auth/gensec/gensec.h"
25 : #include "auth/gensec/gensec_internal.h"
26 : #include "auth/credentials/credentials.h"
27 : #include "auth/common_auth.h"
28 : #include "../lib/util/asn1.h"
29 : #include "param/param.h"
30 : #include "libds/common/roles.h"
31 : #include "lib/util/util_net.h"
32 :
33 : #undef strcasecmp
34 :
35 : #undef DBGC_CLASS
36 : #define DBGC_CLASS DBGC_AUTH
37 :
38 33343 : NTSTATUS gensec_generate_session_info_pac(TALLOC_CTX *mem_ctx,
39 : struct gensec_security *gensec_security,
40 : struct smb_krb5_context *smb_krb5_context,
41 : DATA_BLOB *pac_blob,
42 : const char *principal_string,
43 : const struct tsocket_address *remote_address,
44 : struct auth_session_info **session_info)
45 : {
46 33343 : uint32_t session_info_flags = 0;
47 33343 : struct auth4_context *auth_context = NULL;
48 888 : NTSTATUS status;
49 :
50 33343 : if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
51 8060 : session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
52 : }
53 :
54 33343 : session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
55 :
56 33343 : if (!pac_blob) {
57 13 : enum server_role server_role =
58 13 : lpcfg_server_role(gensec_security->settings->lp_ctx);
59 :
60 : /*
61 : * For any domain setup (DC or member) we require having
62 : * a PAC, as the service ticket comes from an AD DC,
63 : * which will always provide a PAC, unless
64 : * UF_NO_AUTH_DATA_REQUIRED is configured for our
65 : * account, but that's just an invalid configuration,
66 : * the admin configured for us!
67 : *
68 : * As a legacy case, we still allow kerberos tickets from an MIT
69 : * realm, but only in standalone mode. In that mode we'll only
70 : * ever accept a kerberos authentication with a keytab file
71 : * being explicitly configured via the 'keytab method' option.
72 : */
73 13 : if (server_role != ROLE_STANDALONE) {
74 13 : DBG_WARNING("Unable to find PAC in ticket from %s, "
75 : "failing to allow access\n",
76 : principal_string);
77 13 : return NT_STATUS_NO_IMPERSONATION_TOKEN;
78 : }
79 0 : DBG_NOTICE("Unable to find PAC for %s, resorting to local "
80 : "user lookup\n", principal_string);
81 : }
82 :
83 33330 : auth_context = gensec_security->auth_context;
84 :
85 33330 : if ((auth_context == NULL) ||
86 33330 : (auth_context->generate_session_info_pac == NULL)) {
87 0 : DBG_ERR("Cannot generate a session_info without "
88 : "the auth_context\n");
89 0 : return NT_STATUS_INTERNAL_ERROR;
90 : }
91 :
92 33330 : status = auth_context->generate_session_info_pac(
93 : auth_context,
94 : mem_ctx,
95 : smb_krb5_context,
96 : pac_blob,
97 : principal_string,
98 : remote_address,
99 : session_info_flags,
100 : session_info);
101 33330 : return status;
102 : }
103 :
104 : /*
105 : magic check a GSS-API wrapper packet for an Kerberos OID
106 : */
107 106 : static bool gensec_gssapi_check_oid(const DATA_BLOB *blob, const char *oid)
108 : {
109 106 : bool ret = false;
110 106 : struct asn1_data *data = asn1_init(NULL, ASN1_MAX_TREE_DEPTH);
111 :
112 106 : if (!data) return false;
113 :
114 106 : if (!asn1_load(data, *blob)) goto err;
115 106 : if (!asn1_start_tag(data, ASN1_APPLICATION(0))) goto err;
116 68 : if (!asn1_check_OID(data, oid)) goto err;
117 :
118 68 : ret = !asn1_has_error(data);
119 :
120 106 : err:
121 :
122 106 : asn1_free(data);
123 106 : return ret;
124 : }
125 :
126 : /**
127 : * Check if the packet is one for the KRB5 mechanism
128 : *
129 : * NOTE: This is a helper that can be employed by multiple mechanisms, do
130 : * not make assumptions about the private_data
131 : *
132 : * @param gensec_security GENSEC state, unused
133 : * @param in The request, as a DATA_BLOB
134 : * @return Error, INVALID_PARAMETER if it's not a packet for us
135 : * or NT_STATUS_OK if the packet is ok.
136 : */
137 :
138 106 : NTSTATUS gensec_magic_check_krb5_oid(struct gensec_security *unused,
139 : const DATA_BLOB *blob)
140 : {
141 106 : if (gensec_gssapi_check_oid(blob, GENSEC_OID_KERBEROS5)) {
142 68 : return NT_STATUS_OK;
143 : } else {
144 38 : return NT_STATUS_INVALID_PARAMETER;
145 : }
146 : }
147 :
148 50380 : void gensec_child_want_feature(struct gensec_security *gensec_security,
149 : uint32_t feature)
150 : {
151 50380 : struct gensec_security *child_security = gensec_security->child_security;
152 :
153 50380 : gensec_security->want_features |= feature;
154 50380 : if (child_security == NULL) {
155 43982 : return;
156 : }
157 5513 : gensec_want_feature(child_security, feature);
158 : }
159 :
160 2654930 : bool gensec_child_have_feature(struct gensec_security *gensec_security,
161 : uint32_t feature)
162 : {
163 2654930 : struct gensec_security *child_security = gensec_security->child_security;
164 :
165 2654930 : if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
166 : /*
167 : * All mechs with sub (child) mechs need to provide DCERPC
168 : * header signing! This is required because the negotiation
169 : * of header signing is done before the authentication
170 : * is completed.
171 : */
172 16996 : return true;
173 : }
174 :
175 2637640 : if (child_security == NULL) {
176 0 : return false;
177 : }
178 :
179 2637640 : return gensec_have_feature(child_security, feature);
180 : }
181 :
182 298957 : NTSTATUS gensec_child_unseal_packet(struct gensec_security *gensec_security,
183 : uint8_t *data, size_t length,
184 : const uint8_t *whole_pdu, size_t pdu_length,
185 : const DATA_BLOB *sig)
186 : {
187 298957 : if (gensec_security->child_security == NULL) {
188 0 : return NT_STATUS_INVALID_PARAMETER;
189 : }
190 :
191 298957 : return gensec_unseal_packet(gensec_security->child_security,
192 : data, length,
193 : whole_pdu, pdu_length,
194 : sig);
195 : }
196 :
197 56633 : NTSTATUS gensec_child_check_packet(struct gensec_security *gensec_security,
198 : const uint8_t *data, size_t length,
199 : const uint8_t *whole_pdu, size_t pdu_length,
200 : const DATA_BLOB *sig)
201 : {
202 56633 : if (gensec_security->child_security == NULL) {
203 0 : return NT_STATUS_INVALID_PARAMETER;
204 : }
205 :
206 56633 : return gensec_check_packet(gensec_security->child_security,
207 : data, length,
208 : whole_pdu, pdu_length,
209 : sig);
210 : }
211 :
212 298998 : NTSTATUS gensec_child_seal_packet(struct gensec_security *gensec_security,
213 : TALLOC_CTX *mem_ctx,
214 : uint8_t *data, size_t length,
215 : const uint8_t *whole_pdu, size_t pdu_length,
216 : DATA_BLOB *sig)
217 : {
218 298998 : if (gensec_security->child_security == NULL) {
219 0 : return NT_STATUS_INVALID_PARAMETER;
220 : }
221 :
222 298998 : return gensec_seal_packet(gensec_security->child_security,
223 : mem_ctx,
224 : data, length,
225 : whole_pdu, pdu_length,
226 : sig);
227 : }
228 :
229 56709 : NTSTATUS gensec_child_sign_packet(struct gensec_security *gensec_security,
230 : TALLOC_CTX *mem_ctx,
231 : const uint8_t *data, size_t length,
232 : const uint8_t *whole_pdu, size_t pdu_length,
233 : DATA_BLOB *sig)
234 : {
235 56709 : if (gensec_security->child_security == NULL) {
236 0 : return NT_STATUS_INVALID_PARAMETER;
237 : }
238 :
239 56709 : return gensec_sign_packet(gensec_security->child_security,
240 : mem_ctx,
241 : data, length,
242 : whole_pdu, pdu_length,
243 : sig);
244 : }
245 :
246 1476026 : NTSTATUS gensec_child_wrap(struct gensec_security *gensec_security,
247 : TALLOC_CTX *mem_ctx,
248 : const DATA_BLOB *in,
249 : DATA_BLOB *out)
250 : {
251 1476026 : if (gensec_security->child_security == NULL) {
252 0 : return NT_STATUS_INVALID_PARAMETER;
253 : }
254 :
255 1476026 : return gensec_wrap(gensec_security->child_security,
256 : mem_ctx, in, out);
257 : }
258 :
259 1475741 : NTSTATUS gensec_child_unwrap(struct gensec_security *gensec_security,
260 : TALLOC_CTX *mem_ctx,
261 : const DATA_BLOB *in,
262 : DATA_BLOB *out)
263 : {
264 1475741 : if (gensec_security->child_security == NULL) {
265 0 : return NT_STATUS_INVALID_PARAMETER;
266 : }
267 :
268 1475741 : return gensec_unwrap(gensec_security->child_security,
269 : mem_ctx, in, out);
270 : }
271 :
272 104950 : size_t gensec_child_sig_size(struct gensec_security *gensec_security,
273 : size_t data_size)
274 : {
275 104950 : if (gensec_security->child_security == NULL) {
276 0 : return 0;
277 : }
278 :
279 104950 : return gensec_sig_size(gensec_security->child_security, data_size);
280 : }
281 :
282 52012 : size_t gensec_child_max_input_size(struct gensec_security *gensec_security)
283 : {
284 52012 : if (gensec_security->child_security == NULL) {
285 0 : return 0;
286 : }
287 :
288 52012 : return gensec_max_input_size(gensec_security->child_security);
289 : }
290 :
291 52012 : size_t gensec_child_max_wrapped_size(struct gensec_security *gensec_security)
292 : {
293 52012 : if (gensec_security->child_security == NULL) {
294 0 : return 0;
295 : }
296 :
297 52012 : return gensec_max_wrapped_size(gensec_security->child_security);
298 : }
299 :
300 38622 : NTSTATUS gensec_child_session_key(struct gensec_security *gensec_security,
301 : TALLOC_CTX *mem_ctx,
302 : DATA_BLOB *session_key)
303 : {
304 38622 : if (gensec_security->child_security == NULL) {
305 0 : return NT_STATUS_INVALID_PARAMETER;
306 : }
307 :
308 38622 : return gensec_session_key(gensec_security->child_security,
309 : mem_ctx,
310 : session_key);
311 : }
312 :
313 65117 : NTSTATUS gensec_child_session_info(struct gensec_security *gensec_security,
314 : TALLOC_CTX *mem_ctx,
315 : struct auth_session_info **session_info)
316 : {
317 65117 : if (gensec_security->child_security == NULL) {
318 0 : return NT_STATUS_INVALID_PARAMETER;
319 : }
320 :
321 65117 : return gensec_session_info(gensec_security->child_security,
322 : mem_ctx,
323 : session_info);
324 : }
325 :
326 50526 : NTTIME gensec_child_expire_time(struct gensec_security *gensec_security)
327 : {
328 50526 : if (gensec_security->child_security == NULL) {
329 0 : return GENSEC_EXPIRE_TIME_INFINITY;
330 : }
331 :
332 50526 : return gensec_expire_time(gensec_security->child_security);
333 : }
334 :
335 65043 : const char *gensec_child_final_auth_type(struct gensec_security *gensec_security)
336 : {
337 65043 : if (gensec_security->child_security == NULL) {
338 0 : return "NONE";
339 : }
340 :
341 65043 : return gensec_final_auth_type(gensec_security->child_security);
342 : }
343 :
344 27275 : char *gensec_get_unparsed_target_principal(struct gensec_security *gensec_security,
345 : TALLOC_CTX *mem_ctx)
346 : {
347 27275 : const char *target_principal = gensec_get_target_principal(gensec_security);
348 27275 : const char *service = gensec_get_target_service(gensec_security);
349 27275 : const char *hostname = gensec_get_target_hostname(gensec_security);
350 :
351 27275 : if (target_principal != NULL) {
352 0 : return talloc_strdup(mem_ctx, target_principal);
353 27275 : } else if (service != NULL && hostname != NULL) {
354 26966 : return talloc_asprintf(mem_ctx, "%s/%s", service, hostname);
355 309 : } else if (hostname != NULL) {
356 0 : return talloc_strdup(mem_ctx, target_principal);
357 : }
358 :
359 309 : return NULL;
360 : }
361 :
362 58678 : NTSTATUS gensec_kerberos_possible(struct gensec_security *gensec_security)
363 : {
364 58678 : struct cli_credentials *creds = gensec_get_credentials(gensec_security);
365 58678 : bool auth_requested = cli_credentials_authentication_requested(creds);
366 1048 : enum credentials_use_kerberos krb5_state =
367 58678 : cli_credentials_get_kerberos_state(creds);
368 58678 : char *user_principal = NULL;
369 58678 : const char *client_realm = cli_credentials_get_realm(creds);
370 58678 : const char *target_principal = gensec_get_target_principal(gensec_security);
371 58678 : const char *hostname = gensec_get_target_hostname(gensec_security);
372 :
373 58678 : if (!auth_requested) {
374 76 : return NT_STATUS_INVALID_PARAMETER;
375 : }
376 :
377 58602 : if (krb5_state == CRED_USE_KERBEROS_DISABLED) {
378 0 : return NT_STATUS_INVALID_PARAMETER;
379 : }
380 :
381 58602 : errno = 0;
382 58602 : user_principal = cli_credentials_get_principal(creds, gensec_security);
383 58602 : if (errno != 0) {
384 0 : TALLOC_FREE(user_principal);
385 0 : return NT_STATUS_NO_MEMORY;
386 : }
387 :
388 58602 : if (user_principal == NULL) {
389 159 : return NT_STATUS_INVALID_PARAMETER;
390 : }
391 58443 : TALLOC_FREE(user_principal);
392 :
393 58443 : if (target_principal != NULL) {
394 219 : return NT_STATUS_OK;
395 : }
396 :
397 58224 : if (client_realm == NULL) {
398 21753 : return NT_STATUS_INVALID_PARAMETER;
399 : }
400 :
401 36471 : if (hostname == NULL) {
402 291 : return NT_STATUS_INVALID_PARAMETER;
403 : }
404 :
405 36180 : if (strcasecmp(hostname, "localhost") == 0) {
406 0 : return NT_STATUS_INVALID_PARAMETER;
407 : }
408 :
409 : #define STAR_SMBSERVER "*SMBSERVER"
410 36180 : if (strcmp(hostname, STAR_SMBSERVER) == 0) {
411 0 : return NT_STATUS_INVALID_PARAMETER;
412 : }
413 :
414 36180 : if (is_ipaddress(hostname)) {
415 1781 : return NT_STATUS_INVALID_PARAMETER;
416 : }
417 :
418 34399 : return NT_STATUS_OK;
419 : }
|