Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Kerberos backend for GENSEC
5 :
6 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
7 : Copyright (C) Andrew Tridgell 2001
8 : Copyright (C) Luke Howard 2002-2003
9 : Copyright (C) Stefan Metzmacher 2004-2005
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 :
22 : You should have received a copy of the GNU General Public License
23 : along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : */
25 :
26 : #include "includes.h"
27 : #include <tevent.h>
28 : #include "lib/util/tevent_ntstatus.h"
29 : #include "system/kerberos.h"
30 : #include "auth/kerberos/kerberos.h"
31 : #include "auth/auth.h"
32 : #include "lib/tsocket/tsocket.h"
33 : #include "librpc/gen_ndr/dcerpc.h"
34 : #include "auth/credentials/credentials.h"
35 : #include "auth/credentials/credentials_krb5.h"
36 : #include "auth/kerberos/kerberos_credentials.h"
37 : #include "auth/gensec/gensec.h"
38 : #include "auth/gensec/gensec_internal.h"
39 : #include "auth/gensec/gensec_proto.h"
40 : #include "auth/gensec/gensec_toplevel_proto.h"
41 : #include "param/param.h"
42 : #include "auth/auth_sam_reply.h"
43 : #include "lib/util/util_net.h"
44 : #include "../lib/util/asn1.h"
45 : #include "auth/kerberos/pac_utils.h"
46 : #include "gensec_krb5.h"
47 : #include "gensec_krb5_internal.h"
48 : #include "gensec_krb5_helpers.h"
49 :
50 : _PUBLIC_ NTSTATUS gensec_krb5_init(TALLOC_CTX *);
51 :
52 1472 : static int gensec_krb5_destroy(struct gensec_krb5_state *gensec_krb5_state)
53 : {
54 1472 : if (!gensec_krb5_state->smb_krb5_context) {
55 : /* We can't clean anything else up unless we started up this far */
56 0 : return 0;
57 : }
58 1472 : if (gensec_krb5_state->enc_ticket.length) {
59 198 : smb_krb5_free_data_contents(gensec_krb5_state->smb_krb5_context->krb5_context,
60 : &gensec_krb5_state->enc_ticket);
61 : }
62 :
63 1472 : if (gensec_krb5_state->ticket) {
64 1258 : krb5_free_ticket(gensec_krb5_state->smb_krb5_context->krb5_context,
65 : gensec_krb5_state->ticket);
66 : }
67 :
68 : /* ccache freed in a child destructor */
69 :
70 1472 : krb5_free_keyblock(gensec_krb5_state->smb_krb5_context->krb5_context,
71 : gensec_krb5_state->keyblock);
72 :
73 1472 : if (gensec_krb5_state->auth_context) {
74 1472 : krb5_auth_con_free(gensec_krb5_state->smb_krb5_context->krb5_context,
75 : gensec_krb5_state->auth_context);
76 : }
77 :
78 1472 : return 0;
79 : }
80 :
81 1472 : static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security, bool gssapi)
82 : {
83 0 : krb5_error_code ret;
84 0 : struct gensec_krb5_state *gensec_krb5_state;
85 0 : struct cli_credentials *creds;
86 0 : const struct tsocket_address *tlocal_addr, *tremote_addr;
87 0 : krb5_address my_krb5_addr, peer_krb5_addr;
88 :
89 1472 : creds = gensec_get_credentials(gensec_security);
90 1472 : if (!creds) {
91 0 : return NT_STATUS_INVALID_PARAMETER;
92 : }
93 :
94 1472 : gensec_krb5_state = talloc_zero(gensec_security, struct gensec_krb5_state);
95 1472 : if (!gensec_krb5_state) {
96 0 : return NT_STATUS_NO_MEMORY;
97 : }
98 :
99 1472 : gensec_security->private_data = gensec_krb5_state;
100 1472 : gensec_krb5_state->gssapi = gssapi;
101 :
102 1472 : talloc_set_destructor(gensec_krb5_state, gensec_krb5_destroy);
103 :
104 1472 : if (cli_credentials_get_krb5_context(creds,
105 1472 : gensec_security->settings->lp_ctx, &gensec_krb5_state->smb_krb5_context)) {
106 0 : talloc_free(gensec_krb5_state);
107 0 : return NT_STATUS_INTERNAL_ERROR;
108 : }
109 :
110 1472 : ret = krb5_auth_con_init(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context);
111 1472 : if (ret) {
112 0 : DEBUG(1,("gensec_krb5_start: krb5_auth_con_init failed (%s)\n",
113 : smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
114 : ret, gensec_krb5_state)));
115 0 : talloc_free(gensec_krb5_state);
116 0 : return NT_STATUS_INTERNAL_ERROR;
117 : }
118 :
119 1472 : ret = krb5_auth_con_setflags(gensec_krb5_state->smb_krb5_context->krb5_context,
120 : gensec_krb5_state->auth_context,
121 : KRB5_AUTH_CONTEXT_DO_SEQUENCE);
122 1472 : if (ret) {
123 0 : DEBUG(1,("gensec_krb5_start: krb5_auth_con_setflags failed (%s)\n",
124 : smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
125 : ret, gensec_krb5_state)));
126 0 : talloc_free(gensec_krb5_state);
127 0 : return NT_STATUS_INTERNAL_ERROR;
128 : }
129 :
130 1472 : tlocal_addr = gensec_get_local_address(gensec_security);
131 1472 : if (tlocal_addr) {
132 0 : ssize_t sockaddr_ret;
133 0 : struct samba_sockaddr addr;
134 0 : bool ok;
135 :
136 118 : addr.sa_socklen = sizeof(addr.u);
137 118 : sockaddr_ret = tsocket_address_bsd_sockaddr(
138 118 : tlocal_addr, &addr.u.sa, addr.sa_socklen);
139 118 : if (sockaddr_ret < 0) {
140 0 : talloc_free(gensec_krb5_state);
141 0 : return NT_STATUS_INTERNAL_ERROR;
142 : }
143 118 : addr.sa_socklen = sockaddr_ret;
144 118 : ok = smb_krb5_sockaddr_to_kaddr(&addr.u.ss, &my_krb5_addr);
145 118 : if (!ok) {
146 0 : DBG_WARNING("smb_krb5_sockaddr_to_kaddr (local) failed\n");
147 0 : talloc_free(gensec_krb5_state);
148 0 : return NT_STATUS_INTERNAL_ERROR;
149 : }
150 : }
151 :
152 1472 : tremote_addr = gensec_get_remote_address(gensec_security);
153 1472 : if (tremote_addr) {
154 0 : ssize_t sockaddr_ret;
155 0 : struct samba_sockaddr addr;
156 0 : bool ok;
157 :
158 50 : addr.sa_socklen = sizeof(addr.u);
159 50 : sockaddr_ret = tsocket_address_bsd_sockaddr(
160 50 : tremote_addr, &addr.u.sa, addr.sa_socklen);
161 50 : if (sockaddr_ret < 0) {
162 0 : talloc_free(gensec_krb5_state);
163 0 : return NT_STATUS_INTERNAL_ERROR;
164 : }
165 50 : addr.sa_socklen = sockaddr_ret;
166 50 : ok = smb_krb5_sockaddr_to_kaddr(&addr.u.ss, &peer_krb5_addr);
167 50 : if (!ok) {
168 0 : DBG_WARNING("smb_krb5_sockaddr_to_kaddr (remote) failed\n");
169 0 : talloc_free(gensec_krb5_state);
170 0 : return NT_STATUS_INTERNAL_ERROR;
171 : }
172 : }
173 :
174 1472 : ret = krb5_auth_con_setaddrs(gensec_krb5_state->smb_krb5_context->krb5_context,
175 : gensec_krb5_state->auth_context,
176 : tlocal_addr ? &my_krb5_addr : NULL,
177 : tremote_addr ? &peer_krb5_addr : NULL);
178 1472 : if (ret) {
179 0 : DEBUG(1,("gensec_krb5_start: krb5_auth_con_setaddrs failed (%s)\n",
180 : smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
181 : ret, gensec_krb5_state)));
182 0 : talloc_free(gensec_krb5_state);
183 0 : return NT_STATUS_INTERNAL_ERROR;
184 : }
185 :
186 1472 : return NT_STATUS_OK;
187 : }
188 :
189 1274 : static NTSTATUS gensec_krb5_common_server_start(struct gensec_security *gensec_security, bool gssapi)
190 : {
191 0 : NTSTATUS nt_status;
192 0 : struct gensec_krb5_state *gensec_krb5_state;
193 :
194 1274 : nt_status = gensec_krb5_start(gensec_security, gssapi);
195 1274 : if (!NT_STATUS_IS_OK(nt_status)) {
196 0 : return nt_status;
197 : }
198 :
199 1274 : gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
200 1274 : gensec_krb5_state->state_position = GENSEC_KRB5_SERVER_START;
201 :
202 1274 : return NT_STATUS_OK;
203 : }
204 :
205 1274 : static NTSTATUS gensec_krb5_server_start(struct gensec_security *gensec_security)
206 : {
207 1274 : return gensec_krb5_common_server_start(gensec_security, false);
208 : }
209 :
210 0 : static NTSTATUS gensec_fake_gssapi_krb5_server_start(struct gensec_security *gensec_security)
211 : {
212 0 : return gensec_krb5_common_server_start(gensec_security, true);
213 : }
214 :
215 198 : static NTSTATUS gensec_krb5_common_client_start(struct gensec_security *gensec_security, bool gssapi)
216 : {
217 0 : const char *hostname;
218 0 : struct gensec_krb5_state *gensec_krb5_state;
219 0 : NTSTATUS nt_status;
220 198 : hostname = gensec_get_target_hostname(gensec_security);
221 198 : if (!hostname) {
222 0 : DEBUG(3, ("No hostname for target computer passed in, cannot use kerberos for this connection\n"));
223 0 : return NT_STATUS_INVALID_PARAMETER;
224 : }
225 198 : if (is_ipaddress(hostname)) {
226 0 : DEBUG(2, ("Cannot do krb5 to an IP address\n"));
227 0 : return NT_STATUS_INVALID_PARAMETER;
228 : }
229 198 : if (strcmp(hostname, "localhost") == 0) {
230 0 : DEBUG(2, ("krb5 to 'localhost' does not make sense\n"));
231 0 : return NT_STATUS_INVALID_PARAMETER;
232 : }
233 :
234 198 : nt_status = gensec_krb5_start(gensec_security, gssapi);
235 198 : if (!NT_STATUS_IS_OK(nt_status)) {
236 0 : return nt_status;
237 : }
238 :
239 198 : gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
240 198 : gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_START;
241 198 : gensec_krb5_state->ap_req_options = AP_OPTS_USE_SUBKEY;
242 :
243 198 : if (gensec_krb5_state->gssapi) {
244 : /* The Fake GSSAPI model emulates Samba3, which does not do mutual authentication */
245 194 : if (gensec_setting_bool(gensec_security->settings, "gensec_fake_gssapi_krb5", "mutual", false)) {
246 0 : gensec_krb5_state->ap_req_options |= AP_OPTS_MUTUAL_REQUIRED;
247 : }
248 : } else {
249 : /* The wrapping for KPASSWD (a user of the raw KRB5 API) should be mutually authenticated */
250 4 : if (gensec_setting_bool(gensec_security->settings, "gensec_krb5", "mutual", true)) {
251 4 : gensec_krb5_state->ap_req_options |= AP_OPTS_MUTUAL_REQUIRED;
252 : }
253 : }
254 198 : return NT_STATUS_OK;
255 : }
256 :
257 198 : static NTSTATUS gensec_krb5_common_client_creds(struct gensec_security *gensec_security,
258 : struct tevent_context *ev)
259 : {
260 0 : struct gensec_krb5_state *gensec_krb5_state;
261 0 : krb5_error_code ret;
262 0 : struct ccache_container *ccache_container;
263 0 : const char *error_string;
264 0 : const char *principal;
265 0 : const char *hostname;
266 198 : krb5_data in_data = { .length = 0 };
267 198 : krb5_data *in_data_p = NULL;
268 : #ifdef SAMBA4_USES_HEIMDAL
269 0 : struct tevent_context *previous_ev;
270 : #endif
271 :
272 198 : if (lpcfg_parm_bool(gensec_security->settings->lp_ctx,
273 : NULL, "gensec_krb5", "send_authenticator_checksum", true)) {
274 134 : in_data_p = &in_data;
275 : }
276 :
277 198 : gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
278 :
279 198 : principal = gensec_get_target_principal(gensec_security);
280 198 : hostname = gensec_get_target_hostname(gensec_security);
281 :
282 198 : ret = cli_credentials_get_ccache(gensec_get_credentials(gensec_security),
283 : ev,
284 198 : gensec_security->settings->lp_ctx, &ccache_container, &error_string);
285 198 : switch (ret) {
286 198 : case 0:
287 198 : break;
288 0 : case KRB5KDC_ERR_PREAUTH_FAILED:
289 : case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
290 0 : return NT_STATUS_LOGON_FAILURE;
291 0 : case KRB5_KDC_UNREACH:
292 0 : DEBUG(3, ("Cannot reach a KDC we require to contact %s: %s\n", principal, error_string));
293 0 : return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
294 0 : case KRB5_CC_NOTFOUND:
295 : case KRB5_CC_END:
296 0 : DEBUG(3, ("Error preparing credentials we require to contact %s : %s\n", principal, error_string));
297 0 : return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
298 0 : default:
299 0 : DEBUG(1, ("gensec_krb5_start: Acquiring initiator credentials failed: %s\n", error_string));
300 0 : return NT_STATUS_UNSUCCESSFUL;
301 : }
302 :
303 : #ifdef SAMBA4_USES_HEIMDAL
304 : /* Do this every time, in case we have weird recursive issues here */
305 100 : ret = smb_krb5_context_set_event_ctx(gensec_krb5_state->smb_krb5_context, ev, &previous_ev);
306 100 : if (ret != 0) {
307 0 : DEBUG(1, ("gensec_krb5_start: Setting event context failed\n"));
308 0 : return NT_STATUS_NO_MEMORY;
309 : }
310 : #endif
311 198 : if (principal) {
312 0 : krb5_principal target_principal;
313 0 : ret = krb5_parse_name(gensec_krb5_state->smb_krb5_context->krb5_context, principal,
314 : &target_principal);
315 0 : if (ret == 0) {
316 0 : krb5_creds this_cred;
317 0 : krb5_creds *cred;
318 :
319 0 : ZERO_STRUCT(this_cred);
320 0 : ret = krb5_cc_get_principal(gensec_krb5_state->smb_krb5_context->krb5_context,
321 0 : ccache_container->ccache,
322 : &this_cred.client);
323 0 : if (ret != 0) {
324 0 : krb5_free_principal(gensec_krb5_state->smb_krb5_context->krb5_context,
325 : target_principal);
326 0 : return NT_STATUS_UNSUCCESSFUL;
327 : }
328 :
329 0 : ret = krb5_copy_principal(gensec_krb5_state->smb_krb5_context->krb5_context,
330 : target_principal,
331 : &this_cred.server);
332 0 : krb5_free_principal(gensec_krb5_state->smb_krb5_context->krb5_context,
333 : target_principal);
334 0 : if (ret != 0) {
335 0 : krb5_free_cred_contents(gensec_krb5_state->smb_krb5_context->krb5_context,
336 : &this_cred);
337 0 : return NT_STATUS_UNSUCCESSFUL;
338 : }
339 0 : this_cred.times.endtime = 0;
340 :
341 0 : ret = krb5_get_credentials(gensec_krb5_state->smb_krb5_context->krb5_context,
342 : 0,
343 0 : ccache_container->ccache,
344 : &this_cred,
345 : &cred);
346 0 : krb5_free_cred_contents(gensec_krb5_state->smb_krb5_context->krb5_context,
347 : &this_cred);
348 0 : if (ret != 0) {
349 0 : return NT_STATUS_UNSUCCESSFUL;
350 : }
351 :
352 0 : ret = krb5_mk_req_extended(gensec_krb5_state->smb_krb5_context->krb5_context,
353 : &gensec_krb5_state->auth_context,
354 : gensec_krb5_state->ap_req_options,
355 : in_data_p,
356 : cred,
357 : &gensec_krb5_state->enc_ticket);
358 : }
359 : } else {
360 198 : ret = krb5_mk_req(gensec_krb5_state->smb_krb5_context->krb5_context,
361 : &gensec_krb5_state->auth_context,
362 : gensec_krb5_state->ap_req_options,
363 : discard_const_p(char, gensec_get_target_service(gensec_security)),
364 : discard_const_p(char, hostname),
365 198 : in_data_p, ccache_container->ccache,
366 : &gensec_krb5_state->enc_ticket);
367 : }
368 :
369 : #ifdef SAMBA4_USES_HEIMDAL
370 100 : smb_krb5_context_remove_event_ctx(gensec_krb5_state->smb_krb5_context, previous_ev, ev);
371 : #endif
372 :
373 198 : switch (ret) {
374 198 : case 0:
375 198 : return NT_STATUS_OK;
376 0 : case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
377 0 : DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n",
378 : hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
379 0 : return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
380 0 : case KRB5_KDC_UNREACH:
381 0 : DEBUG(3, ("Cannot reach a KDC we require to contact host [%s]: %s\n",
382 : hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
383 0 : return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
384 0 : case KRB5KDC_ERR_PREAUTH_FAILED:
385 : case KRB5KRB_AP_ERR_TKT_EXPIRED:
386 : case KRB5_CC_END:
387 : /* Too much clock skew - we will need to kinit to re-skew the clock */
388 : case KRB5KRB_AP_ERR_SKEW:
389 : case KRB5_KDCREP_SKEW:
390 0 : DEBUG(3, ("kerberos (mk_req) failed: %s\n",
391 : smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
392 0 : FALL_THROUGH;
393 : /* just don't print a message for these really ordinary messages */
394 : case KRB5_FCC_NOFILE:
395 : case KRB5_CC_NOTFOUND:
396 : case ENOENT:
397 :
398 0 : return NT_STATUS_UNSUCCESSFUL;
399 0 : break;
400 :
401 0 : default:
402 0 : DEBUG(0, ("kerberos: %s\n",
403 : smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
404 0 : return NT_STATUS_UNSUCCESSFUL;
405 : }
406 : }
407 :
408 4 : static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security)
409 : {
410 4 : return gensec_krb5_common_client_start(gensec_security, false);
411 : }
412 :
413 194 : static NTSTATUS gensec_fake_gssapi_krb5_client_start(struct gensec_security *gensec_security)
414 : {
415 194 : return gensec_krb5_common_client_start(gensec_security, true);
416 : }
417 :
418 :
419 : /*
420 : generate a krb5 GSS-API wrapper packet given a ticket
421 : */
422 194 : static DATA_BLOB gensec_gssapi_gen_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *ticket, const uint8_t tok_id[2])
423 : {
424 0 : struct asn1_data *data;
425 194 : DATA_BLOB ret = data_blob_null;
426 :
427 194 : data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
428 194 : if (!data || !ticket->data) {
429 0 : return ret;
430 : }
431 :
432 194 : if (!asn1_push_tag(data, ASN1_APPLICATION(0))) goto err;
433 194 : if (!asn1_write_OID(data, GENSEC_OID_KERBEROS5)) goto err;
434 :
435 194 : if (!asn1_write(data, tok_id, 2)) goto err;
436 194 : if (!asn1_write(data, ticket->data, ticket->length)) goto err;
437 194 : if (!asn1_pop_tag(data)) goto err;
438 :
439 :
440 194 : if (!asn1_extract_blob(data, mem_ctx, &ret)) {
441 0 : goto err;
442 : }
443 194 : asn1_free(data);
444 :
445 194 : return ret;
446 :
447 0 : err:
448 :
449 0 : DEBUG(1, ("Failed to build krb5 wrapper at offset %d\n",
450 : (int)asn1_current_ofs(data)));
451 0 : asn1_free(data);
452 0 : return ret;
453 : }
454 :
455 : /*
456 : parse a krb5 GSS-API wrapper packet giving a ticket
457 : */
458 0 : static bool gensec_gssapi_parse_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, DATA_BLOB *ticket, uint8_t tok_id[2])
459 : {
460 0 : bool ret = false;
461 0 : struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
462 0 : int data_remaining;
463 :
464 0 : if (!data) {
465 0 : return false;
466 : }
467 :
468 0 : if (!asn1_load(data, *blob)) goto err;
469 0 : if (!asn1_start_tag(data, ASN1_APPLICATION(0))) goto err;
470 0 : if (!asn1_check_OID(data, GENSEC_OID_KERBEROS5)) goto err;
471 :
472 0 : data_remaining = asn1_tag_remaining(data);
473 :
474 0 : if (data_remaining < 3) {
475 0 : asn1_set_error(data);
476 : } else {
477 0 : if (!asn1_read(data, tok_id, 2)) goto err;
478 0 : data_remaining -= 2;
479 0 : *ticket = data_blob_talloc(mem_ctx, NULL, data_remaining);
480 0 : if (!asn1_read(data, ticket->data, ticket->length)) goto err;
481 : }
482 :
483 0 : if (!asn1_end_tag(data)) goto err;
484 :
485 0 : ret = !asn1_has_error(data);
486 :
487 0 : err:
488 :
489 0 : asn1_free(data);
490 :
491 0 : return ret;
492 : }
493 :
494 1472 : static NTSTATUS gensec_krb5_update_internal(struct gensec_security *gensec_security,
495 : TALLOC_CTX *out_mem_ctx,
496 : struct tevent_context *ev,
497 : const DATA_BLOB in, DATA_BLOB *out)
498 : {
499 1472 : struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
500 1472 : krb5_error_code ret = 0;
501 0 : NTSTATUS nt_status;
502 :
503 1472 : switch (gensec_krb5_state->state_position) {
504 198 : case GENSEC_KRB5_CLIENT_START:
505 : {
506 0 : DATA_BLOB unwrapped_out;
507 :
508 198 : nt_status = gensec_krb5_common_client_creds(gensec_security, ev);
509 198 : if (!NT_STATUS_IS_OK(nt_status)) {
510 0 : return nt_status;
511 : }
512 :
513 198 : if (gensec_krb5_state->gssapi) {
514 194 : unwrapped_out = data_blob_talloc(out_mem_ctx, gensec_krb5_state->enc_ticket.data, gensec_krb5_state->enc_ticket.length);
515 :
516 : /* wrap that up in a nice GSS-API wrapping */
517 194 : *out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REQ);
518 : } else {
519 4 : *out = data_blob_talloc(out_mem_ctx, gensec_krb5_state->enc_ticket.data, gensec_krb5_state->enc_ticket.length);
520 : }
521 198 : if (gensec_krb5_state->ap_req_options & AP_OPTS_MUTUAL_REQUIRED) {
522 4 : gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_MUTUAL_AUTH;
523 4 : nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
524 : } else {
525 194 : gensec_krb5_state->state_position = GENSEC_KRB5_DONE;
526 194 : nt_status = NT_STATUS_OK;
527 : }
528 198 : return nt_status;
529 : }
530 :
531 0 : case GENSEC_KRB5_CLIENT_MUTUAL_AUTH:
532 : {
533 0 : DATA_BLOB unwrapped_in;
534 0 : krb5_data inbuf;
535 0 : krb5_ap_rep_enc_part *repl = NULL;
536 0 : uint8_t tok_id[2];
537 :
538 0 : if (gensec_krb5_state->gssapi) {
539 0 : if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {
540 0 : DEBUG(1,("gensec_gssapi_parse_krb5_wrap(mutual authentication) failed to parse\n"));
541 0 : dump_data_pw("Mutual authentication message:\n", in.data, in.length);
542 0 : return NT_STATUS_INVALID_PARAMETER;
543 : }
544 : } else {
545 0 : unwrapped_in = in;
546 : }
547 : /* TODO: check the tok_id */
548 :
549 0 : inbuf.data = (char *)unwrapped_in.data;
550 0 : inbuf.length = unwrapped_in.length;
551 0 : ret = krb5_rd_rep(gensec_krb5_state->smb_krb5_context->krb5_context,
552 : gensec_krb5_state->auth_context,
553 : &inbuf, &repl);
554 0 : if (ret) {
555 0 : DEBUG(1,("krb5_rd_rep (mutual authentication) failed (%s)\n",
556 : smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, out_mem_ctx)));
557 0 : dump_data_pw("Mutual authentication message:\n", (uint8_t *)inbuf.data, inbuf.length);
558 0 : nt_status = NT_STATUS_ACCESS_DENIED;
559 : } else {
560 0 : *out = data_blob(NULL, 0);
561 0 : nt_status = NT_STATUS_OK;
562 0 : gensec_krb5_state->state_position = GENSEC_KRB5_DONE;
563 : }
564 0 : if (repl) {
565 0 : krb5_free_ap_rep_enc_part(gensec_krb5_state->smb_krb5_context->krb5_context, repl);
566 : }
567 0 : return nt_status;
568 : }
569 :
570 1274 : case GENSEC_KRB5_SERVER_START:
571 : {
572 0 : DATA_BLOB unwrapped_in;
573 1274 : DATA_BLOB unwrapped_out = data_blob(NULL, 0);
574 0 : krb5_data inbuf, outbuf;
575 0 : uint8_t tok_id[2];
576 0 : struct keytab_container *keytab;
577 0 : krb5_principal server_in_keytab;
578 0 : const char *error_string;
579 0 : enum credentials_obtained obtained;
580 :
581 1274 : if (!in.data) {
582 0 : return NT_STATUS_INVALID_PARAMETER;
583 : }
584 :
585 : /* Grab the keytab, however generated */
586 1274 : ret = cli_credentials_get_keytab(gensec_get_credentials(gensec_security),
587 1274 : gensec_security->settings->lp_ctx, &keytab);
588 1274 : if (ret) {
589 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
590 : }
591 :
592 : /* This ensures we lookup the correct entry in that
593 : * keytab. A NULL principal is acceptable, and means
594 : * that the krb5 libs should search the keytab at
595 : * accept time for any matching key */
596 1274 : ret = principal_from_credentials(out_mem_ctx, gensec_get_credentials(gensec_security),
597 : gensec_krb5_state->smb_krb5_context,
598 : &server_in_keytab, &obtained, &error_string);
599 :
600 1274 : if (ret) {
601 0 : DEBUG(2,("Failed to make credentials from principal: %s\n", error_string));
602 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
603 : }
604 :
605 1274 : if (keytab->password_based || obtained < CRED_SPECIFIED) {
606 : /*
607 : * Use match-by-key in this case (matches
608 : * cli_credentials_get_server_gss_creds()
609 : * behaviour). No need to free the memory,
610 : * this is handled with a talloc destructor.
611 : */
612 386 : server_in_keytab = NULL;
613 : }
614 :
615 : /* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omitted) */
616 1274 : if (gensec_krb5_state->gssapi
617 0 : && gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {
618 0 : inbuf.data = (char *)unwrapped_in.data;
619 0 : inbuf.length = unwrapped_in.length;
620 : } else {
621 1274 : inbuf.data = (char *)in.data;
622 1274 : inbuf.length = in.length;
623 : }
624 :
625 1274 : ret = smb_krb5_rd_req_decoded(gensec_krb5_state->smb_krb5_context->krb5_context,
626 : &gensec_krb5_state->auth_context,
627 : &inbuf,
628 1274 : keytab->keytab,
629 : server_in_keytab,
630 : &outbuf,
631 : &gensec_krb5_state->ticket,
632 : &gensec_krb5_state->keyblock);
633 :
634 1274 : if (ret) {
635 16 : DBG_WARNING("smb_krb5_rd_req_decoded failed\n");
636 16 : return NT_STATUS_LOGON_FAILURE;
637 : }
638 1258 : unwrapped_out.data = (uint8_t *)outbuf.data;
639 1258 : unwrapped_out.length = outbuf.length;
640 1258 : gensec_krb5_state->state_position = GENSEC_KRB5_DONE;
641 : /* wrap that up in a nice GSS-API wrapping */
642 1258 : if (gensec_krb5_state->gssapi) {
643 0 : *out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REP);
644 : } else {
645 1258 : *out = data_blob_talloc(out_mem_ctx, outbuf.data, outbuf.length);
646 : }
647 1258 : smb_krb5_free_data_contents(gensec_krb5_state->smb_krb5_context->krb5_context,
648 : &outbuf);
649 1258 : return NT_STATUS_OK;
650 : }
651 :
652 0 : case GENSEC_KRB5_DONE:
653 : default:
654 : /* Asking too many times... */
655 0 : return NT_STATUS_INVALID_PARAMETER;
656 : }
657 : }
658 :
659 : struct gensec_krb5_update_state {
660 : NTSTATUS status;
661 : DATA_BLOB out;
662 : };
663 :
664 1472 : static struct tevent_req *gensec_krb5_update_send(TALLOC_CTX *mem_ctx,
665 : struct tevent_context *ev,
666 : struct gensec_security *gensec_security,
667 : const DATA_BLOB in)
668 : {
669 1472 : struct tevent_req *req = NULL;
670 1472 : struct gensec_krb5_update_state *state = NULL;
671 0 : NTSTATUS status;
672 :
673 1472 : req = tevent_req_create(mem_ctx, &state,
674 : struct gensec_krb5_update_state);
675 1472 : if (req == NULL) {
676 0 : return NULL;
677 : }
678 :
679 1472 : status = gensec_krb5_update_internal(gensec_security,
680 : state, ev, in,
681 1472 : &state->out);
682 1472 : state->status = status;
683 1472 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
684 4 : tevent_req_done(req);
685 4 : return tevent_req_post(req, ev);
686 : }
687 1468 : if (tevent_req_nterror(req, status)) {
688 16 : return tevent_req_post(req, ev);
689 : }
690 :
691 1452 : tevent_req_done(req);
692 1452 : return tevent_req_post(req, ev);
693 : }
694 :
695 1472 : static NTSTATUS gensec_krb5_update_recv(struct tevent_req *req,
696 : TALLOC_CTX *out_mem_ctx,
697 : DATA_BLOB *out)
698 : {
699 0 : struct gensec_krb5_update_state *state =
700 1472 : tevent_req_data(req,
701 : struct gensec_krb5_update_state);
702 0 : NTSTATUS status;
703 :
704 1472 : *out = data_blob_null;
705 :
706 1472 : if (tevent_req_is_nterror(req, &status)) {
707 16 : tevent_req_received(req);
708 16 : return status;
709 : }
710 :
711 1456 : *out = state->out;
712 1456 : talloc_steal(out_mem_ctx, state->out.data);
713 1456 : status = state->status;
714 1456 : tevent_req_received(req);
715 1456 : return status;
716 : }
717 :
718 1448 : static NTSTATUS gensec_krb5_session_key(struct gensec_security *gensec_security,
719 : TALLOC_CTX *mem_ctx,
720 : DATA_BLOB *session_key)
721 : {
722 1448 : struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
723 1448 : krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;
724 1448 : krb5_auth_context auth_context = gensec_krb5_state->auth_context;
725 1448 : krb5_error_code err = -1;
726 1448 : bool remote = false;
727 0 : bool ok;
728 :
729 1448 : if (gensec_krb5_state->state_position != GENSEC_KRB5_DONE) {
730 0 : return NT_STATUS_NO_USER_SESSION_KEY;
731 : }
732 :
733 1448 : switch (gensec_security->gensec_role) {
734 194 : case GENSEC_CLIENT:
735 194 : remote = false;
736 194 : break;
737 1254 : case GENSEC_SERVER:
738 1254 : remote = true;
739 1254 : break;
740 : }
741 :
742 1448 : ok = smb_krb5_get_smb_session_key(mem_ctx,
743 : context,
744 : auth_context,
745 : session_key,
746 : remote);
747 1448 : if (!ok) {
748 0 : DEBUG(10, ("KRB5 error getting session key %d\n", err));
749 0 : return NT_STATUS_NO_USER_SESSION_KEY;
750 : }
751 :
752 1448 : return NT_STATUS_OK;
753 : }
754 :
755 : #ifdef SAMBA4_USES_HEIMDAL
756 1212 : static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security,
757 : TALLOC_CTX *mem_ctx,
758 : struct auth_session_info **_session_info)
759 : {
760 1212 : NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
761 1212 : struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
762 1212 : krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;
763 1212 : struct auth_session_info *session_info = NULL;
764 :
765 0 : krb5_principal client_principal;
766 1212 : char *principal_string = NULL;
767 :
768 1212 : DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
769 0 : krb5_data pac_data;
770 :
771 0 : krb5_error_code ret;
772 :
773 1212 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
774 1212 : if (!tmp_ctx) {
775 0 : return NT_STATUS_NO_MEMORY;
776 : }
777 :
778 1212 : ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal);
779 1212 : if (ret) {
780 0 : DEBUG(5, ("krb5_ticket_get_client failed to get client principal: %s\n",
781 : smb_get_krb5_error_message(context,
782 : ret, tmp_ctx)));
783 0 : talloc_free(tmp_ctx);
784 0 : return NT_STATUS_NO_MEMORY;
785 : }
786 :
787 1212 : ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context,
788 : client_principal, &principal_string);
789 1212 : if (ret) {
790 0 : DEBUG(1, ("Unable to parse client principal: %s\n",
791 : smb_get_krb5_error_message(context,
792 : ret, tmp_ctx)));
793 0 : krb5_free_principal(context, client_principal);
794 0 : talloc_free(tmp_ctx);
795 0 : return NT_STATUS_NO_MEMORY;
796 : }
797 :
798 1212 : ret = krb5_ticket_get_authorization_data_type(context, gensec_krb5_state->ticket,
799 : KRB5_AUTHDATA_WIN2K_PAC,
800 : &pac_data);
801 :
802 1212 : if (ret) {
803 : /* NO pac */
804 0 : DEBUG(5, ("krb5_ticket_get_authorization_data_type failed to find PAC: %s\n",
805 : smb_get_krb5_error_message(context,
806 : ret, tmp_ctx)));
807 : } else {
808 : /* Found pac */
809 1212 : pac_blob = data_blob_talloc(tmp_ctx, pac_data.data, pac_data.length);
810 1212 : smb_krb5_free_data_contents(context, &pac_data);
811 1212 : if (!pac_blob.data) {
812 0 : free(principal_string);
813 0 : krb5_free_principal(context, client_principal);
814 0 : talloc_free(tmp_ctx);
815 0 : return NT_STATUS_NO_MEMORY;
816 : }
817 :
818 : /* decode and verify the pac */
819 1212 : nt_status = kerberos_decode_pac(gensec_krb5_state,
820 : pac_blob,
821 1212 : gensec_krb5_state->smb_krb5_context->krb5_context,
822 1212 : NULL, gensec_krb5_state->keyblock,
823 : client_principal,
824 1212 : gensec_krb5_state->ticket->ticket.authtime, NULL);
825 :
826 1212 : if (!NT_STATUS_IS_OK(nt_status)) {
827 0 : free(principal_string);
828 0 : krb5_free_principal(context, client_principal);
829 0 : talloc_free(tmp_ctx);
830 0 : return nt_status;
831 : }
832 :
833 1212 : pac_blob_ptr = &pac_blob;
834 : }
835 :
836 1212 : nt_status = gensec_generate_session_info_pac(tmp_ctx,
837 : gensec_security,
838 : gensec_krb5_state->smb_krb5_context,
839 : pac_blob_ptr, principal_string,
840 : gensec_get_remote_address(gensec_security),
841 : &session_info);
842 :
843 1212 : free(principal_string);
844 1212 : krb5_free_principal(context, client_principal);
845 :
846 1212 : if (!NT_STATUS_IS_OK(nt_status)) {
847 0 : talloc_free(tmp_ctx);
848 0 : return nt_status;
849 : }
850 :
851 1212 : nt_status = gensec_krb5_session_key(gensec_security, session_info, &session_info->session_key);
852 :
853 1212 : if (!NT_STATUS_IS_OK(nt_status)) {
854 0 : talloc_free(tmp_ctx);
855 0 : return nt_status;
856 : }
857 :
858 1212 : *_session_info = talloc_steal(mem_ctx, session_info);
859 :
860 1212 : talloc_free(tmp_ctx);
861 1212 : return NT_STATUS_OK;
862 : }
863 : #else /* MIT KERBEROS */
864 42 : static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security,
865 : TALLOC_CTX *mem_ctx,
866 : struct auth_session_info **psession_info)
867 : {
868 42 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
869 42 : struct gensec_krb5_state *gensec_krb5_state =
870 : (struct gensec_krb5_state *)gensec_security->private_data;
871 42 : krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;
872 42 : struct auth_session_info *session_info = NULL;
873 :
874 : krb5_principal client_principal;
875 42 : char *principal_string = NULL;
876 :
877 42 : krb5_authdata **auth_pac_data = NULL;
878 42 : DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
879 :
880 : krb5_error_code code;
881 :
882 : TALLOC_CTX *tmp_ctx;
883 :
884 42 : tmp_ctx = talloc_new(mem_ctx);
885 42 : if (tmp_ctx == NULL) {
886 0 : return NT_STATUS_NO_MEMORY;
887 : }
888 :
889 42 : code = krb5_copy_principal(context,
890 42 : gensec_krb5_state->ticket->enc_part2->client,
891 : &client_principal);
892 42 : if (code != 0) {
893 0 : DBG_INFO("krb5_copy_principal failed to copy client "
894 : "principal: %s\n",
895 : smb_get_krb5_error_message(context, code, tmp_ctx));
896 0 : talloc_free(tmp_ctx);
897 0 : return NT_STATUS_NO_MEMORY;
898 : }
899 :
900 42 : code = krb5_unparse_name(context, client_principal, &principal_string);
901 42 : if (code != 0) {
902 0 : DBG_WARNING("Unable to parse client principal: %s\n",
903 : smb_get_krb5_error_message(context, code, tmp_ctx));
904 0 : krb5_free_principal(context, client_principal);
905 0 : talloc_free(tmp_ctx);
906 0 : return NT_STATUS_NO_MEMORY;
907 : }
908 :
909 42 : code = krb5_find_authdata(context,
910 42 : gensec_krb5_state->ticket->enc_part2->authorization_data,
911 : NULL,
912 : KRB5_AUTHDATA_WIN2K_PAC,
913 : &auth_pac_data);
914 42 : if (code != 0) {
915 : /* NO pac */
916 0 : DBG_INFO("krb5_find_authdata failed to find PAC: %s\n",
917 : smb_get_krb5_error_message(context, code, tmp_ctx));
918 : } else {
919 42 : krb5_timestamp ticket_authtime =
920 42 : gensec_krb5_state->ticket->enc_part2->times.authtime;
921 :
922 : /* Found pac */
923 42 : pac_blob = data_blob_talloc(tmp_ctx,
924 : auth_pac_data[0]->contents,
925 : auth_pac_data[0]->length);
926 42 : krb5_free_authdata(context, auth_pac_data);
927 42 : if (pac_blob.data == NULL) {
928 0 : free(principal_string);
929 0 : krb5_free_principal(context, client_principal);
930 0 : talloc_free(tmp_ctx);
931 0 : return NT_STATUS_NO_MEMORY;
932 : }
933 :
934 : /* decode and verify the pac */
935 42 : status = kerberos_decode_pac(gensec_krb5_state,
936 : pac_blob,
937 : context,
938 : NULL,
939 42 : gensec_krb5_state->keyblock,
940 : client_principal,
941 : ticket_authtime,
942 : NULL);
943 :
944 42 : if (!NT_STATUS_IS_OK(status)) {
945 0 : free(principal_string);
946 0 : krb5_free_principal(context, client_principal);
947 0 : talloc_free(tmp_ctx);
948 0 : return status;
949 : }
950 :
951 42 : pac_blob_ptr = &pac_blob;
952 : }
953 42 : krb5_free_principal(context, client_principal);
954 :
955 42 : status = gensec_generate_session_info_pac(tmp_ctx,
956 : gensec_security,
957 : gensec_krb5_state->smb_krb5_context,
958 : pac_blob_ptr,
959 : principal_string,
960 : gensec_get_remote_address(gensec_security),
961 : &session_info);
962 42 : SAFE_FREE(principal_string);
963 42 : if (!NT_STATUS_IS_OK(status)) {
964 0 : talloc_free(tmp_ctx);
965 0 : return status;
966 : }
967 :
968 42 : status = gensec_krb5_session_key(gensec_security,
969 : session_info,
970 42 : &session_info->session_key);
971 42 : if (!NT_STATUS_IS_OK(status)) {
972 0 : talloc_free(tmp_ctx);
973 0 : return status;
974 : }
975 :
976 42 : *psession_info = talloc_steal(mem_ctx, session_info);
977 42 : talloc_free(tmp_ctx);
978 :
979 42 : return NT_STATUS_OK;
980 : }
981 : #endif /* SAMBA4_USES_HEIMDAL */
982 :
983 84 : static NTSTATUS gensec_krb5_wrap(struct gensec_security *gensec_security,
984 : TALLOC_CTX *mem_ctx,
985 : const DATA_BLOB *in,
986 : DATA_BLOB *out)
987 : {
988 84 : struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
989 84 : krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;
990 84 : krb5_auth_context auth_context = gensec_krb5_state->auth_context;
991 0 : krb5_error_code ret;
992 0 : krb5_data input, output;
993 84 : input.length = in->length;
994 84 : input.data = (char *)in->data;
995 :
996 84 : if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
997 84 : ret = krb5_mk_priv(context, auth_context, &input, &output, NULL);
998 84 : if (ret) {
999 0 : DEBUG(1, ("krb5_mk_priv failed: %s\n",
1000 : smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
1001 : ret, mem_ctx)));
1002 0 : return NT_STATUS_ACCESS_DENIED;
1003 : }
1004 84 : *out = data_blob_talloc(mem_ctx, output.data, output.length);
1005 :
1006 84 : smb_krb5_free_data_contents(context, &output);
1007 : } else {
1008 0 : return NT_STATUS_ACCESS_DENIED;
1009 : }
1010 84 : return NT_STATUS_OK;
1011 : }
1012 :
1013 102 : static NTSTATUS gensec_krb5_unwrap(struct gensec_security *gensec_security,
1014 : TALLOC_CTX *mem_ctx,
1015 : const DATA_BLOB *in,
1016 : DATA_BLOB *out)
1017 : {
1018 102 : struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
1019 102 : krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;
1020 102 : krb5_auth_context auth_context = gensec_krb5_state->auth_context;
1021 0 : krb5_error_code ret;
1022 0 : krb5_data input, output;
1023 0 : krb5_replay_data replay;
1024 102 : input.length = in->length;
1025 102 : input.data = (char *)in->data;
1026 :
1027 102 : if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
1028 102 : ret = krb5_rd_priv(context, auth_context, &input, &output, &replay);
1029 102 : if (ret) {
1030 4 : DEBUG(1, ("krb5_rd_priv failed: %s\n",
1031 : smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
1032 : ret, mem_ctx)));
1033 4 : return NT_STATUS_ACCESS_DENIED;
1034 : }
1035 98 : *out = data_blob_talloc(mem_ctx, output.data, output.length);
1036 :
1037 98 : smb_krb5_free_data_contents(context, &output);
1038 : } else {
1039 0 : return NT_STATUS_ACCESS_DENIED;
1040 : }
1041 98 : return NT_STATUS_OK;
1042 : }
1043 :
1044 2420 : static bool gensec_krb5_have_feature(struct gensec_security *gensec_security,
1045 : uint32_t feature)
1046 : {
1047 2420 : struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
1048 2420 : if (feature & GENSEC_FEATURE_SESSION_KEY) {
1049 388 : return true;
1050 : }
1051 2032 : if (gensec_krb5_state->gssapi) {
1052 388 : return false;
1053 : }
1054 :
1055 : /*
1056 : * krb5_mk_priv provides SIGN and SEAL
1057 : */
1058 1644 : if (feature & GENSEC_FEATURE_SIGN) {
1059 102 : return true;
1060 : }
1061 1542 : if (feature & GENSEC_FEATURE_SEAL) {
1062 1542 : return true;
1063 : }
1064 :
1065 0 : return false;
1066 : }
1067 :
1068 1254 : static const char *gensec_krb5_final_auth_type(struct gensec_security *gensec_security)
1069 : {
1070 1254 : return GENSEC_FINAL_AUTH_TYPE_KRB5;
1071 : }
1072 :
1073 : static const char *gensec_krb5_oids[] = {
1074 : GENSEC_OID_KERBEROS5,
1075 : GENSEC_OID_KERBEROS5_OLD,
1076 : NULL
1077 : };
1078 :
1079 : static const struct gensec_security_ops gensec_fake_gssapi_krb5_security_ops = {
1080 : .name = "fake_gssapi_krb5",
1081 : .auth_type = DCERPC_AUTH_TYPE_KRB5,
1082 : .oid = gensec_krb5_oids,
1083 : .client_start = gensec_fake_gssapi_krb5_client_start,
1084 : .server_start = gensec_fake_gssapi_krb5_server_start,
1085 : .update_send = gensec_krb5_update_send,
1086 : .update_recv = gensec_krb5_update_recv,
1087 : .magic = gensec_magic_check_krb5_oid,
1088 : .session_key = gensec_krb5_session_key,
1089 : .session_info = gensec_krb5_session_info,
1090 : .have_feature = gensec_krb5_have_feature,
1091 : .final_auth_type = gensec_krb5_final_auth_type,
1092 : .enabled = false,
1093 : .kerberos = true,
1094 : .priority = GENSEC_KRB5,
1095 : };
1096 :
1097 : static const struct gensec_security_ops gensec_krb5_security_ops = {
1098 : .name = "krb5",
1099 : .client_start = gensec_krb5_client_start,
1100 : .server_start = gensec_krb5_server_start,
1101 : .update_send = gensec_krb5_update_send,
1102 : .update_recv = gensec_krb5_update_recv,
1103 : .session_key = gensec_krb5_session_key,
1104 : .session_info = gensec_krb5_session_info,
1105 : .have_feature = gensec_krb5_have_feature,
1106 : .wrap = gensec_krb5_wrap,
1107 : .unwrap = gensec_krb5_unwrap,
1108 : .final_auth_type = gensec_krb5_final_auth_type,
1109 : .enabled = true,
1110 : .kerberos = true,
1111 : .priority = GENSEC_KRB5
1112 : };
1113 :
1114 18361 : _PUBLIC_ NTSTATUS gensec_krb5_init(TALLOC_CTX *ctx)
1115 : {
1116 1174 : NTSTATUS ret;
1117 :
1118 18361 : ret = gensec_register(ctx, &gensec_krb5_security_ops);
1119 18361 : if (!NT_STATUS_IS_OK(ret)) {
1120 0 : DEBUG(0,("Failed to register '%s' gensec backend!\n",
1121 : gensec_krb5_security_ops.name));
1122 0 : return ret;
1123 : }
1124 :
1125 18361 : ret = gensec_register(ctx, &gensec_fake_gssapi_krb5_security_ops);
1126 18361 : if (!NT_STATUS_IS_OK(ret)) {
1127 0 : DEBUG(0,("Failed to register '%s' gensec backend!\n",
1128 : gensec_fake_gssapi_krb5_security_ops.name));
1129 0 : return ret;
1130 : }
1131 :
1132 18361 : return ret;
1133 : }
|