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