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