Coverage Report

Created: 2026-09-03 07:24

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