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