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