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