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