s3:libsmb: allow store_cldap_reply() to work with a ipv6 response
[samba.git] / source4 / auth / gensec / gensec_gssapi.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Kerberos backend for GENSEC
5    
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7    Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005
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    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include <tevent.h>
26 #include "lib/util/tevent_ntstatus.h"
27 #include "lib/events/events.h"
28 #include "system/kerberos.h"
29 #include "system/gssapi.h"
30 #include "auth/kerberos/kerberos.h"
31 #include "librpc/gen_ndr/krb5pac.h"
32 #include "auth/auth.h"
33 #include <ldb.h>
34 #include "auth/auth_sam.h"
35 #include "librpc/gen_ndr/dcerpc.h"
36 #include "auth/credentials/credentials.h"
37 #include "auth/credentials/credentials_krb5.h"
38 #include "auth/gensec/gensec.h"
39 #include "auth/gensec/gensec_internal.h"
40 #include "auth/gensec/gensec_proto.h"
41 #include "auth/gensec/gensec_toplevel_proto.h"
42 #include "param/param.h"
43 #include "auth/session_proto.h"
44 #include "gensec_gssapi.h"
45 #include "lib/util/util_net.h"
46 #include "auth/kerberos/pac_utils.h"
47 #include "auth/kerberos/gssapi_helper.h"
48 #include "lib/util/smb_strtox.h"
49
50 #ifndef gss_mech_spnego
51 gss_OID_desc spnego_mech_oid_desc =
52                 { 6, discard_const_p(void, "\x2b\x06\x01\x05\x05\x02") };
53 #define gss_mech_spnego (&spnego_mech_oid_desc)
54 #endif
55
56 _PUBLIC_ NTSTATUS gensec_gssapi_init(TALLOC_CTX *);
57
58 static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security);
59 static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security);
60 static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size);
61
62 static int gensec_gssapi_destructor(struct gensec_gssapi_state *gensec_gssapi_state)
63 {
64         OM_uint32 min_stat;
65
66         if (gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
67                 gss_release_cred(&min_stat,
68                                  &gensec_gssapi_state->delegated_cred_handle);
69         }
70
71         if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) {
72                 gss_delete_sec_context(&min_stat,
73                                        &gensec_gssapi_state->gssapi_context,
74                                        GSS_C_NO_BUFFER);
75         }
76
77         if (gensec_gssapi_state->server_name != GSS_C_NO_NAME) {
78                 gss_release_name(&min_stat,
79                                  &gensec_gssapi_state->server_name);
80         }
81         if (gensec_gssapi_state->client_name != GSS_C_NO_NAME) {
82                 gss_release_name(&min_stat,
83                                  &gensec_gssapi_state->client_name);
84         }
85
86         return 0;
87 }
88
89 static NTSTATUS gensec_gssapi_setup_server_principal(TALLOC_CTX *mem_ctx,
90                                                      const char *target_principal,
91                                                      const char *service,
92                                                      const char *hostname,
93                                                      const char *realm,
94                                                      const gss_OID mech,
95                                                      char **pserver_principal,
96                                                      gss_name_t *pserver_name)
97 {
98         char *server_principal = NULL;
99         gss_buffer_desc name_token;
100         gss_OID name_type;
101         OM_uint32 maj_stat, min_stat = 0;
102
103         if (target_principal != NULL) {
104                 server_principal = talloc_strdup(mem_ctx, target_principal);
105                 name_type = GSS_C_NULL_OID;
106         } else {
107                 server_principal = talloc_asprintf(mem_ctx,
108                                                    "%s/%s@%s",
109                                                    service, hostname, realm);
110                 name_type = GSS_C_NT_USER_NAME;
111         }
112         if (server_principal == NULL) {
113                 return NT_STATUS_NO_MEMORY;
114         }
115
116         name_token.value = (uint8_t *)server_principal;
117         name_token.length = strlen(server_principal);
118
119         maj_stat = gss_import_name(&min_stat,
120                                    &name_token,
121                                    name_type,
122                                    pserver_name);
123         if (maj_stat) {
124                 DBG_WARNING("GSS Import name of %s failed: %s\n",
125                             server_principal,
126                             gssapi_error_string(mem_ctx,
127                                                 maj_stat,
128                                                 min_stat,
129                                                 mech));
130                 TALLOC_FREE(server_principal);
131                 return NT_STATUS_INVALID_PARAMETER;
132         }
133
134         *pserver_principal = server_principal;
135
136         return NT_STATUS_OK;
137 }
138
139 static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
140 {
141         struct gensec_gssapi_state *gensec_gssapi_state;
142         krb5_error_code ret;
143 #ifdef SAMBA4_USES_HEIMDAL
144         const char *realm;
145 #endif
146
147         gensec_gssapi_state = talloc_zero(gensec_security, struct gensec_gssapi_state);
148         if (!gensec_gssapi_state) {
149                 return NT_STATUS_NO_MEMORY;
150         }
151
152         gensec_security->private_data = gensec_gssapi_state;
153
154         gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT;
155
156         if (gensec_security->channel_bindings != NULL) {
157                 gensec_gssapi_state->_input_chan_bindings.initiator_addrtype =
158                         gensec_security->channel_bindings->initiator_addrtype;
159                 gensec_gssapi_state->_input_chan_bindings.initiator_address.value =
160                         gensec_security->channel_bindings->initiator_address.data;
161                 gensec_gssapi_state->_input_chan_bindings.initiator_address.length =
162                         gensec_security->channel_bindings->initiator_address.length;
163
164                 gensec_gssapi_state->_input_chan_bindings.acceptor_addrtype =
165                         gensec_security->channel_bindings->acceptor_addrtype;
166                 gensec_gssapi_state->_input_chan_bindings.acceptor_address.value =
167                         gensec_security->channel_bindings->acceptor_address.data;
168                 gensec_gssapi_state->_input_chan_bindings.acceptor_address.length =
169                         gensec_security->channel_bindings->acceptor_address.length;
170
171                 gensec_gssapi_state->_input_chan_bindings.application_data.value =
172                         gensec_security->channel_bindings->application_data.data;
173                 gensec_gssapi_state->_input_chan_bindings.application_data.length =
174                         gensec_security->channel_bindings->application_data.length;
175
176                 gensec_gssapi_state->input_chan_bindings =
177                         &gensec_gssapi_state->_input_chan_bindings;
178         } else {
179                 gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
180         }
181
182         gensec_gssapi_state->server_name = GSS_C_NO_NAME;
183         gensec_gssapi_state->client_name = GSS_C_NO_NAME;
184         
185         gensec_gssapi_state->gss_want_flags = 0;
186         gensec_gssapi_state->expire_time = GENSEC_EXPIRE_TIME_INFINITY;
187
188         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation_by_kdc_policy", true)) {
189                 gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_POLICY_FLAG;
190         }
191         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "mutual", true)) {
192                 gensec_gssapi_state->gss_want_flags |= GSS_C_MUTUAL_FLAG;
193         }
194         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation", false)) {
195                 gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_FLAG;
196         }
197         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "replay", true)) {
198                 gensec_gssapi_state->gss_want_flags |= GSS_C_REPLAY_FLAG;
199         }
200         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "sequence", true)) {
201                 gensec_gssapi_state->gss_want_flags |= GSS_C_SEQUENCE_FLAG;
202         }
203
204         if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
205                 gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
206         }
207         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
208                 gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
209         }
210         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
211                 gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
212                 gensec_gssapi_state->gss_want_flags |= GSS_C_CONF_FLAG;
213         }
214         if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
215                 gensec_gssapi_state->gss_want_flags |= GSS_C_DCE_STYLE;
216         }
217
218         gensec_gssapi_state->gss_got_flags = 0;
219
220         switch (gensec_security->ops->auth_type) {
221         case DCERPC_AUTH_TYPE_SPNEGO:
222                 gensec_gssapi_state->gss_oid = gss_mech_spnego;
223                 break;
224         case DCERPC_AUTH_TYPE_KRB5:
225         default:
226                 gensec_gssapi_state->gss_oid =
227                         discard_const_p(void, gss_mech_krb5);
228                 break;
229         }
230
231         ret = smb_krb5_init_context(gensec_gssapi_state,
232                                     gensec_security->settings->lp_ctx,
233                                     &gensec_gssapi_state->smb_krb5_context);
234         if (ret) {
235                 DEBUG(1,("gensec_gssapi_start: smb_krb5_init_context failed (%s)\n",
236                          error_message(ret)));
237                 talloc_free(gensec_gssapi_state);
238                 return NT_STATUS_INTERNAL_ERROR;
239         }
240
241         gensec_gssapi_state->client_cred = NULL;
242         gensec_gssapi_state->server_cred = NULL;
243
244         gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
245
246         gensec_gssapi_state->sasl = false;
247         gensec_gssapi_state->sasl_state = STAGE_GSS_NEG;
248         gensec_gssapi_state->sasl_protection = 0;
249
250         gensec_gssapi_state->max_wrap_buf_size
251                 = gensec_setting_int(gensec_security->settings, "gensec_gssapi", "max wrap buf size", 65536);
252         gensec_gssapi_state->gss_exchange_count = 0;
253         gensec_gssapi_state->sig_size = 0;
254
255         talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destructor);
256
257 #ifdef SAMBA4_USES_HEIMDAL
258         realm = lpcfg_realm(gensec_security->settings->lp_ctx);
259         if (realm != NULL) {
260                 ret = gsskrb5_set_default_realm(realm);
261                 if (ret) {
262                         DEBUG(1,("gensec_gssapi_start: gsskrb5_set_default_realm failed\n"));
263                         talloc_free(gensec_gssapi_state);
264                         return NT_STATUS_INTERNAL_ERROR;
265                 }
266         }
267
268         /* don't do DNS lookups of any kind, it might/will fail for a netbios name */
269         ret = gsskrb5_set_dns_canonicalize(false);
270         if (ret) {
271                 DEBUG(1,("gensec_gssapi_start: gsskrb5_set_dns_canonicalize failed\n"));
272                 talloc_free(gensec_gssapi_state);
273                 return NT_STATUS_INTERNAL_ERROR;
274         }
275 #endif
276         return NT_STATUS_OK;
277 }
278
279 static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
280 {
281         NTSTATUS nt_status;
282         int ret;
283         struct gensec_gssapi_state *gensec_gssapi_state;
284         struct cli_credentials *machine_account;
285         struct gssapi_creds_container *gcc;
286
287         nt_status = gensec_gssapi_start(gensec_security);
288         if (!NT_STATUS_IS_OK(nt_status)) {
289                 return nt_status;
290         }
291
292         gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
293
294         machine_account = gensec_get_credentials(gensec_security);
295         
296         if (!machine_account) {
297                 DEBUG(3, ("No machine account credentials specified\n"));
298                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
299         } else {
300                 ret = cli_credentials_get_server_gss_creds(machine_account, 
301                                                            gensec_security->settings->lp_ctx, &gcc);
302                 if (ret) {
303                         DEBUG(1, ("Acquiring acceptor credentials failed: %s\n",
304                                   error_message(ret)));
305                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
306                 }
307         }
308
309         gensec_gssapi_state->server_cred = gcc;
310         return NT_STATUS_OK;
311
312 }
313
314 static NTSTATUS gensec_gssapi_sasl_server_start(struct gensec_security *gensec_security)
315 {
316         NTSTATUS nt_status;
317         struct gensec_gssapi_state *gensec_gssapi_state;
318         nt_status = gensec_gssapi_server_start(gensec_security);
319
320         if (NT_STATUS_IS_OK(nt_status)) {
321                 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
322                 gensec_gssapi_state->sasl = true;
323         }
324         return nt_status;
325 }
326
327 static NTSTATUS gensec_gssapi_client_creds(struct gensec_security *gensec_security,
328                                            struct tevent_context *ev)
329 {
330         struct gensec_gssapi_state *gensec_gssapi_state;
331         struct gssapi_creds_container *gcc;
332         struct cli_credentials *creds = gensec_get_credentials(gensec_security);
333         const char *error_string;
334         int ret;
335
336         gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
337
338         /* Only run this the first time the update() call is made */
339         if (gensec_gssapi_state->client_cred) {
340                 return NT_STATUS_OK;
341         }
342
343         ret = cli_credentials_get_client_gss_creds(creds,
344                                                    ev,
345                                                    gensec_security->settings->lp_ctx, &gcc, &error_string);
346         switch (ret) {
347         case 0:
348                 break;
349         case EINVAL:
350                 DEBUG(3, ("Cannot obtain client GSS credentials we need to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
351                 return NT_STATUS_INVALID_PARAMETER;
352         case KRB5KDC_ERR_PREAUTH_FAILED:
353         case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
354         case KRB5KRB_AP_ERR_BAD_INTEGRITY:
355                 DEBUG(1, ("Wrong username or password: %s\n", error_string));
356                 return NT_STATUS_LOGON_FAILURE;
357         case KRB5KDC_ERR_CLIENT_REVOKED:
358                 DEBUG(1, ("Account locked out: %s\n", error_string));
359                 return NT_STATUS_ACCOUNT_LOCKED_OUT;
360         case KRB5_REALM_UNKNOWN:
361         case KRB5_KDC_UNREACH:
362                 DEBUG(3, ("Cannot reach a KDC we require to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
363                 return NT_STATUS_NO_LOGON_SERVERS;
364         case KRB5_CC_NOTFOUND:
365         case KRB5_CC_END:
366                 DEBUG(2, ("Error obtaining ticket we require to contact %s: (possibly due to clock skew between us and the KDC) %s\n", gensec_gssapi_state->target_principal, error_string));
367                 return NT_STATUS_TIME_DIFFERENCE_AT_DC;
368         default:
369                 DEBUG(1, ("Acquiring initiator credentials failed: %s\n", error_string));
370                 return NT_STATUS_UNSUCCESSFUL;
371         }
372
373         gensec_gssapi_state->client_cred = gcc;
374         if (!talloc_reference(gensec_gssapi_state, gcc)) {
375                 return NT_STATUS_NO_MEMORY;
376         }
377
378         return NT_STATUS_OK;
379 }
380
381 static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
382 {
383         struct gensec_gssapi_state *gensec_gssapi_state;
384         struct cli_credentials *creds = gensec_get_credentials(gensec_security);
385         NTSTATUS nt_status;
386
387         nt_status = gensec_kerberos_possible(gensec_security);
388         if (!NT_STATUS_IS_OK(nt_status)) {
389                 char *target_name = NULL;
390                 char *cred_name = NULL;
391
392                 target_name = gensec_get_unparsed_target_principal(gensec_security,
393                                                                    gensec_security);
394                 cred_name = cli_credentials_get_unparsed_name(creds,
395                                                               gensec_security);
396
397                 DBG_NOTICE("Not using kerberos to %s as %s: %s\n",
398                            target_name, cred_name, nt_errstr(nt_status));
399
400                 TALLOC_FREE(target_name);
401                 TALLOC_FREE(cred_name);
402                 return nt_status;
403         }
404
405         nt_status = gensec_gssapi_start(gensec_security);
406         if (!NT_STATUS_IS_OK(nt_status)) {
407                 return nt_status;
408         }
409
410         gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
411
412 #ifdef HAVE_CLIENT_GSS_C_CHANNEL_BOUND_FLAG
413         /*
414          * We can only use GSS_C_CHANNEL_BOUND_FLAG if the kerberos library
415          * supports that in order to add KERB_AP_OPTIONS_CBT.
416          *
417          * See:
418          * https://github.com/heimdal/heimdal/pull/1234
419          * https://github.com/krb5/krb5/pull/1329
420          */
421         if (!(gensec_security->want_features & GENSEC_FEATURE_CB_OPTIONAL)) {
422                 gensec_gssapi_state->gss_want_flags |= GSS_C_CHANNEL_BOUND_FLAG;
423         }
424 #endif
425
426         if (cli_credentials_get_impersonate_principal(creds)) {
427                 gensec_gssapi_state->gss_want_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG);
428         }
429
430         return NT_STATUS_OK;
431 }
432
433 static NTSTATUS gensec_gssapi_sasl_client_start(struct gensec_security *gensec_security)
434 {
435         NTSTATUS nt_status;
436         struct gensec_gssapi_state *gensec_gssapi_state;
437         nt_status = gensec_gssapi_client_start(gensec_security);
438
439         if (NT_STATUS_IS_OK(nt_status)) {
440                 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
441                 gensec_gssapi_state->sasl = true;
442         }
443         return nt_status;
444 }
445
446 static NTSTATUS gensec_gssapi_update_internal(struct gensec_security *gensec_security,
447                                               TALLOC_CTX *out_mem_ctx,
448                                               struct tevent_context *ev,
449                                               const DATA_BLOB in, DATA_BLOB *out)
450 {
451         struct gensec_gssapi_state *gensec_gssapi_state
452                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
453         NTSTATUS nt_status;
454         OM_uint32 maj_stat, min_stat;
455         OM_uint32 min_stat2;
456         gss_buffer_desc input_token = { 0, NULL };
457         gss_buffer_desc output_token = { 0, NULL };
458         struct cli_credentials *cli_creds = gensec_get_credentials(gensec_security);
459         const char *target_principal = gensec_get_target_principal(gensec_security);
460         const char *hostname = gensec_get_target_hostname(gensec_security);
461         const char *service = gensec_get_target_service(gensec_security);
462         gss_OID gss_oid_p = NULL;
463         OM_uint32 time_req = 0;
464         OM_uint32 time_rec = 0;
465         struct timeval tv;
466
467         time_req = gensec_setting_int(gensec_security->settings,
468                                       "gensec_gssapi", "requested_life_time",
469                                       time_req);
470
471         input_token.length = in.length;
472         input_token.value = in.data;
473
474         switch (gensec_gssapi_state->sasl_state) {
475         case STAGE_GSS_NEG:
476         {
477                 switch (gensec_security->gensec_role) {
478                 case GENSEC_CLIENT:
479                 {
480                         const char *client_realm = NULL;
481 #ifdef SAMBA4_USES_HEIMDAL
482                         struct gsskrb5_send_to_kdc send_to_kdc;
483                         krb5_error_code ret;
484 #else
485                         bool fallback = false;
486 #endif
487
488                         nt_status = gensec_gssapi_client_creds(gensec_security, ev);
489                         if (!NT_STATUS_IS_OK(nt_status)) {
490                                 return nt_status;
491                         }
492
493 #ifdef SAMBA4_USES_HEIMDAL
494                         send_to_kdc.func = smb_krb5_send_and_recv_func;
495                         send_to_kdc.ptr = ev;
496
497                         min_stat = gsskrb5_set_send_to_kdc(&send_to_kdc);
498                         if (min_stat) {
499                                 DEBUG(1,("gensec_gssapi_update: gsskrb5_set_send_to_kdc failed\n"));
500                                 return NT_STATUS_INTERNAL_ERROR;
501                         }
502 #endif
503
504                         /*
505                          * With credentials for
506                          * administrator@FOREST1.EXAMPLE.COM this patch changes
507                          * the target_principal for the ldap service of host
508                          * dc2.forest2.example.com from
509                          *
510                          *   ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM
511                          *
512                          * to
513                          *
514                          *   ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM
515                          *
516                          * Typically
517                          * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM
518                          * should be used in order to allow the KDC of
519                          * FOREST1.EXAMPLE.COM to generate a referral ticket
520                          * for krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM.
521                          *
522                          * The problem is that KDCs only return such referral
523                          * tickets if there's a forest trust between
524                          * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM. If
525                          * there's only an external domain trust between
526                          * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM the KDC
527                          * of FOREST1.EXAMPLE.COM will respond with
528                          * S_PRINCIPAL_UNKNOWN when being asked for
529                          * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM.
530                          *
531                          * In the case of an external trust the client can
532                          * still ask explicitly for
533                          * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM and
534                          * the KDC of FOREST1.EXAMPLE.COM will generate it.
535                          *
536                          * From there the client can use the
537                          * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM
538                          * ticket and ask a KDC of FOREST2.EXAMPLE.COM for a
539                          * service ticket for
540                          * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM.
541                          *
542                          * With Heimdal we'll get the fallback on
543                          * S_PRINCIPAL_UNKNOWN behavior when we pass
544                          * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM as
545                          * target principal. As _krb5_get_cred_kdc_any() first
546                          * calls get_cred_kdc_referral() (which always starts
547                          * with the client realm) and falls back to
548                          * get_cred_kdc_capath() (which starts with the given
549                          * realm).
550                          *
551                          * MIT krb5 only tries the given realm of the target
552                          * principal, if we want to autodetect support for
553                          * transitive forest trusts, would have to do the
554                          * fallback ourself.
555                          */
556                         client_realm = cli_credentials_get_realm(cli_creds);
557 #ifndef SAMBA4_USES_HEIMDAL
558                         if (gensec_gssapi_state->server_name == NULL) {
559                                 nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state,
560                                                                                  target_principal,
561                                                                                  service,
562                                                                                  hostname,
563                                                                                  client_realm,
564                                                                                  gensec_gssapi_state->gss_oid,
565                                                                                  &gensec_gssapi_state->target_principal,
566                                                                                  &gensec_gssapi_state->server_name);
567                                 if (!NT_STATUS_IS_OK(nt_status)) {
568                                         return nt_status;
569                                 }
570
571                                 maj_stat = gss_init_sec_context(&min_stat,
572                                                                 gensec_gssapi_state->client_cred->creds,
573                                                                 &gensec_gssapi_state->gssapi_context,
574                                                                 gensec_gssapi_state->server_name,
575                                                                 gensec_gssapi_state->gss_oid,
576                                                                 gensec_gssapi_state->gss_want_flags,
577                                                                 time_req,
578                                                                 gensec_gssapi_state->input_chan_bindings,
579                                                                 &input_token,
580                                                                 &gss_oid_p,
581                                                                 &output_token,
582                                                                 &gensec_gssapi_state->gss_got_flags, /* ret flags */
583                                                                 &time_rec);
584                                 if (maj_stat != GSS_S_FAILURE) {
585                                         goto init_sec_context_done;
586                                 }
587                                 if (min_stat != (OM_uint32)KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
588                                         goto init_sec_context_done;
589                                 }
590                                 if (target_principal != NULL) {
591                                         goto init_sec_context_done;
592                                 }
593
594                                 fallback = true;
595                                 TALLOC_FREE(gensec_gssapi_state->target_principal);
596                                 gss_release_name(&min_stat2, &gensec_gssapi_state->server_name);
597                         }
598 #endif /* !SAMBA4_USES_HEIMDAL */
599                         if (gensec_gssapi_state->server_name == NULL) {
600                                 const char *server_realm = NULL;
601
602                                 server_realm = smb_krb5_get_realm_from_hostname(gensec_gssapi_state,
603                                                                                 hostname,
604                                                                                 client_realm);
605                                 if (server_realm == NULL) {
606                                         return NT_STATUS_NO_MEMORY;
607                                 }
608
609 #ifndef SAMBA4_USES_HEIMDAL
610                                 if (fallback &&
611                                     strequal(client_realm, server_realm)) {
612                                         goto init_sec_context_done;
613                                 }
614 #endif /* !SAMBA4_USES_HEIMDAL */
615
616                                 nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state,
617                                                                                  target_principal,
618                                                                                  service,
619                                                                                  hostname,
620                                                                                  server_realm,
621                                                                                  gensec_gssapi_state->gss_oid,
622                                                                                  &gensec_gssapi_state->target_principal,
623                                                                                  &gensec_gssapi_state->server_name);
624                                 if (!NT_STATUS_IS_OK(nt_status)) {
625                                         return nt_status;
626                                 }
627                         }
628
629                         maj_stat = gss_init_sec_context(&min_stat, 
630                                                         gensec_gssapi_state->client_cred->creds,
631                                                         &gensec_gssapi_state->gssapi_context, 
632                                                         gensec_gssapi_state->server_name, 
633                                                         gensec_gssapi_state->gss_oid,
634                                                         gensec_gssapi_state->gss_want_flags, 
635                                                         time_req,
636                                                         gensec_gssapi_state->input_chan_bindings,
637                                                         &input_token, 
638                                                         &gss_oid_p,
639                                                         &output_token, 
640                                                         &gensec_gssapi_state->gss_got_flags, /* ret flags */
641                                                         &time_rec);
642                         goto init_sec_context_done;
643                         /* JUMP! */
644 init_sec_context_done:
645                         if (gss_oid_p) {
646                                 gensec_gssapi_state->gss_oid = gss_oid_p;
647                         }
648
649 #ifdef SAMBA4_USES_HEIMDAL
650                         send_to_kdc.func = smb_krb5_send_and_recv_func;
651                         send_to_kdc.ptr = NULL;
652
653                         ret = gsskrb5_set_send_to_kdc(&send_to_kdc);
654                         if (ret) {
655                                 DEBUG(1,("gensec_gssapi_update: gsskrb5_set_send_to_kdc failed\n"));
656                                 return NT_STATUS_INTERNAL_ERROR;
657                         }
658 #endif
659                         break;
660                 }
661                 case GENSEC_SERVER:
662                 {
663                         maj_stat = gss_accept_sec_context(&min_stat, 
664                                                           &gensec_gssapi_state->gssapi_context, 
665                                                           gensec_gssapi_state->server_cred->creds,
666                                                           &input_token, 
667                                                           gensec_gssapi_state->input_chan_bindings,
668                                                           &gensec_gssapi_state->client_name, 
669                                                           &gss_oid_p,
670                                                           &output_token, 
671                                                           &gensec_gssapi_state->gss_got_flags, 
672                                                           &time_rec,
673                                                           &gensec_gssapi_state->delegated_cred_handle);
674                         if (gss_oid_p) {
675                                 gensec_gssapi_state->gss_oid = gss_oid_p;
676                         }
677 #ifdef GSS_C_CHANNEL_BOUND_FLAG
678                         if (maj_stat == GSS_S_COMPLETE &&
679                             gensec_security->channel_bindings != NULL &&
680                             !(gensec_security->want_features & GENSEC_FEATURE_CB_OPTIONAL) &&
681                             !(gensec_gssapi_state->gss_got_flags & GSS_C_CHANNEL_BOUND_FLAG))
682                         {
683                                 /*
684                                  * If we require valid channel bindings
685                                  * we need to check the client provided
686                                  * them.
687                                  *
688                                  * We detect this if
689                                  * GSS_C_CHANNEL_BOUND_FLAG is given.
690                                  *
691                                  * Recent heimdal and MIT releases support this
692                                  * with older releases (e.g. MIT > 1.19).
693                                  *
694                                  * It means client with zero channel bindings
695                                  * on a server with non-zero channel bindings
696                                  * won't generate GSS_S_BAD_BINDINGS directly
697                                  * unless KERB_AP_OPTIONS_CBT was also
698                                  * provides by the client.
699                                  *
700                                  * So we need to convert a missing
701                                  * GSS_C_CHANNEL_BOUND_FLAG into
702                                  * GSS_S_BAD_BINDINGS by default
703                                  * (unless GENSEC_FEATURE_CB_OPTIONAL is given).
704                                  */
705                                 maj_stat = GSS_S_BAD_BINDINGS;
706                                 min_stat = 0;
707                         }
708 #endif /* GSS_C_CHANNEL_BOUND_FLAG */
709
710                         break;
711                 }
712                 default:
713                         return NT_STATUS_INVALID_PARAMETER;
714                         
715                 }
716
717                 gensec_gssapi_state->gss_exchange_count++;
718
719                 if (maj_stat == GSS_S_COMPLETE) {
720                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
721                         gss_release_buffer(&min_stat2, &output_token);
722                         
723                         if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG &&
724                             gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
725                                 DEBUG(5, ("gensec_gssapi: credentials were delegated\n"));
726                         } else {
727                                 DEBUG(5, ("gensec_gssapi: NO credentials were delegated\n"));
728                         }
729
730                         tv = timeval_current_ofs(time_rec, 0);
731                         gensec_gssapi_state->expire_time = timeval_to_nttime(&tv);
732
733                         /* We may have been invoked as SASL, so there
734                          * is more work to do */
735                         if (gensec_gssapi_state->sasl) {
736                                 gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_NEG;
737                                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
738                         } else {
739                                 gensec_gssapi_state->sasl_state = STAGE_DONE;
740
741                                 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
742                                         DEBUG(5, ("GSSAPI Connection will be cryptographically sealed\n"));
743                                 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
744                                         DEBUG(5, ("GSSAPI Connection will be cryptographically signed\n"));
745                                 } else {
746                                         DEBUG(5, ("GSSAPI Connection will have no cryptographic protection\n"));
747                                 }
748
749                                 return NT_STATUS_OK;
750                         }
751                 } else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
752                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
753                         gss_release_buffer(&min_stat2, &output_token);
754                         
755                         return NT_STATUS_MORE_PROCESSING_REQUIRED;
756                 } else if (maj_stat == GSS_S_BAD_BINDINGS) {
757                         DBG_WARNING("Got GSS_S_BAD_BINDINGS\n");
758                         return NT_STATUS_BAD_BINDINGS;
759                 } else if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
760                         gss_cred_id_t creds = NULL;
761                         gss_name_t name;
762                         gss_buffer_desc buffer;
763                         OM_uint32 lifetime = 0;
764                         gss_cred_usage_t usage;
765                         const char *role = NULL;
766
767                         switch (gensec_security->gensec_role) {
768                         case GENSEC_CLIENT:
769                                 creds = gensec_gssapi_state->client_cred->creds;
770                                 role = "client";
771                                 break;
772                         case GENSEC_SERVER:
773                                 creds = gensec_gssapi_state->server_cred->creds;
774                                 role = "server";
775                                 break;
776                         }
777
778                         DBG_ERR("GSS %s Update(krb5)(%d) failed, credentials "
779                                 "expired during GSSAPI handshake!\n",
780                                 role,
781                                 gensec_gssapi_state->gss_exchange_count);
782
783                         maj_stat = gss_inquire_cred(&min_stat, 
784                                                     creds,
785                                                     &name, &lifetime, &usage, NULL);
786
787                         if (maj_stat == GSS_S_COMPLETE) {
788                                 const char *usage_string = NULL;
789                                 switch (usage) {
790                                 case GSS_C_BOTH:
791                                         usage_string = "GSS_C_BOTH";
792                                         break;
793                                 case GSS_C_ACCEPT:
794                                         usage_string = "GSS_C_ACCEPT";
795                                         break;
796                                 case GSS_C_INITIATE:
797                                         usage_string = "GSS_C_INITIATE";
798                                         break;
799                                 }
800                                 maj_stat = gss_display_name(&min_stat, name, &buffer, NULL);
801                                 if (maj_stat) {
802                                         buffer.value = NULL;
803                                         buffer.length = 0;
804                                 }
805                                 if (lifetime > 0) {
806                                         DEBUG(0, ("GSSAPI gss_inquire_cred indicates expiry of %*.*s in %u sec for %s\n", 
807                                                   (int)buffer.length, (int)buffer.length, (char *)buffer.value, 
808                                                   lifetime, usage_string));
809                                 } else {
810                                         DEBUG(0, ("GSSAPI gss_inquire_cred indicates %*.*s has already expired for %s\n", 
811                                                   (int)buffer.length, (int)buffer.length, (char *)buffer.value, 
812                                                   usage_string));
813                                 }
814                                 gss_release_buffer(&min_stat, &buffer);
815                                 gss_release_name(&min_stat, &name);
816                         } else if (maj_stat != GSS_S_COMPLETE) {
817                                 DEBUG(0, ("inquiry of credential lifetime via GSSAPI gss_inquire_cred failed: %s\n",
818                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
819                         }
820                         return NT_STATUS_INVALID_PARAMETER;
821                 } else if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
822                                              gss_mech_krb5)) {
823                         switch (min_stat) {
824                         case (OM_uint32)KRB5KRB_AP_ERR_TKT_NYV:
825                                 DEBUG(1, ("Error with ticket to contact %s: possible clock skew between us and the KDC or target server: %s\n",
826                                           gensec_gssapi_state->target_principal,
827                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
828                                 return NT_STATUS_TIME_DIFFERENCE_AT_DC; /* Make SPNEGO ignore us, we can't go any further here */
829                         case (OM_uint32)KRB5KRB_AP_ERR_TKT_EXPIRED:
830                                 DEBUG(1, ("Error with ticket to contact %s: ticket is expired, possible clock skew between us and the KDC or target server: %s\n",
831                                           gensec_gssapi_state->target_principal,
832                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
833                                 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
834                         case (OM_uint32)KRB5_KDC_UNREACH:
835                                 DEBUG(3, ("Cannot reach a KDC we require in order to obtain a ticket to %s: %s\n",
836                                           gensec_gssapi_state->target_principal,
837                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
838                                 return NT_STATUS_NO_LOGON_SERVERS; /* Make SPNEGO ignore us, we can't go any further here */
839                         case (OM_uint32)KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
840                                 DEBUG(3, ("Server %s is not registered with our KDC: %s\n",
841                                           gensec_gssapi_state->target_principal,
842                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
843                                 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
844                         case (OM_uint32)KRB5KRB_AP_ERR_MSG_TYPE:
845                                 /* garbage input, possibly from the auto-mech detection */
846                                 return NT_STATUS_INVALID_PARAMETER;
847                         default:
848                                 DEBUG(1, ("GSS %s Update(krb5)(%d) Update failed: %s\n",
849                                           gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
850                                           gensec_gssapi_state->gss_exchange_count,
851                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
852                                 return NT_STATUS_LOGON_FAILURE;
853                         }
854                 } else {
855                         DEBUG(1, ("GSS %s Update(%d) failed: %s\n",
856                                   gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
857                                   gensec_gssapi_state->gss_exchange_count,
858                                   gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
859                         return NT_STATUS_LOGON_FAILURE;
860                 }
861                 break;
862         }
863
864         /* These last two stages are only done if we were invoked as SASL */
865         case STAGE_SASL_SSF_NEG:
866         {
867                 switch (gensec_security->gensec_role) {
868                 case GENSEC_CLIENT:
869                 {
870                         uint8_t maxlength_proposed[4]; 
871                         uint8_t maxlength_accepted[4]; 
872                         uint8_t security_supported;
873                         int conf_state;
874                         gss_qop_t qop_state;
875                         input_token.length = in.length;
876                         input_token.value = in.data;
877
878                         /* As a client, we have just send a
879                          * zero-length blob to the server (after the
880                          * normal GSSAPI exchange), and it has replied
881                          * with it's SASL negotiation */
882                         
883                         maj_stat = gss_unwrap(&min_stat, 
884                                               gensec_gssapi_state->gssapi_context, 
885                                               &input_token,
886                                               &output_token, 
887                                               &conf_state,
888                                               &qop_state);
889                         if (GSS_ERROR(maj_stat)) {
890                                 DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n", 
891                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
892                                 return NT_STATUS_ACCESS_DENIED;
893                         }
894                         
895                         if (output_token.length < 4) {
896                                 gss_release_buffer(&min_stat, &output_token);
897                                 return NT_STATUS_INVALID_PARAMETER;
898                         }
899
900                         memcpy(maxlength_proposed, output_token.value, 4);
901                         gss_release_buffer(&min_stat, &output_token);
902
903                         /* first byte is the proposed security */
904                         security_supported = maxlength_proposed[0];
905                         maxlength_proposed[0] = '\0';
906                         
907                         /* Rest is the proposed max wrap length */
908                         gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_proposed, 0), 
909                                                                      gensec_gssapi_state->max_wrap_buf_size);
910                         gensec_gssapi_state->sasl_protection = 0;
911                         if (security_supported & NEG_SEAL) {
912                                 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
913                                         gensec_gssapi_state->sasl_protection |= NEG_SEAL;
914                                 }
915                         }
916                         if (security_supported & NEG_SIGN) {
917                                 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
918                                         gensec_gssapi_state->sasl_protection |= NEG_SIGN;
919                                 }
920                         }
921                         if (security_supported & NEG_NONE) {
922                                 gensec_gssapi_state->sasl_protection |= NEG_NONE;
923                         }
924                         if (gensec_gssapi_state->sasl_protection == 0) {
925                                 DEBUG(1, ("Remote server does not support unprotected connections\n"));
926                                 return NT_STATUS_ACCESS_DENIED;
927                         }
928
929                         /* Send back the negotiated max length */
930
931                         RSIVAL(maxlength_accepted, 0, gensec_gssapi_state->max_wrap_buf_size);
932
933                         maxlength_accepted[0] = gensec_gssapi_state->sasl_protection;
934                         
935                         input_token.value = maxlength_accepted;
936                         input_token.length = sizeof(maxlength_accepted);
937
938                         maj_stat = gss_wrap(&min_stat, 
939                                             gensec_gssapi_state->gssapi_context, 
940                                             false,
941                                             GSS_C_QOP_DEFAULT,
942                                             &input_token,
943                                             &conf_state,
944                                             &output_token);
945                         if (GSS_ERROR(maj_stat)) {
946                                 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", 
947                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
948                                 return NT_STATUS_ACCESS_DENIED;
949                         }
950                         
951                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
952                         gss_release_buffer(&min_stat, &output_token);
953
954                         /* quirk:  This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
955                         gensec_gssapi_state->sasl_state = STAGE_DONE;
956
957                         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
958                                 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically sealed\n"));
959                         } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
960                                 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically signed\n"));
961                         } else {
962                                 DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographic protection\n"));
963                         }
964
965                         return NT_STATUS_OK;
966                 }
967                 case GENSEC_SERVER:
968                 {
969                         uint8_t maxlength_proposed[4]; 
970                         uint8_t security_supported = 0x0;
971                         int conf_state;
972
973                         /* As a server, we have just been sent a zero-length blob (note this, but it isn't fatal) */
974                         if (in.length != 0) {
975                                 DEBUG(1, ("SASL/GSSAPI: client sent non-zero length starting SASL negotiation!\n"));
976                         }
977                         
978                         /* Give the client some idea what we will support */
979                           
980                         RSIVAL(maxlength_proposed, 0, gensec_gssapi_state->max_wrap_buf_size);
981                         /* first byte is the proposed security */
982                         maxlength_proposed[0] = '\0';
983                         
984                         gensec_gssapi_state->sasl_protection = 0;
985                         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
986                                 security_supported |= NEG_SEAL;
987                         } 
988                         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
989                                 security_supported |= NEG_SIGN;
990                         }
991                         if (security_supported == 0) {
992                                 /* If we don't support anything, this must be 0 */
993                                 RSIVAL(maxlength_proposed, 0, 0x0);
994                         }
995
996                         /* TODO:  We may not wish to support this */
997                         security_supported |= NEG_NONE;
998                         maxlength_proposed[0] = security_supported;
999                         
1000                         input_token.value = maxlength_proposed;
1001                         input_token.length = sizeof(maxlength_proposed);
1002
1003                         maj_stat = gss_wrap(&min_stat, 
1004                                             gensec_gssapi_state->gssapi_context, 
1005                                             false,
1006                                             GSS_C_QOP_DEFAULT,
1007                                             &input_token,
1008                                             &conf_state,
1009                                             &output_token);
1010                         if (GSS_ERROR(maj_stat)) {
1011                                 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", 
1012                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1013                                 return NT_STATUS_ACCESS_DENIED;
1014                         }
1015                         
1016                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
1017                         gss_release_buffer(&min_stat, &output_token);
1018
1019                         gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_ACCEPT;
1020                         return NT_STATUS_MORE_PROCESSING_REQUIRED;
1021                 }
1022                 default:
1023                         return NT_STATUS_INVALID_PARAMETER;
1024                         
1025                 }
1026         }
1027         /* This is s server-only stage */
1028         case STAGE_SASL_SSF_ACCEPT:
1029         {
1030                 uint8_t maxlength_accepted[4]; 
1031                 uint8_t security_accepted;
1032                 int conf_state;
1033                 gss_qop_t qop_state;
1034                 input_token.length = in.length;
1035                 input_token.value = in.data;
1036                         
1037                 maj_stat = gss_unwrap(&min_stat, 
1038                                       gensec_gssapi_state->gssapi_context, 
1039                                       &input_token,
1040                                       &output_token, 
1041                                       &conf_state,
1042                                       &qop_state);
1043                 if (GSS_ERROR(maj_stat)) {
1044                         DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n", 
1045                                   gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1046                         return NT_STATUS_ACCESS_DENIED;
1047                 }
1048                         
1049                 if (output_token.length < 4) {
1050                         gss_release_buffer(&min_stat, &output_token);
1051                         return NT_STATUS_INVALID_PARAMETER;
1052                 }
1053
1054                 memcpy(maxlength_accepted, output_token.value, 4);
1055                 gss_release_buffer(&min_stat, &output_token);
1056                 
1057                 /* first byte is the proposed security */
1058                 security_accepted = maxlength_accepted[0];
1059                 maxlength_accepted[0] = '\0';
1060
1061                 /* Rest is the proposed max wrap length */
1062                 gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_accepted, 0), 
1063                                                              gensec_gssapi_state->max_wrap_buf_size);
1064
1065                 gensec_gssapi_state->sasl_protection = 0;
1066                 if (security_accepted & NEG_SEAL) {
1067                         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
1068                                 DEBUG(1, ("Remote client wanted seal, but gensec refused\n"));
1069                                 return NT_STATUS_ACCESS_DENIED;
1070                         }
1071                         gensec_gssapi_state->sasl_protection |= NEG_SEAL;
1072                 }
1073                 if (security_accepted & NEG_SIGN) {
1074                         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
1075                                 DEBUG(1, ("Remote client wanted sign, but gensec refused\n"));
1076                                 return NT_STATUS_ACCESS_DENIED;
1077                         }
1078                         gensec_gssapi_state->sasl_protection |= NEG_SIGN;
1079                 }
1080                 if (security_accepted & NEG_NONE) {
1081                         gensec_gssapi_state->sasl_protection |= NEG_NONE;
1082                 }
1083
1084                 /* quirk:  This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
1085                 gensec_gssapi_state->sasl_state = STAGE_DONE;
1086                 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
1087                         DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically sealed\n"));
1088                 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
1089                         DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically signed\n"));
1090                 } else {
1091                         DEBUG(5, ("SASL/GSSAPI Connection from client will have no cryptographic protection\n"));
1092                 }
1093
1094                 *out = data_blob(NULL, 0);
1095                 return NT_STATUS_OK;    
1096         }
1097         default:
1098                 return NT_STATUS_INVALID_PARAMETER;
1099         }
1100 }
1101
1102 struct gensec_gssapi_update_state {
1103         NTSTATUS status;
1104         DATA_BLOB out;
1105 };
1106
1107 static struct tevent_req *gensec_gssapi_update_send(TALLOC_CTX *mem_ctx,
1108                                                     struct tevent_context *ev,
1109                                                     struct gensec_security *gensec_security,
1110                                                     const DATA_BLOB in)
1111 {
1112         struct tevent_req *req = NULL;
1113         struct gensec_gssapi_update_state *state = NULL;
1114         NTSTATUS status;
1115
1116         req = tevent_req_create(mem_ctx, &state,
1117                                 struct gensec_gssapi_update_state);
1118         if (req == NULL) {
1119                 return NULL;
1120         }
1121
1122         status = gensec_gssapi_update_internal(gensec_security,
1123                                                state, ev, in,
1124                                                &state->out);
1125         state->status = status;
1126         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1127                 tevent_req_done(req);
1128                 return tevent_req_post(req, ev);
1129         }
1130         if (tevent_req_nterror(req, status)) {
1131                 return tevent_req_post(req, ev);
1132         }
1133
1134         tevent_req_done(req);
1135         return tevent_req_post(req, ev);
1136 }
1137
1138 static NTSTATUS gensec_gssapi_update_recv(struct tevent_req *req,
1139                                           TALLOC_CTX *out_mem_ctx,
1140                                           DATA_BLOB *out)
1141 {
1142         struct gensec_gssapi_update_state *state =
1143                 tevent_req_data(req,
1144                 struct gensec_gssapi_update_state);
1145         NTSTATUS status;
1146
1147         *out = data_blob_null;
1148
1149         if (tevent_req_is_nterror(req, &status)) {
1150                 tevent_req_received(req);
1151                 return status;
1152         }
1153
1154         *out = state->out;
1155         talloc_steal(out_mem_ctx, state->out.data);
1156         status = state->status;
1157         tevent_req_received(req);
1158         return status;
1159 }
1160
1161 static NTSTATUS gensec_gssapi_wrap(struct gensec_security *gensec_security, 
1162                                    TALLOC_CTX *mem_ctx, 
1163                                    const DATA_BLOB *in, 
1164                                    DATA_BLOB *out)
1165 {
1166         struct gensec_gssapi_state *gensec_gssapi_state
1167                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1168         OM_uint32 maj_stat, min_stat;
1169         gss_buffer_desc input_token, output_token;
1170         int conf_state;
1171         input_token.length = in->length;
1172         input_token.value = in->data;
1173
1174         maj_stat = gss_wrap(&min_stat, 
1175                             gensec_gssapi_state->gssapi_context, 
1176                             gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
1177                             GSS_C_QOP_DEFAULT,
1178                             &input_token,
1179                             &conf_state,
1180                             &output_token);
1181         if (GSS_ERROR(maj_stat)) {
1182                 DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n", 
1183                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1184                 return NT_STATUS_ACCESS_DENIED;
1185         }
1186
1187         *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
1188         gss_release_buffer(&min_stat, &output_token);
1189
1190         if (gensec_gssapi_state->sasl) {
1191                 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
1192                 if (max_wrapped_size < out->length) {
1193                         DEBUG(1, ("gensec_gssapi_wrap: when wrapped, INPUT data (%u) is grew to be larger than SASL negotiated maximum output size (%u > %u)\n",
1194                                   (unsigned)in->length, 
1195                                   (unsigned)out->length, 
1196                                   (unsigned int)max_wrapped_size));
1197                         return NT_STATUS_INVALID_PARAMETER;
1198                 }
1199         }
1200         
1201         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1202             && !conf_state) {
1203                 return NT_STATUS_ACCESS_DENIED;
1204         }
1205         return NT_STATUS_OK;
1206 }
1207
1208 static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security, 
1209                                      TALLOC_CTX *mem_ctx, 
1210                                      const DATA_BLOB *in, 
1211                                      DATA_BLOB *out)
1212 {
1213         struct gensec_gssapi_state *gensec_gssapi_state
1214                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1215         OM_uint32 maj_stat, min_stat;
1216         gss_buffer_desc input_token, output_token;
1217         int conf_state;
1218         gss_qop_t qop_state;
1219         input_token.length = in->length;
1220         input_token.value = in->data;
1221         
1222         if (gensec_gssapi_state->sasl) {
1223                 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
1224                 if (max_wrapped_size < in->length) {
1225                         DEBUG(1, ("gensec_gssapi_unwrap: WRAPPED data is larger than SASL negotiated maximum size\n"));
1226                         return NT_STATUS_INVALID_PARAMETER;
1227                 }
1228         }
1229         
1230         /*
1231          * FIXME: input_message_buffer is marked const, but gss_unwrap() may
1232          * modify it (see calls to rrc_rotate() in _gssapi_unwrap_cfx()).
1233          */
1234         maj_stat = gss_unwrap(&min_stat, 
1235                               gensec_gssapi_state->gssapi_context, 
1236                               &input_token,
1237                               &output_token, 
1238                               &conf_state,
1239                               &qop_state);
1240         if (GSS_ERROR(maj_stat)) {
1241                 DEBUG(1, ("gensec_gssapi_unwrap: GSS UnWrap failed: %s\n", 
1242                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1243                 return NT_STATUS_ACCESS_DENIED;
1244         }
1245
1246         *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
1247         gss_release_buffer(&min_stat, &output_token);
1248         
1249         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1250             && !conf_state) {
1251                 return NT_STATUS_ACCESS_DENIED;
1252         }
1253         return NT_STATUS_OK;
1254 }
1255
1256 /* Find out the maximum input size negotiated on this connection */
1257
1258 static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security) 
1259 {
1260         struct gensec_gssapi_state *gensec_gssapi_state
1261                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1262         OM_uint32 maj_stat, min_stat;
1263         OM_uint32 max_input_size;
1264
1265         maj_stat = gss_wrap_size_limit(&min_stat, 
1266                                        gensec_gssapi_state->gssapi_context,
1267                                        gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
1268                                        GSS_C_QOP_DEFAULT,
1269                                        gensec_gssapi_state->max_wrap_buf_size,
1270                                        &max_input_size);
1271         if (GSS_ERROR(maj_stat)) {
1272                 TALLOC_CTX *mem_ctx = talloc_new(NULL); 
1273                 DEBUG(1, ("gensec_gssapi_max_input_size: determining signature size with gss_wrap_size_limit failed: %s\n",
1274                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1275                 talloc_free(mem_ctx);
1276                 return 0;
1277         }
1278
1279         return max_input_size;
1280 }
1281
1282 /* Find out the maximum output size negotiated on this connection */
1283 static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security) 
1284 {
1285         struct gensec_gssapi_state *gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);;
1286         return gensec_gssapi_state->max_wrap_buf_size;
1287 }
1288
1289 static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security, 
1290                                           TALLOC_CTX *mem_ctx, 
1291                                           uint8_t *data, size_t length, 
1292                                           const uint8_t *whole_pdu, size_t pdu_length, 
1293                                           DATA_BLOB *sig)
1294 {
1295         struct gensec_gssapi_state *gensec_gssapi_state
1296                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1297         bool hdr_signing = false;
1298         size_t sig_size = 0;
1299         NTSTATUS status;
1300
1301         if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1302                 hdr_signing = true;
1303         }
1304
1305         sig_size = gensec_gssapi_sig_size(gensec_security, length);
1306
1307         status = gssapi_seal_packet(gensec_gssapi_state->gssapi_context,
1308                                     gensec_gssapi_state->gss_oid,
1309                                     hdr_signing, sig_size,
1310                                     data, length,
1311                                     whole_pdu, pdu_length,
1312                                     mem_ctx, sig);
1313         if (!NT_STATUS_IS_OK(status)) {
1314                 DEBUG(0, ("gssapi_seal_packet(hdr_signing=%u,sig_size=%zu,"
1315                           "data=%zu,pdu=%zu) failed: %s\n",
1316                           hdr_signing, sig_size, length, pdu_length,
1317                           nt_errstr(status)));
1318                 return status;
1319         }
1320
1321         return NT_STATUS_OK;
1322 }
1323
1324 static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security, 
1325                                             uint8_t *data, size_t length, 
1326                                             const uint8_t *whole_pdu, size_t pdu_length,
1327                                             const DATA_BLOB *sig)
1328 {
1329         struct gensec_gssapi_state *gensec_gssapi_state
1330                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1331         bool hdr_signing = false;
1332         NTSTATUS status;
1333
1334         if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1335                 hdr_signing = true;
1336         }
1337
1338         status = gssapi_unseal_packet(gensec_gssapi_state->gssapi_context,
1339                                       gensec_gssapi_state->gss_oid,
1340                                       hdr_signing,
1341                                       data, length,
1342                                       whole_pdu, pdu_length,
1343                                       sig);
1344         if (!NT_STATUS_IS_OK(status)) {
1345                 DEBUG(0, ("gssapi_unseal_packet(hdr_signing=%u,sig_size=%zu,"
1346                           "data=%zu,pdu=%zu) failed: %s\n",
1347                           hdr_signing, sig->length, length, pdu_length,
1348                           nt_errstr(status)));
1349                 return status;
1350         }
1351
1352         return NT_STATUS_OK;
1353 }
1354
1355 static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_security, 
1356                                           TALLOC_CTX *mem_ctx, 
1357                                           const uint8_t *data, size_t length, 
1358                                           const uint8_t *whole_pdu, size_t pdu_length, 
1359                                           DATA_BLOB *sig)
1360 {
1361         struct gensec_gssapi_state *gensec_gssapi_state
1362                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1363         bool hdr_signing = false;
1364         NTSTATUS status;
1365
1366         if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1367                 hdr_signing = true;
1368         }
1369
1370         status = gssapi_sign_packet(gensec_gssapi_state->gssapi_context,
1371                                     gensec_gssapi_state->gss_oid,
1372                                     hdr_signing,
1373                                     data, length,
1374                                     whole_pdu, pdu_length,
1375                                     mem_ctx, sig);
1376         if (!NT_STATUS_IS_OK(status)) {
1377                 DEBUG(0, ("gssapi_sign_packet(hdr_signing=%u,"
1378                           "data=%zu,pdu=%zu) failed: %s\n",
1379                           hdr_signing, length, pdu_length,
1380                           nt_errstr(status)));
1381                 return status;
1382         }
1383
1384         return NT_STATUS_OK;
1385 }
1386
1387 static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security, 
1388                                            const uint8_t *data, size_t length, 
1389                                            const uint8_t *whole_pdu, size_t pdu_length, 
1390                                            const DATA_BLOB *sig)
1391 {
1392         struct gensec_gssapi_state *gensec_gssapi_state
1393                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1394         bool hdr_signing = false;
1395         NTSTATUS status;
1396
1397         if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1398                 hdr_signing = true;
1399         }
1400
1401         status = gssapi_check_packet(gensec_gssapi_state->gssapi_context,
1402                                      gensec_gssapi_state->gss_oid,
1403                                      hdr_signing,
1404                                      data, length,
1405                                      whole_pdu, pdu_length,
1406                                      sig);
1407         if (!NT_STATUS_IS_OK(status)) {
1408                 DEBUG(0, ("gssapi_check_packet(hdr_signing=%u,sig_size=%zu,"
1409                           "data=%zu,pdu=%zu) failed: %s\n",
1410                           hdr_signing, sig->length, length, pdu_length,
1411                           nt_errstr(status)));
1412                 return status;
1413         }
1414
1415         return NT_STATUS_OK;
1416 }
1417
1418 /* Try to figure out what features we actually got on the connection */
1419 static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security, 
1420                                        uint32_t feature) 
1421 {
1422         struct gensec_gssapi_state *gensec_gssapi_state
1423                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1424         if (feature & GENSEC_FEATURE_SIGN) {
1425                 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1426                 if (gensec_gssapi_state->sasl 
1427                     && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1428                         return ((gensec_gssapi_state->sasl_protection & NEG_SIGN) 
1429                                 && (gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG));
1430                 }
1431                 return gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG;
1432         }
1433         if (feature & GENSEC_FEATURE_SEAL) {
1434                 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1435                 if (gensec_gssapi_state->sasl 
1436                     && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1437                         return ((gensec_gssapi_state->sasl_protection & NEG_SEAL) 
1438                                  && (gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG));
1439                 }
1440                 return gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG;
1441         }
1442         if (feature & GENSEC_FEATURE_SESSION_KEY) {
1443                 /* Only for GSSAPI/Krb5 */
1444                 if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
1445                                       gss_mech_krb5)) {
1446                         return true;
1447                 }
1448         }
1449         if (feature & GENSEC_FEATURE_DCE_STYLE) {
1450                 return gensec_gssapi_state->gss_got_flags & GSS_C_DCE_STYLE;
1451         }
1452         if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
1453                 NTSTATUS status;
1454                 uint32_t keytype;
1455
1456                 if (!(gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG)) {
1457                         return false;
1458                 }
1459
1460                 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "force_new_spnego", false)) {
1461                         return true;
1462                 }
1463                 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "disable_new_spnego", false)) {
1464                         return false;
1465                 }
1466
1467                 status = gssapi_get_session_key(gensec_gssapi_state,
1468                                                 gensec_gssapi_state->gssapi_context, NULL, &keytype);
1469                 /* 
1470                  * We should do a proper sig on the mechListMic unless
1471                  * we know we have to be backwards compatible with
1472                  * earlier windows versions.  
1473                  * 
1474                  * Negotiating a non-krb5
1475                  * mech for example should be regarded as having
1476                  * NEW_SPNEGO
1477                  */
1478                 if (NT_STATUS_IS_OK(status)) {
1479                         switch (keytype) {
1480                         case ENCTYPE_DES_CBC_CRC:
1481                         case ENCTYPE_DES_CBC_MD5:
1482                         case ENCTYPE_ARCFOUR_HMAC:
1483                         case ENCTYPE_DES3_CBC_SHA1:
1484                                 return false;
1485                         }
1486                 }
1487                 return true;
1488         }
1489         /* We can always do async (rather than strict request/reply) packets.  */
1490         if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
1491                 return true;
1492         }
1493         if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1494                 return true;
1495         }
1496         return false;
1497 }
1498
1499 static NTTIME gensec_gssapi_expire_time(struct gensec_security *gensec_security)
1500 {
1501         struct gensec_gssapi_state *gensec_gssapi_state =
1502                 talloc_get_type_abort(gensec_security->private_data,
1503                 struct gensec_gssapi_state);
1504
1505         return gensec_gssapi_state->expire_time;
1506 }
1507
1508 /*
1509  * Extract the 'session key' needed by SMB signing and ncacn_np
1510  * (for encrypting some passwords).
1511  * 
1512  * This breaks all the abstractions, but what do you expect...
1513  */
1514 static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security, 
1515                                           TALLOC_CTX *mem_ctx,
1516                                           DATA_BLOB *session_key) 
1517 {
1518         struct gensec_gssapi_state *gensec_gssapi_state
1519                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1520         return gssapi_get_session_key(mem_ctx, gensec_gssapi_state->gssapi_context, session_key, NULL);
1521 }
1522
1523 /* Get some basic (and authorization) information about the user on
1524  * this session.  This uses either the PAC (if present) or a local
1525  * database lookup */
1526 static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
1527                                            TALLOC_CTX *mem_ctx,
1528                                            struct auth_session_info **_session_info) 
1529 {
1530         NTSTATUS nt_status;
1531         TALLOC_CTX *tmp_ctx;
1532         struct gensec_gssapi_state *gensec_gssapi_state
1533                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1534         struct auth_session_info *session_info = NULL;
1535         OM_uint32 maj_stat, min_stat;
1536         DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
1537
1538         gss_buffer_desc name_token;
1539         char *principal_string;
1540         
1541         tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
1542         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1543
1544         maj_stat = gss_display_name (&min_stat,
1545                                      gensec_gssapi_state->client_name,
1546                                      &name_token,
1547                                      NULL);
1548         if (GSS_ERROR(maj_stat)) {
1549                 DEBUG(1, ("GSS display_name failed: %s\n",
1550                           gssapi_error_string(tmp_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1551                 talloc_free(tmp_ctx);
1552                 return NT_STATUS_FOOBAR;
1553         }
1554
1555         principal_string = talloc_strndup(tmp_ctx,
1556                                           (const char *)name_token.value,
1557                                           name_token.length);
1558
1559         gss_release_buffer(&min_stat, &name_token);
1560
1561         if (!principal_string) {
1562                 talloc_free(tmp_ctx);
1563                 return NT_STATUS_NO_MEMORY;
1564         }
1565
1566         nt_status = gssapi_obtain_pac_blob(tmp_ctx,  gensec_gssapi_state->gssapi_context,
1567                                            gensec_gssapi_state->client_name,
1568                                            &pac_blob);
1569         
1570         /* IF we have the PAC - otherwise we need to get this
1571          * data from elsewhere - local ldb, or (TODO) lookup of some
1572          * kind... 
1573          */
1574         if (NT_STATUS_IS_OK(nt_status)) {
1575                 pac_blob_ptr = &pac_blob;
1576         }
1577         nt_status = gensec_generate_session_info_pac(tmp_ctx,
1578                                                      gensec_security,
1579                                                      gensec_gssapi_state->smb_krb5_context,
1580                                                      pac_blob_ptr, principal_string,
1581                                                      gensec_get_remote_address(gensec_security),
1582                                                      &session_info);
1583         if (!NT_STATUS_IS_OK(nt_status)) {
1584                 talloc_free(tmp_ctx);
1585                 return nt_status;
1586         }
1587
1588         nt_status = gensec_gssapi_session_key(gensec_security, session_info, &session_info->session_key);
1589         if (!NT_STATUS_IS_OK(nt_status)) {
1590                 talloc_free(tmp_ctx);
1591                 return nt_status;
1592         }
1593
1594         if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG &&
1595             gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
1596                 krb5_error_code ret;
1597                 const char *error_string;
1598
1599                 DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));
1600
1601                 /*
1602                  * Create anonymous credentials for now.
1603                  *
1604                  * We will update them with the provided client gss creds.
1605                  */
1606                 session_info->credentials = cli_credentials_init_anon(session_info);
1607                 if (session_info->credentials == NULL) {
1608                         talloc_free(tmp_ctx);
1609                         return NT_STATUS_NO_MEMORY;
1610                 }
1611
1612                 ret = cli_credentials_set_client_gss_creds(session_info->credentials, 
1613                                                            gensec_security->settings->lp_ctx,
1614                                                            gensec_gssapi_state->delegated_cred_handle,
1615                                                            CRED_SPECIFIED, &error_string);
1616                 if (ret) {
1617                         talloc_free(tmp_ctx);
1618                         DEBUG(2,("Failed to get gss creds: %s\n", error_string));
1619                         return NT_STATUS_NO_MEMORY;
1620                 }
1621                 
1622                 /* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */
1623                 cli_credentials_set_kerberos_state(session_info->credentials,
1624                                                    CRED_USE_KERBEROS_REQUIRED,
1625                                                    CRED_SPECIFIED);
1626
1627                 /* It has been taken from this place... */
1628                 gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
1629         } else {
1630                 DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n"));
1631         }
1632
1633         *_session_info = talloc_steal(mem_ctx, session_info);
1634         talloc_free(tmp_ctx);
1635
1636         return NT_STATUS_OK;
1637 }
1638
1639 static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size)
1640 {
1641         struct gensec_gssapi_state *gensec_gssapi_state
1642                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1643         size_t sig_size;
1644
1645         if (gensec_gssapi_state->sig_size > 0) {
1646                 return gensec_gssapi_state->sig_size;
1647         }
1648
1649         sig_size = gssapi_get_sig_size(gensec_gssapi_state->gssapi_context,
1650                                        gensec_gssapi_state->gss_oid,
1651                                        gensec_gssapi_state->gss_got_flags,
1652                                        data_size);
1653
1654         gensec_gssapi_state->sig_size = sig_size;
1655         return gensec_gssapi_state->sig_size;
1656 }
1657
1658 static const char *gensec_gssapi_final_auth_type(struct gensec_security *gensec_security)
1659 {
1660         struct gensec_gssapi_state *gensec_gssapi_state
1661                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1662         /* Only return the string for GSSAPI/Krb5 */
1663         if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
1664                               gss_mech_krb5)) {
1665                 return GENSEC_FINAL_AUTH_TYPE_KRB5;
1666         } else {
1667                 return "gensec_gssapi: UNKNOWN MECH";
1668         }
1669 }
1670
1671 static const char *gensec_gssapi_krb5_oids[] = { 
1672         GENSEC_OID_KERBEROS5_OLD,
1673         GENSEC_OID_KERBEROS5,
1674         NULL 
1675 };
1676
1677 static const char *gensec_gssapi_spnego_oids[] = { 
1678         GENSEC_OID_SPNEGO,
1679         NULL 
1680 };
1681
1682 /* As a server, this could in theory accept any GSSAPI mech */
1683 static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
1684         .name           = "gssapi_spnego",
1685         .sasl_name      = "GSS-SPNEGO",
1686         .auth_type      = DCERPC_AUTH_TYPE_SPNEGO,
1687         .oid            = gensec_gssapi_spnego_oids,
1688         .client_start   = gensec_gssapi_client_start,
1689         .server_start   = gensec_gssapi_server_start,
1690         .magic          = gensec_magic_check_krb5_oid,
1691         .update_send    = gensec_gssapi_update_send,
1692         .update_recv    = gensec_gssapi_update_recv,
1693         .session_key    = gensec_gssapi_session_key,
1694         .session_info   = gensec_gssapi_session_info,
1695         .sign_packet    = gensec_gssapi_sign_packet,
1696         .check_packet   = gensec_gssapi_check_packet,
1697         .seal_packet    = gensec_gssapi_seal_packet,
1698         .unseal_packet  = gensec_gssapi_unseal_packet,
1699         .max_input_size   = gensec_gssapi_max_input_size,
1700         .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1701         .wrap           = gensec_gssapi_wrap,
1702         .unwrap         = gensec_gssapi_unwrap,
1703         .have_feature   = gensec_gssapi_have_feature,
1704         .expire_time    = gensec_gssapi_expire_time,
1705         .final_auth_type = gensec_gssapi_final_auth_type,
1706         .enabled        = false,
1707         .kerberos       = true,
1708         .priority       = GENSEC_GSSAPI
1709 };
1710
1711 /* As a server, this could in theory accept any GSSAPI mech */
1712 static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
1713         .name           = "gssapi_krb5",
1714         .auth_type      = DCERPC_AUTH_TYPE_KRB5,
1715         .oid            = gensec_gssapi_krb5_oids,
1716         .client_start   = gensec_gssapi_client_start,
1717         .server_start   = gensec_gssapi_server_start,
1718         .magic          = gensec_magic_check_krb5_oid,
1719         .update_send    = gensec_gssapi_update_send,
1720         .update_recv    = gensec_gssapi_update_recv,
1721         .session_key    = gensec_gssapi_session_key,
1722         .session_info   = gensec_gssapi_session_info,
1723         .sig_size       = gensec_gssapi_sig_size,
1724         .sign_packet    = gensec_gssapi_sign_packet,
1725         .check_packet   = gensec_gssapi_check_packet,
1726         .seal_packet    = gensec_gssapi_seal_packet,
1727         .unseal_packet  = gensec_gssapi_unseal_packet,
1728         .max_input_size   = gensec_gssapi_max_input_size,
1729         .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1730         .wrap           = gensec_gssapi_wrap,
1731         .unwrap         = gensec_gssapi_unwrap,
1732         .have_feature   = gensec_gssapi_have_feature,
1733         .expire_time    = gensec_gssapi_expire_time,
1734         .final_auth_type = gensec_gssapi_final_auth_type,
1735         .enabled        = true,
1736         .kerberos       = true,
1737         .priority       = GENSEC_GSSAPI
1738 };
1739
1740 /* As a server, this could in theory accept any GSSAPI mech */
1741 static const struct gensec_security_ops gensec_gssapi_sasl_krb5_security_ops = {
1742         .name             = "gssapi_krb5_sasl",
1743         .sasl_name        = "GSSAPI",
1744         .client_start     = gensec_gssapi_sasl_client_start,
1745         .server_start     = gensec_gssapi_sasl_server_start,
1746         .update_send      = gensec_gssapi_update_send,
1747         .update_recv      = gensec_gssapi_update_recv,
1748         .session_key      = gensec_gssapi_session_key,
1749         .session_info     = gensec_gssapi_session_info,
1750         .max_input_size   = gensec_gssapi_max_input_size,
1751         .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1752         .wrap             = gensec_gssapi_wrap,
1753         .unwrap           = gensec_gssapi_unwrap,
1754         .have_feature     = gensec_gssapi_have_feature,
1755         .expire_time      = gensec_gssapi_expire_time,
1756         .final_auth_type = gensec_gssapi_final_auth_type,
1757         .enabled          = true,
1758         .kerberos         = true,
1759         .priority         = GENSEC_GSSAPI
1760 };
1761
1762 _PUBLIC_ NTSTATUS gensec_gssapi_init(TALLOC_CTX *ctx)
1763 {
1764         NTSTATUS ret;
1765
1766         ret = gensec_register(ctx, &gensec_gssapi_spnego_security_ops);
1767         if (!NT_STATUS_IS_OK(ret)) {
1768                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1769                         gensec_gssapi_spnego_security_ops.name));
1770                 return ret;
1771         }
1772
1773         ret = gensec_register(ctx, &gensec_gssapi_krb5_security_ops);
1774         if (!NT_STATUS_IS_OK(ret)) {
1775                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1776                         gensec_gssapi_krb5_security_ops.name));
1777                 return ret;
1778         }
1779
1780         ret = gensec_register(ctx, &gensec_gssapi_sasl_krb5_security_ops);
1781         if (!NT_STATUS_IS_OK(ret)) {
1782                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1783                         gensec_gssapi_sasl_krb5_security_ops.name));
1784                 return ret;
1785         }
1786
1787         return ret;
1788 }