gse: Use the smb_gss_oid_equal wrapper.
[samba.git] / source3 / librpc / crypto / gse.c
1 /*
2  *  GSSAPI Security Extensions
3  *  RPC Pipe client and server routines
4  *  Copyright (C) Simo Sorce 2010.
5  *  Copyright (C) Andrew Bartlett 2004-2011.
6  *  Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /* We support only GSSAPI/KRB5 here */
23
24 #include "includes.h"
25 #include "gse.h"
26 #include "libads/kerberos_proto.h"
27 #include "auth/common_auth.h"
28 #include "auth/gensec/gensec.h"
29 #include "auth/credentials/credentials.h"
30 #include "../librpc/gen_ndr/dcerpc.h"
31
32 #if defined(HAVE_KRB5)
33
34 #include "auth/kerberos/pac_utils.h"
35 #include "gse_krb5.h"
36
37 static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min);
38
39 struct gse_context {
40         gss_ctx_id_t gssapi_context;
41         gss_name_t server_name;
42         gss_name_t client_name;
43         OM_uint32 gss_want_flags, gss_got_flags;
44
45         gss_cred_id_t delegated_cred_handle;
46
47         NTTIME expire_time;
48
49         /* gensec_gse only */
50         krb5_context k5ctx;
51         krb5_ccache ccache;
52         krb5_keytab keytab;
53
54         gss_OID_desc gss_mech;
55         gss_cred_id_t creds;
56
57         gss_OID ret_mech;
58 };
59
60 /* free non talloc dependent contexts */
61 static int gse_context_destructor(void *ptr)
62 {
63         struct gse_context *gse_ctx;
64         OM_uint32 gss_min;
65
66         gse_ctx = talloc_get_type_abort(ptr, struct gse_context);
67         if (gse_ctx->k5ctx) {
68                 if (gse_ctx->ccache) {
69                         krb5_cc_close(gse_ctx->k5ctx, gse_ctx->ccache);
70                         gse_ctx->ccache = NULL;
71                 }
72                 if (gse_ctx->keytab) {
73                         krb5_kt_close(gse_ctx->k5ctx, gse_ctx->keytab);
74                         gse_ctx->keytab = NULL;
75                 }
76                 krb5_free_context(gse_ctx->k5ctx);
77                 gse_ctx->k5ctx = NULL;
78         }
79         if (gse_ctx->gssapi_context != GSS_C_NO_CONTEXT) {
80                 (void)gss_delete_sec_context(&gss_min,
81                                                  &gse_ctx->gssapi_context,
82                                                  GSS_C_NO_BUFFER);
83         }
84         if (gse_ctx->server_name) {
85                 (void)gss_release_name(&gss_min,
86                                            &gse_ctx->server_name);
87         }
88         if (gse_ctx->client_name) {
89                 (void)gss_release_name(&gss_min,
90                                            &gse_ctx->client_name);
91         }
92         if (gse_ctx->creds) {
93                 (void)gss_release_cred(&gss_min,
94                                            &gse_ctx->creds);
95         }
96         if (gse_ctx->delegated_cred_handle) {
97                 (void)gss_release_cred(&gss_min,
98                                            &gse_ctx->delegated_cred_handle);
99         }
100
101         /* MIT and Heimdal differ as to if you can call
102          * gss_release_oid() on this OID, generated by
103          * gss_{accept,init}_sec_context().  However, as long as the
104          * oid is gss_mech_krb5 (which it always is at the moment),
105          * then this is a moot point, as both declare this particular
106          * OID static, and so no memory is lost.  This assert is in
107          * place to ensure that the programmer who wishes to extend
108          * this code to EAP or other GSS mechanisms determines an
109          * implementation-dependent way of releasing any dynamically
110          * allocated OID */
111         SMB_ASSERT(smb_gss_oid_equal(&gse_ctx->gss_mech, GSS_C_NO_OID) ||
112                    smb_gss_oid_equal(&gse_ctx->gss_mech, gss_mech_krb5));
113
114         return 0;
115 }
116
117 static NTSTATUS gse_context_init(TALLOC_CTX *mem_ctx,
118                                  bool do_sign, bool do_seal,
119                                  const char *ccache_name,
120                                  uint32_t add_gss_c_flags,
121                                  struct gse_context **_gse_ctx)
122 {
123         struct gse_context *gse_ctx;
124         krb5_error_code k5ret;
125         NTSTATUS status;
126
127         gse_ctx = talloc_zero(mem_ctx, struct gse_context);
128         if (!gse_ctx) {
129                 return NT_STATUS_NO_MEMORY;
130         }
131         talloc_set_destructor((TALLOC_CTX *)gse_ctx, gse_context_destructor);
132
133         gse_ctx->expire_time = GENSEC_EXPIRE_TIME_INFINITY;
134
135         memcpy(&gse_ctx->gss_mech, gss_mech_krb5, sizeof(gss_OID_desc));
136
137         gse_ctx->gss_want_flags = GSS_C_MUTUAL_FLAG |
138                                 GSS_C_DELEG_FLAG |
139                                 GSS_C_DELEG_POLICY_FLAG |
140                                 GSS_C_REPLAY_FLAG |
141                                 GSS_C_SEQUENCE_FLAG;
142         if (do_sign) {
143                 gse_ctx->gss_want_flags |= GSS_C_INTEG_FLAG;
144         }
145         if (do_seal) {
146                 gse_ctx->gss_want_flags |= GSS_C_INTEG_FLAG;
147                 gse_ctx->gss_want_flags |= GSS_C_CONF_FLAG;
148         }
149
150         gse_ctx->gss_want_flags |= add_gss_c_flags;
151
152         /* Initialize Kerberos Context */
153         initialize_krb5_error_table();
154
155         k5ret = krb5_init_context(&gse_ctx->k5ctx);
156         if (k5ret) {
157                 DEBUG(0, ("Failed to initialize kerberos context! (%s)\n",
158                           error_message(k5ret)));
159                 status = NT_STATUS_INTERNAL_ERROR;
160                 goto err_out;
161         }
162
163         if (!ccache_name) {
164                 ccache_name = krb5_cc_default_name(gse_ctx->k5ctx);
165         }
166         k5ret = krb5_cc_resolve(gse_ctx->k5ctx, ccache_name,
167                                 &gse_ctx->ccache);
168         if (k5ret) {
169                 DEBUG(1, ("Failed to resolve credential cache! (%s)\n",
170                           error_message(k5ret)));
171                 status = NT_STATUS_INTERNAL_ERROR;
172                 goto err_out;
173         }
174
175         /* TODO: Should we enforce a enc_types list ?
176         ret = krb5_set_default_tgs_ktypes(gse_ctx->k5ctx, enc_types);
177         */
178
179         *_gse_ctx = gse_ctx;
180         return NT_STATUS_OK;
181
182 err_out:
183         TALLOC_FREE(gse_ctx);
184         return status;
185 }
186
187 static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
188                                 bool do_sign, bool do_seal,
189                                 const char *ccache_name,
190                                 const char *server,
191                                 const char *service,
192                                 const char *username,
193                                 const char *password,
194                                 uint32_t add_gss_c_flags,
195                                 struct gse_context **_gse_ctx)
196 {
197         struct gse_context *gse_ctx;
198         OM_uint32 gss_maj, gss_min;
199         gss_buffer_desc name_buffer = {0, NULL};
200         gss_OID_set_desc mech_set;
201         NTSTATUS status;
202
203         if (!server || !service) {
204                 return NT_STATUS_INVALID_PARAMETER;
205         }
206
207         status = gse_context_init(mem_ctx, do_sign, do_seal,
208                                   ccache_name, add_gss_c_flags,
209                                   &gse_ctx);
210         if (!NT_STATUS_IS_OK(status)) {
211                 return NT_STATUS_NO_MEMORY;
212         }
213
214         /* Guess the realm based on the supplied service, and avoid the GSS libs
215            doing DNS lookups which may fail.
216
217            TODO: Loop with the KDC on some more combinations (local
218            realm in particular), possibly falling back to
219            GSS_C_NT_HOSTBASED_SERVICE
220         */
221         name_buffer.value = kerberos_get_principal_from_service_hostname(
222                                         gse_ctx, service, server, lp_realm());
223         if (!name_buffer.value) {
224                 status = NT_STATUS_NO_MEMORY;
225                 goto err_out;
226         }
227         name_buffer.length = strlen((char *)name_buffer.value);
228         gss_maj = gss_import_name(&gss_min, &name_buffer,
229                                   GSS_C_NT_USER_NAME,
230                                   &gse_ctx->server_name);
231         if (gss_maj) {
232                 DEBUG(0, ("gss_import_name failed for %s, with [%s]\n",
233                           (char *)name_buffer.value,
234                           gse_errstr(gse_ctx, gss_maj, gss_min)));
235                 status = NT_STATUS_INTERNAL_ERROR;
236                 goto err_out;
237         }
238
239         /* TODO: get krb5 ticket using username/password, if no valid
240          * one already available in ccache */
241
242         mech_set.count = 1;
243         mech_set.elements = &gse_ctx->gss_mech;
244
245         gss_maj = gss_acquire_cred(&gss_min,
246                                    GSS_C_NO_NAME,
247                                    GSS_C_INDEFINITE,
248                                    &mech_set,
249                                    GSS_C_INITIATE,
250                                    &gse_ctx->creds,
251                                    NULL, NULL);
252         if (gss_maj) {
253                 DEBUG(0, ("gss_acquire_creds failed for %s, with [%s]\n",
254                           (char *)name_buffer.value,
255                           gse_errstr(gse_ctx, gss_maj, gss_min)));
256                 status = NT_STATUS_INTERNAL_ERROR;
257                 goto err_out;
258         }
259
260         *_gse_ctx = gse_ctx;
261         TALLOC_FREE(name_buffer.value);
262         return NT_STATUS_OK;
263
264 err_out:
265         TALLOC_FREE(name_buffer.value);
266         TALLOC_FREE(gse_ctx);
267         return status;
268 }
269
270 static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
271                                           struct gse_context *gse_ctx,
272                                           const DATA_BLOB *token_in,
273                                           DATA_BLOB *token_out)
274 {
275         OM_uint32 gss_maj, gss_min;
276         gss_buffer_desc in_data;
277         gss_buffer_desc out_data;
278         DATA_BLOB blob = data_blob_null;
279         NTSTATUS status;
280         OM_uint32 time_rec = 0;
281         struct timeval tv;
282
283         in_data.value = token_in->data;
284         in_data.length = token_in->length;
285
286         gss_maj = gss_init_sec_context(&gss_min,
287                                         gse_ctx->creds,
288                                         &gse_ctx->gssapi_context,
289                                         gse_ctx->server_name,
290                                         &gse_ctx->gss_mech,
291                                         gse_ctx->gss_want_flags,
292                                         0, GSS_C_NO_CHANNEL_BINDINGS,
293                                         &in_data, NULL, &out_data,
294                                         &gse_ctx->gss_got_flags, &time_rec);
295         switch (gss_maj) {
296         case GSS_S_COMPLETE:
297                 /* we are done with it */
298                 tv = timeval_current_ofs(time_rec, 0);
299                 gse_ctx->expire_time = timeval_to_nttime(&tv);
300
301                 status = NT_STATUS_OK;
302                 break;
303         case GSS_S_CONTINUE_NEEDED:
304                 /* we will need a third leg */
305                 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
306                 break;
307         default:
308                 DEBUG(0, ("gss_init_sec_context failed with [%s]\n",
309                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
310                 status = NT_STATUS_INTERNAL_ERROR;
311                 goto done;
312         }
313
314         /* we may be told to return nothing */
315         if (out_data.length) {
316                 blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length);
317                 if (!blob.data) {
318                         status = NT_STATUS_NO_MEMORY;
319                 }
320
321                 gss_maj = gss_release_buffer(&gss_min, &out_data);
322         }
323
324 done:
325         *token_out = blob;
326         return status;
327 }
328
329 static NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
330                                 bool do_sign, bool do_seal,
331                                 uint32_t add_gss_c_flags,
332                                 struct gse_context **_gse_ctx)
333 {
334         struct gse_context *gse_ctx;
335         OM_uint32 gss_maj, gss_min;
336         krb5_error_code ret;
337         NTSTATUS status;
338
339         status = gse_context_init(mem_ctx, do_sign, do_seal,
340                                   NULL, add_gss_c_flags, &gse_ctx);
341         if (!NT_STATUS_IS_OK(status)) {
342                 return NT_STATUS_NO_MEMORY;
343         }
344
345         ret = gse_krb5_get_server_keytab(gse_ctx->k5ctx,
346                                          &gse_ctx->keytab);
347         if (ret) {
348                 status = NT_STATUS_INTERNAL_ERROR;
349                 goto done;
350         }
351
352 #ifdef HAVE_GSS_KRB5_IMPORT_CRED
353
354         /* This creates a GSSAPI cred_id_t with the keytab set */
355         gss_maj = gss_krb5_import_cred(&gss_min, NULL, NULL, gse_ctx->keytab, 
356                                        &gse_ctx->creds);
357
358         if (gss_maj != 0
359             && gss_maj != (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME)) {
360                 DEBUG(0, ("gss_krb5_import_cred failed with [%s]\n",
361                           gse_errstr(gse_ctx, gss_maj, gss_min)));
362                 status = NT_STATUS_INTERNAL_ERROR;
363                 goto done;
364
365                 /* This is the error the MIT krb5 1.9 gives when it
366                  * implements the function, but we do not specify the
367                  * principal.  However, when we specify the principal
368                  * as host$@REALM the GSS acceptor fails with 'wrong
369                  * principal in request'.  Work around the issue by
370                  * falling back to the alternate approach below. */
371         } else if (gss_maj == (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME))
372 #endif
373         /* FIXME!!!
374          * This call sets the default keytab for the whole server, not
375          * just for this context. Need to find a way that does not alter
376          * the state of the whole server ... */
377         {
378                 const char *ktname;
379                 gss_OID_set_desc mech_set;
380
381                 ret = smb_krb5_keytab_name(gse_ctx, gse_ctx->k5ctx,
382                                    gse_ctx->keytab, &ktname);
383                 if (ret) {
384                         status = NT_STATUS_INTERNAL_ERROR;
385                         goto done;
386                 }
387
388                 ret = gsskrb5_register_acceptor_identity(ktname);
389                 if (ret) {
390                         status = NT_STATUS_INTERNAL_ERROR;
391                         goto done;
392                 }
393
394                 mech_set.count = 1;
395                 mech_set.elements = &gse_ctx->gss_mech;
396
397                 gss_maj = gss_acquire_cred(&gss_min,
398                                    GSS_C_NO_NAME,
399                                    GSS_C_INDEFINITE,
400                                    &mech_set,
401                                    GSS_C_ACCEPT,
402                                    &gse_ctx->creds,
403                                    NULL, NULL);
404
405                 if (gss_maj) {
406                         DEBUG(0, ("gss_acquire_creds failed with [%s]\n",
407                                   gse_errstr(gse_ctx, gss_maj, gss_min)));
408                         status = NT_STATUS_INTERNAL_ERROR;
409                         goto done;
410                 }
411         }
412
413         status = NT_STATUS_OK;
414
415 done:
416         if (!NT_STATUS_IS_OK(status)) {
417                 TALLOC_FREE(gse_ctx);
418         }
419
420         *_gse_ctx = gse_ctx;
421         return status;
422 }
423
424 static NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx,
425                                           struct gse_context *gse_ctx,
426                                           const DATA_BLOB *token_in,
427                                           DATA_BLOB *token_out)
428 {
429         OM_uint32 gss_maj, gss_min;
430         gss_buffer_desc in_data;
431         gss_buffer_desc out_data;
432         DATA_BLOB blob = data_blob_null;
433         NTSTATUS status;
434         OM_uint32 time_rec = 0;
435         struct timeval tv;
436
437         in_data.value = token_in->data;
438         in_data.length = token_in->length;
439
440         gss_maj = gss_accept_sec_context(&gss_min,
441                                          &gse_ctx->gssapi_context,
442                                          gse_ctx->creds,
443                                          &in_data,
444                                          GSS_C_NO_CHANNEL_BINDINGS,
445                                          &gse_ctx->client_name,
446                                          &gse_ctx->ret_mech,
447                                          &out_data,
448                                          &gse_ctx->gss_got_flags,
449                                          &time_rec,
450                                          &gse_ctx->delegated_cred_handle);
451         switch (gss_maj) {
452         case GSS_S_COMPLETE:
453                 /* we are done with it */
454                 tv = timeval_current_ofs(time_rec, 0);
455                 gse_ctx->expire_time = timeval_to_nttime(&tv);
456
457                 status = NT_STATUS_OK;
458                 break;
459         case GSS_S_CONTINUE_NEEDED:
460                 /* we will need a third leg */
461                 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
462                 break;
463         default:
464                 DEBUG(1, ("gss_accept_sec_context failed with [%s]\n",
465                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
466
467                 if (gse_ctx->gssapi_context) {
468                         gss_delete_sec_context(&gss_min,
469                                                 &gse_ctx->gssapi_context,
470                                                 GSS_C_NO_BUFFER);
471                 }
472
473                 status = NT_STATUS_LOGON_FAILURE;
474                 goto done;
475         }
476
477         /* we may be told to return nothing */
478         if (out_data.length) {
479                 blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length);
480                 if (!blob.data) {
481                         status = NT_STATUS_NO_MEMORY;
482                 }
483                 gss_maj = gss_release_buffer(&gss_min, &out_data);
484         }
485
486
487 done:
488         *token_out = blob;
489         return status;
490 }
491
492 static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min)
493 {
494         OM_uint32 gss_min, gss_maj;
495         gss_buffer_desc msg_min;
496         gss_buffer_desc msg_maj;
497         OM_uint32 msg_ctx = 0;
498
499         char *errstr = NULL;
500
501         ZERO_STRUCT(msg_min);
502         ZERO_STRUCT(msg_maj);
503
504         gss_maj = gss_display_status(&gss_min, maj, GSS_C_GSS_CODE,
505                                      GSS_C_NO_OID, &msg_ctx, &msg_maj);
506         if (gss_maj) {
507                 goto done;
508         }
509         errstr = talloc_strndup(mem_ctx,
510                                 (char *)msg_maj.value,
511                                         msg_maj.length);
512         if (!errstr) {
513                 goto done;
514         }
515         gss_maj = gss_display_status(&gss_min, min, GSS_C_MECH_CODE,
516                                      (gss_OID)discard_const(gss_mech_krb5),
517                                      &msg_ctx, &msg_min);
518         if (gss_maj) {
519                 goto done;
520         }
521
522         errstr = talloc_strdup_append_buffer(errstr, ": ");
523         if (!errstr) {
524                 goto done;
525         }
526         errstr = talloc_strndup_append_buffer(errstr,
527                                                 (char *)msg_min.value,
528                                                         msg_min.length);
529         if (!errstr) {
530                 goto done;
531         }
532
533 done:
534         if (msg_min.value) {
535                 gss_maj = gss_release_buffer(&gss_min, &msg_min);
536         }
537         if (msg_maj.value) {
538                 gss_maj = gss_release_buffer(&gss_min, &msg_maj);
539         }
540         return errstr;
541 }
542
543 static size_t gse_get_signature_length(struct gse_context *gse_ctx,
544                                        bool seal, size_t payload_size)
545 {
546         OM_uint32 gss_min, gss_maj;
547         gss_iov_buffer_desc iov[2];
548         int sealed;
549
550         /*
551          * gss_wrap_iov_length() only needs the type and length
552          */
553         iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
554         iov[0].buffer.value = NULL;
555         iov[0].buffer.length = 0;
556         iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
557         iov[1].buffer.value = NULL;
558         iov[1].buffer.length = payload_size;
559
560         gss_maj = gss_wrap_iov_length(&gss_min, gse_ctx->gssapi_context,
561                                         seal, GSS_C_QOP_DEFAULT,
562                                         &sealed, iov, 2);
563         if (gss_maj) {
564                 DEBUG(0, ("gss_wrap_iov_length failed with [%s]\n",
565                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
566                 return 0;
567         }
568
569         return iov[0].buffer.length;
570 }
571
572 static NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
573                          DATA_BLOB *data, DATA_BLOB *signature)
574 {
575         OM_uint32 gss_min, gss_maj;
576         gss_iov_buffer_desc iov[2];
577         int req_seal = 1; /* setting to 1 means we request sign+seal */
578         int sealed = 1;
579         NTSTATUS status;
580
581         /* allocate the memory ourselves so we do not need to talloc_memdup */
582         signature->length = gse_get_signature_length(gse_ctx, true, data->length);
583         if (!signature->length) {
584                 return NT_STATUS_INTERNAL_ERROR;
585         }
586         signature->data = (uint8_t *)talloc_size(mem_ctx, signature->length);
587         if (!signature->data) {
588                 return NT_STATUS_NO_MEMORY;
589         }
590         iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
591         iov[0].buffer.value = signature->data;
592         iov[0].buffer.length = signature->length;
593
594         /* data is encrypted in place, which is ok */
595         iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
596         iov[1].buffer.value = data->data;
597         iov[1].buffer.length = data->length;
598
599         gss_maj = gss_wrap_iov(&gss_min, gse_ctx->gssapi_context,
600                                 req_seal, GSS_C_QOP_DEFAULT,
601                                 &sealed, iov, 2);
602         if (gss_maj) {
603                 DEBUG(0, ("gss_wrap_iov failed with [%s]\n",
604                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
605                 status = NT_STATUS_ACCESS_DENIED;
606                 goto done;
607         }
608
609         if (!sealed) {
610                 DEBUG(0, ("gss_wrap_iov says data was not sealed!\n"));
611                 status = NT_STATUS_ACCESS_DENIED;
612                 goto done;
613         }
614
615         status = NT_STATUS_OK;
616
617         DEBUG(10, ("Sealed %d bytes, and got %d bytes header/signature.\n",
618                    (int)iov[1].buffer.length, (int)iov[0].buffer.length));
619
620 done:
621         return status;
622 }
623
624 static NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
625                            DATA_BLOB *data, const DATA_BLOB *signature)
626 {
627         OM_uint32 gss_min, gss_maj;
628         gss_iov_buffer_desc iov[2];
629         int sealed;
630         NTSTATUS status;
631
632         iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
633         iov[0].buffer.value = signature->data;
634         iov[0].buffer.length = signature->length;
635
636         /* data is decrypted in place, which is ok */
637         iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
638         iov[1].buffer.value = data->data;
639         iov[1].buffer.length = data->length;
640
641         gss_maj = gss_unwrap_iov(&gss_min, gse_ctx->gssapi_context,
642                                  &sealed, NULL, iov, 2);
643         if (gss_maj) {
644                 DEBUG(0, ("gss_unwrap_iov failed with [%s]\n",
645                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
646                 status = NT_STATUS_ACCESS_DENIED;
647                 goto done;
648         }
649
650         if (!sealed) {
651                 DEBUG(0, ("gss_unwrap_iov says data is not sealed!\n"));
652                 status = NT_STATUS_ACCESS_DENIED;
653                 goto done;
654         }
655
656         status = NT_STATUS_OK;
657
658         DEBUG(10, ("Unsealed %d bytes, with %d bytes header/signature.\n",
659                    (int)iov[1].buffer.length, (int)iov[0].buffer.length));
660
661 done:
662         return status;
663 }
664
665 static NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
666                          DATA_BLOB *data, DATA_BLOB *signature)
667 {
668         OM_uint32 gss_min, gss_maj;
669         gss_buffer_desc in_data = { 0, NULL };
670         gss_buffer_desc out_data = { 0, NULL};
671         NTSTATUS status;
672
673         in_data.value = data->data;
674         in_data.length = data->length;
675
676         gss_maj = gss_get_mic(&gss_min, gse_ctx->gssapi_context,
677                               GSS_C_QOP_DEFAULT,
678                               &in_data, &out_data);
679         if (gss_maj) {
680                 DEBUG(0, ("gss_get_mic failed with [%s]\n",
681                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
682                 status = NT_STATUS_ACCESS_DENIED;
683                 goto done;
684         }
685
686         *signature = data_blob_talloc(mem_ctx,
687                                         out_data.value, out_data.length);
688         if (!signature->data) {
689                 status = NT_STATUS_NO_MEMORY;
690                 goto done;
691         }
692
693         status = NT_STATUS_OK;
694
695 done:
696         if (out_data.value) {
697                 gss_maj = gss_release_buffer(&gss_min, &out_data);
698         }
699         return status;
700 }
701
702 static NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
703                              const DATA_BLOB *data, const DATA_BLOB *signature)
704 {
705         OM_uint32 gss_min, gss_maj;
706         gss_buffer_desc in_data = { 0, NULL };
707         gss_buffer_desc in_token = { 0, NULL};
708         NTSTATUS status;
709
710         in_data.value = data->data;
711         in_data.length = data->length;
712         in_token.value = signature->data;
713         in_token.length = signature->length;
714
715         gss_maj = gss_verify_mic(&gss_min, gse_ctx->gssapi_context,
716                                  &in_data, &in_token, NULL);
717         if (gss_maj) {
718                 DEBUG(0, ("gss_verify_mic failed with [%s]\n",
719                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
720                 status = NT_STATUS_ACCESS_DENIED;
721                 goto done;
722         }
723
724         status = NT_STATUS_OK;
725
726 done:
727         return status;
728 }
729
730 static NTSTATUS gensec_gse_client_start(struct gensec_security *gensec_security)
731 {
732         struct gse_context *gse_ctx;
733         struct cli_credentials *creds = gensec_get_credentials(gensec_security);
734         NTSTATUS nt_status;
735         OM_uint32 want_flags = 0;
736         bool do_sign = false, do_seal = false;
737         const char *hostname = gensec_get_target_hostname(gensec_security);
738         const char *service = gensec_get_target_service(gensec_security);
739         const char *username = cli_credentials_get_username(creds);
740         const char *password = cli_credentials_get_password(creds);
741
742         if (!hostname) {
743                 DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
744                 return NT_STATUS_INVALID_PARAMETER;
745         }
746         if (is_ipaddress(hostname)) {
747                 DEBUG(2, ("Cannot do GSE to an IP address\n"));
748                 return NT_STATUS_INVALID_PARAMETER;
749         }
750         if (strcmp(hostname, "localhost") == 0) {
751                 DEBUG(2, ("GSE to 'localhost' does not make sense\n"));
752                 return NT_STATUS_INVALID_PARAMETER;
753         }
754
755         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
756                 do_sign = true;
757         }
758         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
759                 do_seal = true;
760         }
761         if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
762                 want_flags |= GSS_C_DCE_STYLE;
763         }
764
765         nt_status = gse_init_client(gensec_security, do_sign, do_seal, NULL,
766                                     hostname, service,
767                                     username, password, want_flags,
768                                     &gse_ctx);
769         if (!NT_STATUS_IS_OK(nt_status)) {
770                 return nt_status;
771         }
772         gensec_security->private_data = gse_ctx;
773         return NT_STATUS_OK;
774 }
775
776 static NTSTATUS gensec_gse_server_start(struct gensec_security *gensec_security)
777 {
778         struct gse_context *gse_ctx;
779         NTSTATUS nt_status;
780         OM_uint32 want_flags = 0;
781         bool do_sign = false, do_seal = false;
782
783         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
784                 do_sign = true;
785         }
786         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
787                 do_seal = true;
788         }
789         if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
790                 want_flags |= GSS_C_DCE_STYLE;
791         }
792
793         nt_status = gse_init_server(gensec_security, do_sign, do_seal, want_flags,
794                                     &gse_ctx);
795         if (!NT_STATUS_IS_OK(nt_status)) {
796                 return nt_status;
797         }
798         gensec_security->private_data = gse_ctx;
799         return NT_STATUS_OK;
800 }
801
802 /**
803  * Next state function for the GSE GENSEC mechanism
804  *
805  * @param gensec_gse_state GSE State
806  * @param mem_ctx The TALLOC_CTX for *out to be allocated on
807  * @param in The request, as a DATA_BLOB
808  * @param out The reply, as an talloc()ed DATA_BLOB, on *mem_ctx
809  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
810  *                or NT_STATUS_OK if the user is authenticated.
811  */
812
813 static NTSTATUS gensec_gse_update(struct gensec_security *gensec_security,
814                                   TALLOC_CTX *mem_ctx,
815                                   struct tevent_context *ev,
816                                   const DATA_BLOB in, DATA_BLOB *out)
817 {
818         NTSTATUS status;
819         struct gse_context *gse_ctx =
820                 talloc_get_type_abort(gensec_security->private_data,
821                 struct gse_context);
822
823         switch (gensec_security->gensec_role) {
824         case GENSEC_CLIENT:
825                 status = gse_get_client_auth_token(mem_ctx, gse_ctx,
826                                                    &in, out);
827                 break;
828         case GENSEC_SERVER:
829                 status = gse_get_server_auth_token(mem_ctx, gse_ctx,
830                                                    &in, out);
831                 break;
832         }
833         if (!NT_STATUS_IS_OK(status)) {
834                 return status;
835         }
836
837         return NT_STATUS_OK;
838 }
839
840 static NTSTATUS gensec_gse_wrap(struct gensec_security *gensec_security,
841                                 TALLOC_CTX *mem_ctx,
842                                 const DATA_BLOB *in,
843                                 DATA_BLOB *out)
844 {
845         struct gse_context *gse_ctx =
846                 talloc_get_type_abort(gensec_security->private_data,
847                 struct gse_context);
848         OM_uint32 maj_stat, min_stat;
849         gss_buffer_desc input_token, output_token;
850         int conf_state;
851         input_token.length = in->length;
852         input_token.value = in->data;
853
854         maj_stat = gss_wrap(&min_stat,
855                             gse_ctx->gssapi_context,
856                             gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
857                             GSS_C_QOP_DEFAULT,
858                             &input_token,
859                             &conf_state,
860                             &output_token);
861         if (GSS_ERROR(maj_stat)) {
862                 DEBUG(0, ("gensec_gse_wrap: GSS Wrap failed: %s\n",
863                           gse_errstr(talloc_tos(), maj_stat, min_stat)));
864                 return NT_STATUS_ACCESS_DENIED;
865         }
866
867         *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
868         gss_release_buffer(&min_stat, &output_token);
869
870         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
871             && !conf_state) {
872                 return NT_STATUS_ACCESS_DENIED;
873         }
874         return NT_STATUS_OK;
875 }
876
877 static NTSTATUS gensec_gse_unwrap(struct gensec_security *gensec_security,
878                                      TALLOC_CTX *mem_ctx,
879                                      const DATA_BLOB *in,
880                                      DATA_BLOB *out)
881 {
882         struct gse_context *gse_ctx =
883                 talloc_get_type_abort(gensec_security->private_data,
884                 struct gse_context);
885         OM_uint32 maj_stat, min_stat;
886         gss_buffer_desc input_token, output_token;
887         int conf_state;
888         gss_qop_t qop_state;
889         input_token.length = in->length;
890         input_token.value = in->data;
891
892         maj_stat = gss_unwrap(&min_stat,
893                               gse_ctx->gssapi_context,
894                               &input_token,
895                               &output_token,
896                               &conf_state,
897                               &qop_state);
898         if (GSS_ERROR(maj_stat)) {
899                 DEBUG(0, ("gensec_gse_unwrap: GSS UnWrap failed: %s\n",
900                           gse_errstr(talloc_tos(), maj_stat, min_stat)));
901                 return NT_STATUS_ACCESS_DENIED;
902         }
903
904         *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
905         gss_release_buffer(&min_stat, &output_token);
906
907         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
908             && !conf_state) {
909                 return NT_STATUS_ACCESS_DENIED;
910         }
911         return NT_STATUS_OK;
912 }
913
914 static NTSTATUS gensec_gse_seal_packet(struct gensec_security *gensec_security,
915                                        TALLOC_CTX *mem_ctx,
916                                        uint8_t *data, size_t length,
917                                        const uint8_t *whole_pdu, size_t pdu_length,
918                                        DATA_BLOB *sig)
919 {
920         struct gse_context *gse_ctx =
921                 talloc_get_type_abort(gensec_security->private_data,
922                 struct gse_context);
923         DATA_BLOB payload = data_blob_const(data, length);
924         return gse_seal(mem_ctx, gse_ctx, &payload, sig);
925 }
926
927 static NTSTATUS gensec_gse_unseal_packet(struct gensec_security *gensec_security,
928                                          uint8_t *data, size_t length,
929                                          const uint8_t *whole_pdu, size_t pdu_length,
930                                          const DATA_BLOB *sig)
931 {
932         struct gse_context *gse_ctx =
933                 talloc_get_type_abort(gensec_security->private_data,
934                 struct gse_context);
935         DATA_BLOB payload = data_blob_const(data, length);
936         return gse_unseal(talloc_tos() /* unused */, gse_ctx, &payload, sig);
937 }
938
939 static NTSTATUS gensec_gse_sign_packet(struct gensec_security *gensec_security,
940                                        TALLOC_CTX *mem_ctx,
941                                        const uint8_t *data, size_t length,
942                                        const uint8_t *whole_pdu, size_t pdu_length,
943                                        DATA_BLOB *sig)
944 {
945         struct gse_context *gse_ctx =
946                 talloc_get_type_abort(gensec_security->private_data,
947                 struct gse_context);
948         DATA_BLOB payload = data_blob_const(data, length);
949         return gse_sign(mem_ctx, gse_ctx, &payload, sig);
950 }
951
952 static NTSTATUS gensec_gse_check_packet(struct gensec_security *gensec_security,
953                                         const uint8_t *data, size_t length,
954                                         const uint8_t *whole_pdu, size_t pdu_length,
955                                         const DATA_BLOB *sig)
956 {
957         struct gse_context *gse_ctx =
958                 talloc_get_type_abort(gensec_security->private_data,
959                 struct gse_context);
960         DATA_BLOB payload = data_blob_const(data, length);
961         return gse_sigcheck(NULL, gse_ctx, &payload, sig);
962 }
963
964 /* Try to figure out what features we actually got on the connection */
965 static bool gensec_gse_have_feature(struct gensec_security *gensec_security,
966                                     uint32_t feature)
967 {
968         struct gse_context *gse_ctx =
969                 talloc_get_type_abort(gensec_security->private_data,
970                 struct gse_context);
971
972         if (feature & GENSEC_FEATURE_SIGN) {
973                 return gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG;
974         }
975         if (feature & GENSEC_FEATURE_SEAL) {
976                 return gse_ctx->gss_got_flags & GSS_C_CONF_FLAG;
977         }
978         if (feature & GENSEC_FEATURE_SESSION_KEY) {
979                 /* Only for GSE/Krb5 */
980                 if (smb_gss_oid_equal(gse_ctx->ret_mech, gss_mech_krb5)) {
981                         return true;
982                 }
983         }
984         if (feature & GENSEC_FEATURE_DCE_STYLE) {
985                 return gse_ctx->gss_got_flags & GSS_C_DCE_STYLE;
986         }
987         if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
988                 NTSTATUS status;
989                 uint32_t keytype;
990
991                 if (!(gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG)) {
992                         return false;
993                 }
994
995                 status = gssapi_get_session_key(talloc_tos(), 
996                                                 gse_ctx->gssapi_context, NULL, &keytype);
997                 /* 
998                  * We should do a proper sig on the mechListMic unless
999                  * we know we have to be backwards compatible with
1000                  * earlier windows versions.  
1001                  * 
1002                  * Negotiating a non-krb5
1003                  * mech for example should be regarded as having
1004                  * NEW_SPNEGO
1005                  */
1006                 if (NT_STATUS_IS_OK(status)) {
1007                         switch (keytype) {
1008                         case ENCTYPE_DES_CBC_CRC:
1009                         case ENCTYPE_DES_CBC_MD5:
1010                         case ENCTYPE_ARCFOUR_HMAC:
1011                         case ENCTYPE_DES3_CBC_SHA1:
1012                                 return false;
1013                         }
1014                 }
1015                 return true;
1016         }
1017         /* We can always do async (rather than strict request/reply) packets.  */
1018         if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
1019                 return true;
1020         }
1021         return false;
1022 }
1023
1024 static NTTIME gensec_gse_expire_time(struct gensec_security *gensec_security)
1025 {
1026         struct gse_context *gse_ctx =
1027                 talloc_get_type_abort(gensec_security->private_data,
1028                 struct gse_context);
1029
1030         return gse_ctx->expire_time;
1031 }
1032
1033 /*
1034  * Extract the 'sesssion key' needed by SMB signing and ncacn_np
1035  * (for encrypting some passwords).
1036  *
1037  * This breaks all the abstractions, but what do you expect...
1038  */
1039 static NTSTATUS gensec_gse_session_key(struct gensec_security *gensec_security,
1040                                        TALLOC_CTX *mem_ctx,
1041                                        DATA_BLOB *session_key)
1042 {
1043         struct gse_context *gse_ctx =
1044                 talloc_get_type_abort(gensec_security->private_data,
1045                 struct gse_context);
1046
1047         return gssapi_get_session_key(mem_ctx, gse_ctx->gssapi_context, session_key, NULL);
1048 }
1049
1050 /* Get some basic (and authorization) information about the user on
1051  * this session.  This uses either the PAC (if present) or a local
1052  * database lookup */
1053 static NTSTATUS gensec_gse_session_info(struct gensec_security *gensec_security,
1054                                         TALLOC_CTX *mem_ctx,
1055                                         struct auth_session_info **_session_info)
1056 {
1057         struct gse_context *gse_ctx =
1058                 talloc_get_type_abort(gensec_security->private_data,
1059                 struct gse_context);
1060         NTSTATUS nt_status;
1061         TALLOC_CTX *tmp_ctx;
1062         struct auth_session_info *session_info = NULL;
1063         OM_uint32 maj_stat, min_stat;
1064         DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
1065
1066         gss_buffer_desc name_token;
1067         char *principal_string;
1068
1069         tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gse_session_info context");
1070         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1071
1072         maj_stat = gss_display_name(&min_stat,
1073                                     gse_ctx->client_name,
1074                                     &name_token,
1075                                     NULL);
1076         if (GSS_ERROR(maj_stat)) {
1077                 DEBUG(1, ("GSS display_name failed: %s\n",
1078                           gse_errstr(talloc_tos(), maj_stat, min_stat)));
1079                 talloc_free(tmp_ctx);
1080                 return NT_STATUS_FOOBAR;
1081         }
1082
1083         principal_string = talloc_strndup(tmp_ctx,
1084                                           (const char *)name_token.value,
1085                                           name_token.length);
1086
1087         gss_release_buffer(&min_stat, &name_token);
1088
1089         if (!principal_string) {
1090                 talloc_free(tmp_ctx);
1091                 return NT_STATUS_NO_MEMORY;
1092         }
1093
1094         nt_status = gssapi_obtain_pac_blob(tmp_ctx,  gse_ctx->gssapi_context,
1095                                            gse_ctx->client_name,
1096                                            &pac_blob);
1097
1098         /* IF we have the PAC - otherwise we need to get this
1099          * data from elsewere
1100          */
1101         if (NT_STATUS_IS_OK(nt_status)) {
1102                 pac_blob_ptr = &pac_blob;
1103         }
1104         nt_status = gensec_generate_session_info_pac(tmp_ctx,
1105                                                      gensec_security,
1106                                                      NULL,
1107                                                      pac_blob_ptr, principal_string,
1108                                                      gensec_get_remote_address(gensec_security),
1109                                                      &session_info);
1110         if (!NT_STATUS_IS_OK(nt_status)) {
1111                 talloc_free(tmp_ctx);
1112                 return nt_status;
1113         }
1114
1115         nt_status = gensec_gse_session_key(gensec_security, session_info,
1116                                            &session_info->session_key);
1117         if (!NT_STATUS_IS_OK(nt_status)) {
1118                 talloc_free(tmp_ctx);
1119                 return nt_status;
1120         }
1121
1122         *_session_info = talloc_move(mem_ctx, &session_info);
1123         talloc_free(tmp_ctx);
1124
1125         return NT_STATUS_OK;
1126 }
1127
1128 static size_t gensec_gse_sig_size(struct gensec_security *gensec_security,
1129                                   size_t data_size)
1130 {
1131         struct gse_context *gse_ctx =
1132                 talloc_get_type_abort(gensec_security->private_data,
1133                 struct gse_context);
1134
1135         return gse_get_signature_length(gse_ctx,
1136                                         gensec_security->want_features & GENSEC_FEATURE_SEAL,
1137                                         data_size);
1138 }
1139
1140 static const char *gensec_gse_krb5_oids[] = {
1141         GENSEC_OID_KERBEROS5_OLD,
1142         GENSEC_OID_KERBEROS5,
1143         NULL
1144 };
1145
1146 const struct gensec_security_ops gensec_gse_krb5_security_ops = {
1147         .name           = "gse_krb5",
1148         .auth_type      = DCERPC_AUTH_TYPE_KRB5,
1149         .oid            = gensec_gse_krb5_oids,
1150         .client_start   = gensec_gse_client_start,
1151         .server_start   = gensec_gse_server_start,
1152         .magic          = gensec_magic_check_krb5_oid,
1153         .update         = gensec_gse_update,
1154         .session_key    = gensec_gse_session_key,
1155         .session_info   = gensec_gse_session_info,
1156         .sig_size       = gensec_gse_sig_size,
1157         .sign_packet    = gensec_gse_sign_packet,
1158         .check_packet   = gensec_gse_check_packet,
1159         .seal_packet    = gensec_gse_seal_packet,
1160         .unseal_packet  = gensec_gse_unseal_packet,
1161         .wrap           = gensec_gse_wrap,
1162         .unwrap         = gensec_gse_unwrap,
1163         .have_feature   = gensec_gse_have_feature,
1164         .expire_time    = gensec_gse_expire_time,
1165         .enabled        = true,
1166         .kerberos       = true,
1167         .priority       = GENSEC_GSSAPI
1168 };
1169
1170 #endif /* HAVE_KRB5 */