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