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