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