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