Coverage Report

Created: 2025-12-31 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/lib/tls/tls_tstream.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
4
   Copyright (C) Stefan Metzmacher 2010-2025
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
*/
19
20
#include "includes.h"
21
#include "system/network.h"
22
#include "system/filesys.h"
23
#include "system/time.h"
24
#include "lib/util/dlinklist.h"
25
#include "lib/util/time_basic.h"
26
#include "lib/util/util_file.h"
27
#include "lib/util/tevent_ntstatus.h"
28
#include "../util/tevent_unix.h"
29
#include "../lib/tsocket/tsocket.h"
30
#include "../lib/tsocket/tsocket_internal.h"
31
#include "../lib/util/util_net.h"
32
#include "lib/tls/tls.h"
33
#include "lib/param/param.h"
34
35
#include <gnutls/gnutls.h>
36
#include <gnutls/crypto.h>
37
#include <gnutls/x509.h>
38
#include "lib/crypto/gnutls_helpers.h"
39
40
#ifdef HAVE_LIBQUIC
41
#include <netinet/quic.h>
42
#endif
43
44
#ifdef HAVE_LIBNGTCP2
45
#include <ngtcp2/ngtcp2.h>
46
#include <ngtcp2/ngtcp2_crypto.h>
47
#include <ngtcp2/ngtcp2_crypto_gnutls.h>
48
#endif
49
50
0
#define DH_BITS 2048
51
52
const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer)
53
0
{
54
0
  switch (verify_peer) {
55
0
  case TLS_VERIFY_PEER_NO_CHECK:
56
0
    return TLS_VERIFY_PEER_NO_CHECK_STRING;
57
58
0
  case TLS_VERIFY_PEER_CA_ONLY:
59
0
    return TLS_VERIFY_PEER_CA_ONLY_STRING;
60
61
0
  case TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE:
62
0
    return TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING;
63
64
0
  case TLS_VERIFY_PEER_CA_AND_NAME:
65
0
    return TLS_VERIFY_PEER_CA_AND_NAME_STRING;
66
67
0
  case TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE:
68
0
    return TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING;
69
0
  }
70
71
0
  return "unknown tls_verify_peer_state";
72
0
}
73
74
static const struct tstream_context_ops tstream_tls_ops;
75
76
struct tstream_tls {
77
  struct tstream_context *plain_stream;
78
  int error;
79
80
  gnutls_session_t tls_session;
81
82
  bool is_server;
83
84
  enum tls_verify_peer_state verify_peer;
85
  const char *peer_name;
86
87
  DATA_BLOB channel_bindings;
88
89
  struct tevent_context *current_ev;
90
91
  struct tevent_immediate *retry_im;
92
93
  struct {
94
    struct tevent_req *mgmt_req;
95
  } waiting_flush;
96
97
  struct {
98
    uint8_t *buf;
99
    off_t ofs;
100
    struct iovec iov;
101
    struct tevent_req *subreq;
102
  } push;
103
104
  struct {
105
    uint8_t *buf;
106
    struct iovec iov;
107
    struct tevent_req *subreq;
108
  } pull;
109
110
  struct {
111
    struct tevent_req *req;
112
  } handshake;
113
114
  struct {
115
    off_t ofs;
116
    size_t left;
117
    uint8_t buffer[1024];
118
    struct tevent_req *req;
119
  } write;
120
121
  struct {
122
    off_t ofs;
123
    size_t left;
124
    uint8_t buffer[1024];
125
    struct tevent_req *req;
126
  } read;
127
128
  struct {
129
    struct tevent_req *req;
130
  } disconnect;
131
};
132
133
static void tstream_tls_retry_handshake(struct tstream_context *stream);
134
static void tstream_tls_retry_read(struct tstream_context *stream);
135
static void tstream_tls_retry_write(struct tstream_context *stream);
136
static void tstream_tls_retry_disconnect(struct tstream_context *stream);
137
static void tstream_tls_retry_trigger(struct tevent_context *ctx,
138
              struct tevent_immediate *im,
139
              void *private_data);
140
141
static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
142
0
{
143
144
0
  struct tstream_tls *tlss =
145
0
    tstream_context_data(stream,
146
0
    struct tstream_tls);
147
148
0
  if (tlss->push.subreq == NULL && tlss->pull.subreq == NULL) {
149
0
    if (tlss->waiting_flush.mgmt_req != NULL) {
150
0
      struct tevent_req *req = tlss->waiting_flush.mgmt_req;
151
152
0
      tlss->waiting_flush.mgmt_req = NULL;
153
154
0
      tevent_req_done(req);
155
0
      return;
156
0
    }
157
0
  }
158
159
0
  if (tlss->disconnect.req) {
160
0
    tstream_tls_retry_disconnect(stream);
161
0
    return;
162
0
  }
163
164
0
  if (tlss->handshake.req) {
165
0
    tstream_tls_retry_handshake(stream);
166
0
    return;
167
0
  }
168
169
0
  if (tlss->write.req && tlss->read.req && !deferred) {
170
0
    tevent_schedule_immediate(tlss->retry_im, tlss->current_ev,
171
0
            tstream_tls_retry_trigger,
172
0
            stream);
173
0
  }
174
175
0
  if (tlss->write.req) {
176
0
    tstream_tls_retry_write(stream);
177
0
    return;
178
0
  }
179
180
0
  if (tlss->read.req) {
181
0
    tstream_tls_retry_read(stream);
182
0
    return;
183
0
  }
184
0
}
185
186
static void tstream_tls_retry_trigger(struct tevent_context *ctx,
187
              struct tevent_immediate *im,
188
              void *private_data)
189
0
{
190
0
  struct tstream_context *stream =
191
0
    talloc_get_type_abort(private_data,
192
0
    struct tstream_context);
193
194
0
  tstream_tls_retry(stream, true);
195
0
}
196
197
static void tstream_tls_push_done(struct tevent_req *subreq);
198
199
static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
200
           const void *buf, size_t size)
201
0
{
202
0
  struct tstream_context *stream =
203
0
    talloc_get_type_abort(ptr,
204
0
    struct tstream_context);
205
0
  struct tstream_tls *tlss =
206
0
    tstream_context_data(stream,
207
0
    struct tstream_tls);
208
0
  struct tevent_req *subreq = NULL;
209
0
  uint8_t *nbuf;
210
0
  size_t len;
211
212
0
  if (tlss->error != 0) {
213
0
    errno = tlss->error;
214
0
    return -1;
215
0
  }
216
217
0
  if (tlss->push.subreq) {
218
0
    errno = EAGAIN;
219
0
    return -1;
220
0
  }
221
222
0
  len = MIN(size, UINT16_MAX - tlss->push.ofs);
223
224
0
  if (len == 0) {
225
0
    errno = EAGAIN;
226
0
    return -1;
227
0
  }
228
229
0
  nbuf = talloc_realloc(tlss, tlss->push.buf,
230
0
            uint8_t, tlss->push.ofs + len);
231
0
  if (nbuf == NULL) {
232
0
    if (tlss->push.buf) {
233
0
      errno = EAGAIN;
234
0
      return -1;
235
0
    }
236
237
0
    return -1;
238
0
  }
239
0
  tlss->push.buf = nbuf;
240
241
0
  memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
242
0
  tlss->push.ofs += len;
243
244
0
  tlss->push.iov.iov_base = (char *)tlss->push.buf;
245
0
  tlss->push.iov.iov_len = tlss->push.ofs;
246
247
0
  subreq = tstream_writev_send(tlss,
248
0
             tlss->current_ev,
249
0
             tlss->plain_stream,
250
0
             &tlss->push.iov, 1);
251
0
  if (subreq == NULL) {
252
0
    errno = ENOMEM;
253
0
    return -1;
254
0
  }
255
0
  tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
256
257
0
  tlss->push.subreq = subreq;
258
0
  return len;
259
0
}
260
261
static void tstream_tls_push_done(struct tevent_req *subreq)
262
0
{
263
0
  struct tstream_context *stream =
264
0
    tevent_req_callback_data(subreq,
265
0
    struct tstream_context);
266
0
  struct tstream_tls *tlss =
267
0
    tstream_context_data(stream,
268
0
    struct tstream_tls);
269
0
  int ret;
270
0
  int sys_errno;
271
272
0
  tlss->push.subreq = NULL;
273
0
  ZERO_STRUCT(tlss->push.iov);
274
0
  TALLOC_FREE(tlss->push.buf);
275
0
  tlss->push.ofs = 0;
276
277
0
  ret = tstream_writev_recv(subreq, &sys_errno);
278
0
  TALLOC_FREE(subreq);
279
0
  if (ret == -1) {
280
0
    tlss->error = sys_errno;
281
0
    tstream_tls_retry(stream, false);
282
0
    return;
283
0
  }
284
285
0
  tstream_tls_retry(stream, false);
286
0
}
287
288
static void tstream_tls_pull_done(struct tevent_req *subreq);
289
290
static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
291
           void *buf, size_t size)
292
0
{
293
0
  struct tstream_context *stream =
294
0
    talloc_get_type_abort(ptr,
295
0
    struct tstream_context);
296
0
  struct tstream_tls *tlss =
297
0
    tstream_context_data(stream,
298
0
    struct tstream_tls);
299
0
  struct tevent_req *subreq;
300
0
  size_t len;
301
302
0
  if (tlss->error != 0) {
303
0
    errno = tlss->error;
304
0
    return -1;
305
0
  }
306
307
0
  if (tlss->pull.subreq) {
308
0
    errno = EAGAIN;
309
0
    return -1;
310
0
  }
311
312
0
  if (tlss->pull.iov.iov_base) {
313
0
    uint8_t *b;
314
0
    size_t n;
315
316
0
    b = (uint8_t *)tlss->pull.iov.iov_base;
317
318
0
    n = MIN(tlss->pull.iov.iov_len, size);
319
0
    memcpy(buf, b, n);
320
321
0
    tlss->pull.iov.iov_len -= n;
322
0
    b += n;
323
0
    tlss->pull.iov.iov_base = (char *)b;
324
0
    if (tlss->pull.iov.iov_len == 0) {
325
0
      tlss->pull.iov.iov_base = NULL;
326
0
      TALLOC_FREE(tlss->pull.buf);
327
0
    }
328
329
0
    return n;
330
0
  }
331
332
0
  if (size == 0) {
333
0
    return 0;
334
0
  }
335
336
0
  len = MIN(size, UINT16_MAX);
337
338
0
  tlss->pull.buf = talloc_array(tlss, uint8_t, len);
339
0
  if (tlss->pull.buf == NULL) {
340
0
    return -1;
341
0
  }
342
343
0
  tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
344
0
  tlss->pull.iov.iov_len = len;
345
346
0
  subreq = tstream_readv_send(tlss,
347
0
            tlss->current_ev,
348
0
            tlss->plain_stream,
349
0
            &tlss->pull.iov, 1);
350
0
  if (subreq == NULL) {
351
0
    errno = ENOMEM;
352
0
    return -1;
353
0
  }
354
0
  tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
355
356
0
  tlss->pull.subreq = subreq;
357
0
  errno = EAGAIN;
358
0
  return -1;
359
0
}
360
361
static void tstream_tls_pull_done(struct tevent_req *subreq)
362
0
{
363
0
  struct tstream_context *stream =
364
0
    tevent_req_callback_data(subreq,
365
0
    struct tstream_context);
366
0
  struct tstream_tls *tlss =
367
0
    tstream_context_data(stream,
368
0
    struct tstream_tls);
369
0
  int ret;
370
0
  int sys_errno;
371
372
0
  tlss->pull.subreq = NULL;
373
374
0
  ret = tstream_readv_recv(subreq, &sys_errno);
375
0
  TALLOC_FREE(subreq);
376
0
  if (ret == -1) {
377
0
    tlss->error = sys_errno;
378
0
    tstream_tls_retry(stream, false);
379
0
    return;
380
0
  }
381
382
0
  tstream_tls_retry(stream, false);
383
0
}
384
385
static int tstream_tls_destructor(struct tstream_tls *tlss)
386
0
{
387
0
  if (tlss->tls_session) {
388
0
    gnutls_deinit(tlss->tls_session);
389
0
    tlss->tls_session = NULL;
390
0
  }
391
392
0
  return 0;
393
0
}
394
395
static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
396
0
{
397
0
  struct tstream_tls *tlss =
398
0
    tstream_context_data(stream,
399
0
    struct tstream_tls);
400
0
  size_t ret;
401
402
0
  if (tlss->error != 0) {
403
0
    errno = tlss->error;
404
0
    return -1;
405
0
  }
406
407
0
  ret = gnutls_record_check_pending(tlss->tls_session);
408
0
  ret += tlss->read.left;
409
410
0
  return ret;
411
0
}
412
413
struct tstream_tls_readv_state {
414
  struct tstream_context *stream;
415
416
  struct iovec *vector;
417
  int count;
418
419
  int ret;
420
};
421
422
static void tstream_tls_readv_crypt_next(struct tevent_req *req);
423
424
static struct tevent_req *tstream_tls_readv_send(TALLOC_CTX *mem_ctx,
425
          struct tevent_context *ev,
426
          struct tstream_context *stream,
427
          struct iovec *vector,
428
          size_t count)
429
0
{
430
0
  struct tstream_tls *tlss =
431
0
    tstream_context_data(stream,
432
0
    struct tstream_tls);
433
0
  struct tevent_req *req;
434
0
  struct tstream_tls_readv_state *state;
435
436
0
  tlss->read.req = NULL;
437
438
0
  if (tlss->current_ev != ev) {
439
0
    SMB_ASSERT(tlss->push.subreq == NULL);
440
0
    SMB_ASSERT(tlss->pull.subreq == NULL);
441
0
  }
442
443
0
  tlss->current_ev = ev;
444
445
0
  req = tevent_req_create(mem_ctx, &state,
446
0
        struct tstream_tls_readv_state);
447
0
  if (req == NULL) {
448
0
    return NULL;
449
0
  }
450
451
0
  state->stream = stream;
452
0
  state->ret = 0;
453
454
0
  if (tlss->error != 0) {
455
0
    tevent_req_error(req, tlss->error);
456
0
    return tevent_req_post(req, ev);
457
0
  }
458
459
  /*
460
   * we make a copy of the vector so we can change the structure
461
   */
462
0
  state->vector = talloc_array(state, struct iovec, count);
463
0
  if (tevent_req_nomem(state->vector, req)) {
464
0
    return tevent_req_post(req, ev);
465
0
  }
466
0
  memcpy(state->vector, vector, sizeof(struct iovec) * count);
467
0
  state->count = count;
468
469
0
  tstream_tls_readv_crypt_next(req);
470
0
  if (!tevent_req_is_in_progress(req)) {
471
0
    return tevent_req_post(req, ev);
472
0
  }
473
474
0
  return req;
475
0
}
476
477
static void tstream_tls_readv_crypt_next(struct tevent_req *req)
478
0
{
479
0
  struct tstream_tls_readv_state *state =
480
0
    tevent_req_data(req,
481
0
    struct tstream_tls_readv_state);
482
0
  struct tstream_tls *tlss =
483
0
    tstream_context_data(state->stream,
484
0
    struct tstream_tls);
485
486
  /*
487
   * copy the pending buffer first
488
   */
489
0
  while (tlss->read.left > 0 && state->count > 0) {
490
0
    uint8_t *base = (uint8_t *)state->vector[0].iov_base;
491
0
    size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
492
493
0
    memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
494
495
0
    base += len;
496
0
    state->vector[0].iov_base = (char *) base;
497
0
    state->vector[0].iov_len -= len;
498
499
0
    tlss->read.ofs += len;
500
0
    tlss->read.left -= len;
501
502
0
    if (state->vector[0].iov_len == 0) {
503
0
      state->vector += 1;
504
0
      state->count -= 1;
505
0
    }
506
507
0
    state->ret += len;
508
0
  }
509
510
0
  if (state->count == 0) {
511
0
    tevent_req_done(req);
512
0
    return;
513
0
  }
514
515
0
  tlss->read.req = req;
516
0
  tstream_tls_retry_read(state->stream);
517
0
}
518
519
static void tstream_tls_retry_read(struct tstream_context *stream)
520
0
{
521
0
  struct tstream_tls *tlss =
522
0
    tstream_context_data(stream,
523
0
    struct tstream_tls);
524
0
  struct tevent_req *req = tlss->read.req;
525
0
  int ret;
526
527
0
  if (tlss->error != 0) {
528
0
    tevent_req_error(req, tlss->error);
529
0
    return;
530
0
  }
531
532
0
  tlss->read.left = 0;
533
0
  tlss->read.ofs = 0;
534
535
0
  ret = gnutls_record_recv(tlss->tls_session,
536
0
         tlss->read.buffer,
537
0
         sizeof(tlss->read.buffer));
538
0
  if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
539
0
    return;
540
0
  }
541
542
0
  tlss->read.req = NULL;
543
544
0
  if (gnutls_error_is_fatal(ret) != 0) {
545
0
    DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
546
0
    tlss->error = EIO;
547
0
    tevent_req_error(req, tlss->error);
548
0
    return;
549
0
  }
550
551
0
  if (ret == 0) {
552
0
    tlss->error = EPIPE;
553
0
    tevent_req_error(req, tlss->error);
554
0
    return;
555
0
  }
556
557
0
  tlss->read.left = ret;
558
0
  tstream_tls_readv_crypt_next(req);
559
0
}
560
561
static int tstream_tls_readv_recv(struct tevent_req *req,
562
          int *perrno)
563
0
{
564
0
  struct tstream_tls_readv_state *state =
565
0
    tevent_req_data(req,
566
0
    struct tstream_tls_readv_state);
567
0
  struct tstream_tls *tlss =
568
0
    tstream_context_data(state->stream,
569
0
    struct tstream_tls);
570
0
  int ret;
571
572
0
  tlss->read.req = NULL;
573
574
0
  ret = tsocket_simple_int_recv(req, perrno);
575
0
  if (ret == 0) {
576
0
    ret = state->ret;
577
0
  }
578
579
0
  tevent_req_received(req);
580
0
  return ret;
581
0
}
582
583
struct tstream_tls_writev_state {
584
  struct tstream_context *stream;
585
586
  struct iovec *vector;
587
  int count;
588
589
  int ret;
590
};
591
592
static void tstream_tls_writev_crypt_next(struct tevent_req *req);
593
594
static struct tevent_req *tstream_tls_writev_send(TALLOC_CTX *mem_ctx,
595
          struct tevent_context *ev,
596
          struct tstream_context *stream,
597
          const struct iovec *vector,
598
          size_t count)
599
0
{
600
0
  struct tstream_tls *tlss =
601
0
    tstream_context_data(stream,
602
0
    struct tstream_tls);
603
0
  struct tevent_req *req;
604
0
  struct tstream_tls_writev_state *state;
605
606
0
  tlss->write.req = NULL;
607
608
0
  if (tlss->current_ev != ev) {
609
0
    SMB_ASSERT(tlss->push.subreq == NULL);
610
0
    SMB_ASSERT(tlss->pull.subreq == NULL);
611
0
  }
612
613
0
  tlss->current_ev = ev;
614
615
0
  req = tevent_req_create(mem_ctx, &state,
616
0
        struct tstream_tls_writev_state);
617
0
  if (req == NULL) {
618
0
    return NULL;
619
0
  }
620
621
0
  state->stream = stream;
622
0
  state->ret = 0;
623
624
0
  if (tlss->error != 0) {
625
0
    tevent_req_error(req, tlss->error);
626
0
    return tevent_req_post(req, ev);
627
0
  }
628
629
  /*
630
   * we make a copy of the vector so we can change the structure
631
   */
632
0
  state->vector = talloc_array(state, struct iovec, count);
633
0
  if (tevent_req_nomem(state->vector, req)) {
634
0
    return tevent_req_post(req, ev);
635
0
  }
636
0
  memcpy(state->vector, vector, sizeof(struct iovec) * count);
637
0
  state->count = count;
638
639
0
  tstream_tls_writev_crypt_next(req);
640
0
  if (!tevent_req_is_in_progress(req)) {
641
0
    return tevent_req_post(req, ev);
642
0
  }
643
644
0
  return req;
645
0
}
646
647
static void tstream_tls_writev_crypt_next(struct tevent_req *req)
648
0
{
649
0
  struct tstream_tls_writev_state *state =
650
0
    tevent_req_data(req,
651
0
    struct tstream_tls_writev_state);
652
0
  struct tstream_tls *tlss =
653
0
    tstream_context_data(state->stream,
654
0
    struct tstream_tls);
655
656
0
  tlss->write.left = sizeof(tlss->write.buffer);
657
0
  tlss->write.ofs = 0;
658
659
  /*
660
   * first fill our buffer
661
   */
662
0
  while (tlss->write.left > 0 && state->count > 0) {
663
0
    uint8_t *base = (uint8_t *)state->vector[0].iov_base;
664
0
    size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
665
666
0
    memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
667
668
0
    base += len;
669
0
    state->vector[0].iov_base = (char *) base;
670
0
    state->vector[0].iov_len -= len;
671
672
0
    tlss->write.ofs += len;
673
0
    tlss->write.left -= len;
674
675
0
    if (state->vector[0].iov_len == 0) {
676
0
      state->vector += 1;
677
0
      state->count -= 1;
678
0
    }
679
680
0
    state->ret += len;
681
0
  }
682
683
0
  if (tlss->write.ofs == 0) {
684
0
    tevent_req_done(req);
685
0
    return;
686
0
  }
687
688
0
  tlss->write.left = tlss->write.ofs;
689
0
  tlss->write.ofs = 0;
690
691
0
  tlss->write.req = req;
692
0
  tstream_tls_retry_write(state->stream);
693
0
}
694
695
static void tstream_tls_retry_write(struct tstream_context *stream)
696
0
{
697
0
  struct tstream_tls *tlss =
698
0
    tstream_context_data(stream,
699
0
    struct tstream_tls);
700
0
  struct tevent_req *req = tlss->write.req;
701
0
  int ret;
702
703
0
  if (tlss->error != 0) {
704
0
    tevent_req_error(req, tlss->error);
705
0
    return;
706
0
  }
707
708
0
  ret = gnutls_record_send(tlss->tls_session,
709
0
         tlss->write.buffer + tlss->write.ofs,
710
0
         tlss->write.left);
711
0
  if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
712
0
    return;
713
0
  }
714
715
0
  tlss->write.req = NULL;
716
717
0
  if (gnutls_error_is_fatal(ret) != 0) {
718
0
    DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
719
0
    tlss->error = EIO;
720
0
    tevent_req_error(req, tlss->error);
721
0
    return;
722
0
  }
723
724
0
  if (ret == 0) {
725
0
    tlss->error = EPIPE;
726
0
    tevent_req_error(req, tlss->error);
727
0
    return;
728
0
  }
729
730
0
  tlss->write.ofs += ret;
731
0
  tlss->write.left -= ret;
732
733
0
  if (tlss->write.left > 0) {
734
0
    tlss->write.req = req;
735
0
    tstream_tls_retry_write(stream);
736
0
    return;
737
0
  }
738
739
0
  tstream_tls_writev_crypt_next(req);
740
0
}
741
742
static int tstream_tls_writev_recv(struct tevent_req *req,
743
           int *perrno)
744
0
{
745
0
  struct tstream_tls_writev_state *state =
746
0
    tevent_req_data(req,
747
0
    struct tstream_tls_writev_state);
748
0
  struct tstream_tls *tlss =
749
0
    tstream_context_data(state->stream,
750
0
    struct tstream_tls);
751
0
  int ret;
752
753
0
  tlss->write.req = NULL;
754
755
0
  ret = tsocket_simple_int_recv(req, perrno);
756
0
  if (ret == 0) {
757
0
    ret = state->ret;
758
0
  }
759
760
0
  tevent_req_received(req);
761
0
  return ret;
762
0
}
763
764
struct tstream_tls_disconnect_state {
765
  uint8_t _dummy;
766
};
767
768
static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
769
            struct tevent_context *ev,
770
            struct tstream_context *stream)
771
0
{
772
0
  struct tstream_tls *tlss =
773
0
    tstream_context_data(stream,
774
0
    struct tstream_tls);
775
0
  struct tevent_req *req;
776
0
  struct tstream_tls_disconnect_state *state;
777
778
0
  tlss->disconnect.req = NULL;
779
780
0
  if (tlss->current_ev != ev) {
781
0
    SMB_ASSERT(tlss->push.subreq == NULL);
782
0
    SMB_ASSERT(tlss->pull.subreq == NULL);
783
0
  }
784
785
0
  tlss->current_ev = ev;
786
787
0
  req = tevent_req_create(mem_ctx, &state,
788
0
        struct tstream_tls_disconnect_state);
789
0
  if (req == NULL) {
790
0
    return NULL;
791
0
  }
792
793
0
  if (tlss->error != 0) {
794
0
    tevent_req_error(req, tlss->error);
795
0
    return tevent_req_post(req, ev);
796
0
  }
797
798
0
  tlss->disconnect.req = req;
799
0
  tstream_tls_retry_disconnect(stream);
800
0
  if (!tevent_req_is_in_progress(req)) {
801
0
    return tevent_req_post(req, ev);
802
0
  }
803
804
0
  return req;
805
0
}
806
807
static void tstream_tls_retry_disconnect(struct tstream_context *stream)
808
0
{
809
0
  struct tstream_tls *tlss =
810
0
    tstream_context_data(stream,
811
0
    struct tstream_tls);
812
0
  struct tevent_req *req = tlss->disconnect.req;
813
0
  int ret;
814
815
0
  if (tlss->error != 0) {
816
0
    tevent_req_error(req, tlss->error);
817
0
    return;
818
0
  }
819
820
0
  ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
821
0
  if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
822
0
    return;
823
0
  }
824
825
0
  tlss->disconnect.req = NULL;
826
827
0
  if (gnutls_error_is_fatal(ret) != 0) {
828
0
    DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
829
0
    tlss->error = EIO;
830
0
    tevent_req_error(req, tlss->error);
831
0
    return;
832
0
  }
833
834
0
  if (ret != GNUTLS_E_SUCCESS) {
835
0
    DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
836
0
    tlss->error = EIO;
837
0
    tevent_req_error(req, tlss->error);
838
0
    return;
839
0
  }
840
841
0
  if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
842
0
    tlss->waiting_flush.mgmt_req = req;
843
0
    return;
844
0
  }
845
846
0
  tevent_req_done(req);
847
0
}
848
849
static int tstream_tls_disconnect_recv(struct tevent_req *req,
850
               int *perrno)
851
0
{
852
0
  int ret;
853
854
0
  ret = tsocket_simple_int_recv(req, perrno);
855
856
0
  tevent_req_received(req);
857
0
  return ret;
858
0
}
859
860
static const struct tstream_context_ops tstream_tls_ops = {
861
  .name     = "tls",
862
863
  .pending_bytes    = tstream_tls_pending_bytes,
864
865
  .readv_send   = tstream_tls_readv_send,
866
  .readv_recv   = tstream_tls_readv_recv,
867
868
  .writev_send    = tstream_tls_writev_send,
869
  .writev_recv    = tstream_tls_writev_recv,
870
871
  .disconnect_send  = tstream_tls_disconnect_send,
872
  .disconnect_recv  = tstream_tls_disconnect_recv,
873
};
874
875
struct tstream_tls_params_internal {
876
  gnutls_certificate_credentials_t x509_cred;
877
  gnutls_dh_params_t dh_params;
878
  const char *tls_priority;
879
  bool tls_enabled;
880
  enum tls_verify_peer_state verify_peer;
881
  const char *peer_name;
882
#ifdef HAVE_LIBQUIC
883
  bool quic;
884
#endif /* HAVE_LIBQUIC */
885
};
886
887
struct tstream_tls_params {
888
  struct tstream_tls_params_internal *internal;
889
};
890
891
static int tstream_tls_params_internal_destructor(struct tstream_tls_params_internal *tlsp)
892
0
{
893
0
  if (tlsp->x509_cred) {
894
0
    gnutls_certificate_free_credentials(tlsp->x509_cred);
895
0
    tlsp->x509_cred = NULL;
896
0
  }
897
0
  if (tlsp->dh_params) {
898
0
    gnutls_dh_params_deinit(tlsp->dh_params);
899
0
    tlsp->dh_params = NULL;
900
0
  }
901
902
0
  return 0;
903
0
}
904
905
bool tstream_tls_params_enabled(struct tstream_tls_params *tls_params)
906
0
{
907
0
  struct tstream_tls_params_internal *tlsp = tls_params->internal;
908
909
0
  return tlsp->tls_enabled;
910
0
}
911
912
bool tstream_tls_params_quic_enabled(struct tstream_tls_params *tls_params)
913
0
{
914
#ifdef HAVE_LIBQUIC
915
916
  struct tstream_tls_params_internal *tlsp = tls_params->internal;
917
918
  return tlsp->quic;
919
920
#else /* HAVE_LIBQUIC */
921
922
0
  return false;
923
924
0
#endif /* HAVE_LIBQUIC */
925
0
}
926
927
enum tls_verify_peer_state tstream_tls_params_verify_peer(
928
  struct tstream_tls_params *tls_params)
929
0
{
930
#ifdef HAVE_LIBQUIC
931
932
  struct tstream_tls_params_internal *tlsp = tls_params->internal;
933
934
  return tlsp->verify_peer;
935
936
#else /* HAVE_LIBQUIC */
937
938
0
  return TLS_VERIFY_PEER_NO_CHECK;
939
940
0
#endif /* HAVE_LIBQUIC */
941
0
}
942
943
bool tstream_tls_verify_peer_trusted(enum tls_verify_peer_state verify_peer)
944
0
{
945
0
  return (verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME);
946
0
}
947
948
const char *tstream_tls_params_peer_name(
949
  const struct tstream_tls_params *params)
950
0
{
951
0
  return params->internal->peer_name;
952
0
}
953
954
static NTSTATUS tstream_tls_setup_channel_bindings(struct tstream_tls *tlss)
955
0
{
956
0
  gnutls_datum_t cb = { .size = 0 };
957
0
  int ret;
958
959
#ifdef HAVE_GNUTLS_CB_TLS_SERVER_END_POINT
960
  ret = gnutls_session_channel_binding(tlss->tls_session,
961
               GNUTLS_CB_TLS_SERVER_END_POINT,
962
               &cb);
963
#else /* not HAVE_GNUTLS_CB_TLS_SERVER_END_POINT */
964
0
  ret = legacy_gnutls_server_end_point_cb(tlss->tls_session,
965
0
            tlss->is_server,
966
0
            &cb);
967
0
#endif /* not HAVE_GNUTLS_CB_TLS_SERVER_END_POINT */
968
0
  if (ret != GNUTLS_E_SUCCESS) {
969
0
    return gnutls_error_to_ntstatus(ret,
970
0
        NT_STATUS_CRYPTO_SYSTEM_INVALID);
971
0
  }
972
973
0
  if (cb.size != 0) {
974
    /*
975
     * Looking at the OpenLDAP implementation
976
     * for LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT
977
     * revealed that we need to prefix it with
978
     * 'tls-server-end-point:'
979
     */
980
0
    const char endpoint_prefix[] = "tls-server-end-point:";
981
0
    size_t prefix_size = strlen(endpoint_prefix);
982
0
    size_t size = prefix_size + cb.size;
983
984
0
    tlss->channel_bindings = data_blob_talloc_named(tlss, NULL, size,
985
0
                "tls_channel_bindings");
986
0
    if (tlss->channel_bindings.data == NULL) {
987
0
      gnutls_free(cb.data);
988
0
      return NT_STATUS_NO_MEMORY;
989
0
    }
990
0
    memcpy(tlss->channel_bindings.data, endpoint_prefix, prefix_size);
991
0
    memcpy(tlss->channel_bindings.data + prefix_size, cb.data, cb.size);
992
0
    gnutls_free(cb.data);
993
0
  }
994
995
0
  return NT_STATUS_OK;
996
0
}
997
998
const DATA_BLOB *tstream_tls_channel_bindings(struct tstream_context *tls_tstream)
999
0
{
1000
0
  struct tstream_tls *tlss =
1001
0
    talloc_get_type(_tstream_context_data(tls_tstream),
1002
0
    struct tstream_tls);
1003
1004
0
  if (tlss == NULL) {
1005
0
    return NULL;
1006
0
  }
1007
1008
0
  return &tlss->channel_bindings;
1009
0
}
1010
1011
NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
1012
           bool system_cas,
1013
           const char * const *ca_dirs,
1014
           const char *ca_file,
1015
           const char *crl_file,
1016
           const char *tls_priority,
1017
           enum tls_verify_peer_state verify_peer,
1018
           const char *peer_name,
1019
           struct tstream_tls_params **_tlsp)
1020
0
{
1021
0
  struct tstream_tls_params *__tlsp = NULL;
1022
0
  struct tstream_tls_params_internal *tlsp = NULL;
1023
0
  bool got_ca = false;
1024
0
  size_t i;
1025
0
  int ret;
1026
1027
0
  __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1028
0
  if (__tlsp == NULL) {
1029
0
    return NT_STATUS_NO_MEMORY;
1030
0
  }
1031
1032
0
  tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1033
0
  if (tlsp == NULL) {
1034
0
    TALLOC_FREE(__tlsp);
1035
0
    return NT_STATUS_NO_MEMORY;
1036
0
  }
1037
0
  talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1038
0
  __tlsp->internal = tlsp;
1039
1040
0
  tlsp->verify_peer = verify_peer;
1041
0
  if (peer_name != NULL) {
1042
0
    tlsp->peer_name = talloc_strdup(tlsp, peer_name);
1043
0
    if (tlsp->peer_name == NULL) {
1044
0
      TALLOC_FREE(__tlsp);
1045
0
      return NT_STATUS_NO_MEMORY;
1046
0
    }
1047
0
  } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
1048
0
    DEBUG(0,("TLS failed to missing peer_name - "
1049
0
       "with 'tls verify peer = %s'\n",
1050
0
       tls_verify_peer_string(tlsp->verify_peer)));
1051
0
    TALLOC_FREE(__tlsp);
1052
0
    return NT_STATUS_INVALID_PARAMETER_MIX;
1053
0
  }
1054
1055
0
  ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
1056
0
  if (ret != GNUTLS_E_SUCCESS) {
1057
0
    DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1058
0
    TALLOC_FREE(__tlsp);
1059
0
    return NT_STATUS_NO_MEMORY;
1060
0
  }
1061
1062
0
  if (system_cas) {
1063
0
    ret = gnutls_certificate_set_x509_system_trust(tlsp->x509_cred);
1064
0
    if (ret < 0) {
1065
0
      DBG_ERR("gnutls_certificate_set_x509_system_trust() - %s\n",
1066
0
        gnutls_strerror(ret));
1067
0
      TALLOC_FREE(__tlsp);
1068
0
      return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1069
0
    }
1070
0
    if (ret > 0) {
1071
0
      got_ca = true;
1072
0
    }
1073
0
  }
1074
1075
0
  for (i = 0; ca_dirs != NULL && ca_dirs[i] != NULL; i++) {
1076
0
    const char *ca_dir = ca_dirs[i];
1077
1078
0
    if (!directory_exist(ca_dir)) {
1079
0
      continue;
1080
0
    }
1081
1082
0
    ret = gnutls_certificate_set_x509_trust_dir(tlsp->x509_cred,
1083
0
                  ca_dir,
1084
0
                  GNUTLS_X509_FMT_PEM);
1085
0
    if (ret < 0) {
1086
0
      DBG_ERR("gnutls_certificate_set_x509_trust_dir(%s) - %s\n",
1087
0
        ca_dir, gnutls_strerror(ret));
1088
0
      TALLOC_FREE(__tlsp);
1089
0
      return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1090
0
    }
1091
0
    if (ret > 0) {
1092
0
      got_ca = true;
1093
0
    }
1094
0
  }
1095
1096
0
  if (ca_file && *ca_file && file_exist(ca_file)) {
1097
0
    ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1098
0
                   ca_file,
1099
0
                   GNUTLS_X509_FMT_PEM);
1100
0
    if (ret < 0) {
1101
0
      DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1102
0
         ca_file, gnutls_strerror(ret)));
1103
0
      TALLOC_FREE(__tlsp);
1104
0
      return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1105
0
    }
1106
0
    if (ret > 0) {
1107
0
      got_ca = true;
1108
0
    }
1109
0
  }
1110
1111
0
  if (!got_ca && tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
1112
0
    D_ERR("TLS: 'tls verify peer = %s' requires "
1113
0
          "'tls trust system cas', "
1114
0
          "'tls ca directories' or "
1115
0
          "'tls cafile'\n",
1116
0
          tls_verify_peer_string(tlsp->verify_peer));
1117
0
    TALLOC_FREE(__tlsp);
1118
0
    return NT_STATUS_INVALID_PARAMETER_MIX;
1119
0
  }
1120
1121
0
  if (crl_file && *crl_file && file_exist(crl_file)) {
1122
0
    ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1123
0
                 crl_file, 
1124
0
                 GNUTLS_X509_FMT_PEM);
1125
0
    if (ret < 0) {
1126
0
      DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1127
0
         crl_file, gnutls_strerror(ret)));
1128
0
      TALLOC_FREE(__tlsp);
1129
0
      return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1130
0
    }
1131
0
  } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE) {
1132
0
    DEBUG(0,("TLS failed to missing crlfile %s - "
1133
0
       "with 'tls verify peer = %s'\n",
1134
0
       crl_file,
1135
0
       tls_verify_peer_string(tlsp->verify_peer)));
1136
0
    TALLOC_FREE(__tlsp);
1137
0
    return NT_STATUS_INVALID_PARAMETER_MIX;
1138
0
  }
1139
1140
0
  tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
1141
0
  if (tlsp->tls_priority == NULL) {
1142
0
    TALLOC_FREE(__tlsp);
1143
0
    return NT_STATUS_NO_MEMORY;
1144
0
  }
1145
1146
0
  tlsp->tls_enabled = true;
1147
1148
0
  *_tlsp = __tlsp;
1149
0
  return NT_STATUS_OK;
1150
0
}
1151
1152
NTSTATUS tstream_tls_params_client_lpcfg(TALLOC_CTX *mem_ctx,
1153
           struct loadparm_context *lp_ctx,
1154
           const char *peer_name,
1155
           struct tstream_tls_params **tlsp)
1156
0
{
1157
0
  TALLOC_CTX *frame = talloc_stackframe();
1158
0
  bool system_cas = false;
1159
0
  const char * const *ca_dirs = NULL;
1160
0
  const char *ptr = NULL;
1161
0
  char *ca_file = NULL;
1162
0
  char *crl_file = NULL;
1163
0
  const char *tls_priority = NULL;
1164
0
  enum tls_verify_peer_state verify_peer =
1165
0
    TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE;
1166
0
  NTSTATUS status;
1167
1168
0
  system_cas = lpcfg_tls_trust_system_cas(lp_ctx);
1169
0
  ca_dirs = lpcfg_tls_ca_directories(lp_ctx);
1170
1171
0
  ptr = lpcfg__tls_cafile(lp_ctx);
1172
0
  if (ptr != NULL) {
1173
0
    ca_file = lpcfg_tls_cafile(frame, lp_ctx);
1174
0
    if (ca_file == NULL) {
1175
0
      TALLOC_FREE(frame);
1176
0
      return NT_STATUS_NO_MEMORY;
1177
0
    }
1178
0
  }
1179
1180
0
  ptr = lpcfg__tls_crlfile(lp_ctx);
1181
0
  if (ptr != NULL) {
1182
0
    crl_file = lpcfg_tls_crlfile(frame, lp_ctx);
1183
0
    if (crl_file == NULL) {
1184
0
      TALLOC_FREE(frame);
1185
0
      return NT_STATUS_NO_MEMORY;
1186
0
    }
1187
0
  }
1188
1189
0
  tls_priority = lpcfg_tls_priority(lp_ctx);
1190
0
  verify_peer = lpcfg_tls_verify_peer(lp_ctx);
1191
1192
0
  status = tstream_tls_params_client(mem_ctx,
1193
0
             system_cas,
1194
0
             ca_dirs,
1195
0
             ca_file,
1196
0
             crl_file,
1197
0
             tls_priority,
1198
0
             verify_peer,
1199
0
             peer_name,
1200
0
             tlsp);
1201
0
  TALLOC_FREE(frame);
1202
0
  return status;
1203
0
}
1204
1205
NTSTATUS tstream_tls_params_quic_prepare(struct tstream_tls_params *tlsp)
1206
0
{
1207
#ifdef HAVE_LIBQUIC
1208
  const char *tls_priority = NULL;
1209
1210
  if (!tlsp->internal->tls_enabled) {
1211
    goto disable;
1212
  }
1213
1214
  if (tlsp->internal->peer_name != NULL &&
1215
      is_ipaddress(tlsp->internal->peer_name))
1216
  {
1217
    goto disable;
1218
  }
1219
1220
  tls_priority = talloc_strdup(tlsp->internal, QUIC_PRIORITY);
1221
  if (tls_priority == NULL) {
1222
    return NT_STATUS_NO_MEMORY;
1223
  }
1224
1225
  talloc_free(discard_const(tlsp->internal->tls_priority));
1226
  tlsp->internal->tls_priority = tls_priority;
1227
1228
  tlsp->internal->quic = true;
1229
1230
  return NT_STATUS_OK;
1231
disable:
1232
  tlsp->internal->quic = false;
1233
#endif /* HAVE_LIBQUIC */
1234
0
  return NT_STATUS_OK;
1235
0
}
1236
1237
static NTSTATUS tstream_tls_prepare_gnutls(struct tstream_tls_params *_tlsp,
1238
             struct tstream_tls *tlss)
1239
0
{
1240
0
  struct tstream_tls_params_internal *tlsp = NULL;
1241
0
  int ret;
1242
0
  unsigned int flags;
1243
0
  gnutls_certificate_request_t cert_req = GNUTLS_CERT_IGNORE;
1244
0
  const char *hostname = NULL;
1245
1246
0
  if (tlss->is_server) {
1247
0
    flags = GNUTLS_SERVER;
1248
0
    cert_req = GNUTLS_CERT_REQUEST;
1249
0
  } else {
1250
0
    flags = GNUTLS_CLIENT;
1251
    /*
1252
     * tls_tstream can't properly handle 'New Session Ticket'
1253
     * messages sent 'after' the client sends the 'Finished'
1254
     * message.  GNUTLS_NO_TICKETS was introduced in GnuTLS 3.5.6.
1255
     * This flag is to indicate the session Flag session should not
1256
     * use resumption with session tickets.
1257
     */
1258
0
    flags |= GNUTLS_NO_TICKETS;
1259
0
  }
1260
1261
  /*
1262
   * Note we need to make sure x509_cred and dh_params
1263
   * from tstream_tls_params_internal stay alive for
1264
   * the whole lifetime of this session!
1265
   *
1266
   * See 'man gnutls_credentials_set' and
1267
   * 'man gnutls_certificate_set_dh_params'.
1268
   *
1269
   * Note: here we use talloc_reference() in a way
1270
   *       that does not expose it to the caller.
1271
   */
1272
0
  tlsp = talloc_reference(tlss, _tlsp->internal);
1273
0
  if (tlsp == NULL) {
1274
0
    return NT_STATUS_NO_MEMORY;
1275
0
  }
1276
1277
#ifdef HAVE_LIBQUIC
1278
  if (tlss->is_server && tlsp->quic) {
1279
    flags |= GNUTLS_NO_AUTO_SEND_TICKET;
1280
    cert_req = GNUTLS_CERT_IGNORE;
1281
  }
1282
#endif /* HAVE_LIBQUIC */
1283
1284
0
  tlss->verify_peer = tlsp->verify_peer;
1285
0
  if (tlsp->peer_name != NULL) {
1286
0
    bool ip = is_ipaddress(tlsp->peer_name);
1287
#ifdef HAVE_LIBQUIC
1288
    bool force_name = tlsp->quic;
1289
#else
1290
0
    bool force_name = false;
1291
0
#endif /* HAVE_LIBQUIC */
1292
1293
0
    tlss->peer_name = talloc_strdup(tlss, tlsp->peer_name);
1294
0
    if (tlss->peer_name == NULL) {
1295
0
      return NT_STATUS_NO_MEMORY;
1296
0
    }
1297
1298
0
    if (!ip) {
1299
0
      hostname = tlss->peer_name;
1300
0
    }
1301
1302
0
    if (!force_name &&
1303
0
        tlss->verify_peer < TLS_VERIFY_PEER_CA_AND_NAME)
1304
0
    {
1305
0
      hostname = NULL;
1306
0
    }
1307
0
  }
1308
1309
0
  if (tlss->current_ev != NULL) {
1310
0
    tlss->retry_im = tevent_create_immediate(tlss);
1311
0
    if (tlss->retry_im == NULL) {
1312
0
      return NT_STATUS_NO_MEMORY;
1313
0
    }
1314
0
  }
1315
1316
0
  ret = gnutls_init(&tlss->tls_session, flags);
1317
0
  if (ret != GNUTLS_E_SUCCESS) {
1318
0
    return gnutls_error_to_ntstatus(ret,
1319
0
      NT_STATUS_CRYPTO_SYSTEM_INVALID);
1320
0
  }
1321
1322
0
  ret = gnutls_set_default_priority(tlss->tls_session);
1323
0
  if (ret != GNUTLS_E_SUCCESS) {
1324
0
    return gnutls_error_to_ntstatus(ret,
1325
0
      NT_STATUS_CRYPTO_SYSTEM_INVALID);
1326
0
  }
1327
1328
0
  if (strlen(tlsp->tls_priority) > 0) {
1329
0
    const char *error_pos = NULL;
1330
1331
0
    ret = gnutls_priority_set_direct(tlss->tls_session,
1332
0
             tlsp->tls_priority,
1333
0
             &error_pos);
1334
0
    if (ret != GNUTLS_E_SUCCESS) {
1335
0
      return gnutls_error_to_ntstatus(ret,
1336
0
        NT_STATUS_CRYPTO_SYSTEM_INVALID);
1337
0
    }
1338
0
  }
1339
1340
0
  ret = gnutls_credentials_set(tlss->tls_session,
1341
0
             GNUTLS_CRD_CERTIFICATE,
1342
0
             tlsp->x509_cred);
1343
0
  if (ret != GNUTLS_E_SUCCESS) {
1344
0
    return gnutls_error_to_ntstatus(ret,
1345
0
        NT_STATUS_CRYPTO_SYSTEM_INVALID);
1346
0
  }
1347
1348
0
  if (hostname != NULL) {
1349
0
    ret = gnutls_server_name_set(tlss->tls_session,
1350
0
               GNUTLS_NAME_DNS,
1351
0
               hostname,
1352
0
               strlen(hostname));
1353
0
    if (ret != GNUTLS_E_SUCCESS) {
1354
0
      return gnutls_error_to_ntstatus(ret,
1355
0
          NT_STATUS_CRYPTO_SYSTEM_INVALID);
1356
0
    }
1357
0
  }
1358
1359
0
  if (tlss->is_server) {
1360
0
    gnutls_certificate_server_set_request(tlss->tls_session,
1361
0
                  cert_req);
1362
0
    gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
1363
0
  }
1364
1365
0
  return NT_STATUS_OK;
1366
0
}
1367
1368
static NTSTATUS tstream_tls_verify_peer(struct tstream_tls *tlss)
1369
0
{
1370
0
  unsigned int status = UINT32_MAX;
1371
0
  bool ip = true;
1372
0
  const char *hostname = NULL;
1373
0
  int ret;
1374
1375
0
  if (tlss->verify_peer == TLS_VERIFY_PEER_NO_CHECK) {
1376
0
    return NT_STATUS_OK;
1377
0
  }
1378
1379
0
  if (tlss->peer_name != NULL) {
1380
0
    ip = is_ipaddress(tlss->peer_name);
1381
0
  }
1382
1383
0
  if (!ip) {
1384
0
    hostname = tlss->peer_name;
1385
0
  }
1386
1387
0
  if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
1388
0
    hostname = NULL;
1389
0
  }
1390
1391
0
  if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
1392
0
    if (hostname == NULL) {
1393
0
      DEBUG(1,("TLS %s - no hostname available for "
1394
0
         "verify_peer[%s] and peer_name[%s]\n",
1395
0
         __location__,
1396
0
         tls_verify_peer_string(tlss->verify_peer),
1397
0
         tlss->peer_name));
1398
0
      return NT_STATUS_IMAGE_CERT_REVOKED;
1399
0
    }
1400
0
  }
1401
1402
0
  ret = gnutls_certificate_verify_peers3(tlss->tls_session,
1403
0
                 hostname,
1404
0
                 &status);
1405
0
  if (ret != GNUTLS_E_SUCCESS) {
1406
0
    return gnutls_error_to_ntstatus(ret,
1407
0
      NT_STATUS_CRYPTO_SYSTEM_INVALID);
1408
0
  }
1409
1410
0
  if (status != 0) {
1411
0
    DEBUG(1,("TLS %s - check failed for "
1412
0
       "verify_peer[%s] and peer_name[%s] "
1413
0
       "status 0x%x (%s%s%s%s%s%s%s%s)\n",
1414
0
       __location__,
1415
0
       tls_verify_peer_string(tlss->verify_peer),
1416
0
       tlss->peer_name,
1417
0
       status,
1418
0
       status & GNUTLS_CERT_INVALID ? "invalid " : "",
1419
0
       status & GNUTLS_CERT_REVOKED ? "revoked " : "",
1420
0
       status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
1421
0
        "signer_not_found " : "",
1422
0
       status & GNUTLS_CERT_SIGNER_NOT_CA ?
1423
0
        "signer_not_ca " : "",
1424
0
       status & GNUTLS_CERT_INSECURE_ALGORITHM ?
1425
0
        "insecure_algorithm " : "",
1426
0
       status & GNUTLS_CERT_NOT_ACTIVATED ?
1427
0
        "not_activated " : "",
1428
0
       status & GNUTLS_CERT_EXPIRED ?
1429
0
        "expired " : "",
1430
0
       status & GNUTLS_CERT_UNEXPECTED_OWNER ?
1431
0
        "unexpected_owner " : ""));
1432
0
    return NT_STATUS_IMAGE_CERT_REVOKED;
1433
0
  }
1434
1435
0
  return NT_STATUS_OK;
1436
0
}
1437
1438
struct tstream_tls_connect_state {
1439
  struct tstream_context *tls_stream;
1440
};
1441
1442
struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
1443
               struct tevent_context *ev,
1444
               struct tstream_context *plain_stream,
1445
               struct tstream_tls_params *_tls_params,
1446
               const char *location)
1447
0
{
1448
0
  struct tevent_req *req;
1449
0
  struct tstream_tls_connect_state *state;
1450
0
  struct tstream_tls *tlss;
1451
0
  NTSTATUS status;
1452
1453
0
  req = tevent_req_create(mem_ctx, &state,
1454
0
        struct tstream_tls_connect_state);
1455
0
  if (req == NULL) {
1456
0
    return NULL;
1457
0
  }
1458
1459
0
  state->tls_stream = tstream_context_create(state,
1460
0
               &tstream_tls_ops,
1461
0
               &tlss,
1462
0
               struct tstream_tls,
1463
0
               location);
1464
0
  if (tevent_req_nomem(state->tls_stream, req)) {
1465
0
    return tevent_req_post(req, ev);
1466
0
  }
1467
0
  ZERO_STRUCTP(tlss);
1468
0
  talloc_set_destructor(tlss, tstream_tls_destructor);
1469
0
  tlss->plain_stream = plain_stream;
1470
0
  tlss->is_server = false;
1471
0
  tlss->current_ev = ev;
1472
1473
0
  status = tstream_tls_prepare_gnutls(_tls_params, tlss);
1474
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1475
0
    tevent_req_oom(req);
1476
0
    return tevent_req_post(req, ev);
1477
0
  }
1478
0
  if (!NT_STATUS_IS_OK(status)) {
1479
0
    tevent_req_error(req, EINVAL);
1480
0
    return tevent_req_post(req, ev);
1481
0
  }
1482
1483
0
  gnutls_transport_set_ptr(tlss->tls_session,
1484
0
         (gnutls_transport_ptr_t)state->tls_stream);
1485
0
  gnutls_transport_set_pull_function(tlss->tls_session,
1486
0
             (gnutls_pull_func)tstream_tls_pull_function);
1487
0
  gnutls_transport_set_push_function(tlss->tls_session,
1488
0
             (gnutls_push_func)tstream_tls_push_function);
1489
1490
0
  tlss->handshake.req = req;
1491
0
  tstream_tls_retry_handshake(state->tls_stream);
1492
0
  if (!tevent_req_is_in_progress(req)) {
1493
0
    return tevent_req_post(req, ev);
1494
0
  }
1495
1496
0
  return req;
1497
0
}
1498
1499
int tstream_tls_connect_recv(struct tevent_req *req,
1500
           int *perrno,
1501
           TALLOC_CTX *mem_ctx,
1502
           struct tstream_context **tls_stream)
1503
0
{
1504
0
  struct tstream_tls_connect_state *state =
1505
0
    tevent_req_data(req,
1506
0
    struct tstream_tls_connect_state);
1507
1508
0
  if (tevent_req_is_unix_error(req, perrno)) {
1509
0
    tevent_req_received(req);
1510
0
    return -1;
1511
0
  }
1512
1513
0
  *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1514
0
  tevent_req_received(req);
1515
0
  return 0;
1516
0
}
1517
1518
/*
1519
  initialise global tls state
1520
*/
1521
NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
1522
           const char *dns_host_name,
1523
           const char * const *additional_dns_hostnames,
1524
           bool enabled,
1525
           const char *key_file,
1526
           const char *cert_file,
1527
           const char *ca_file,
1528
           const char *crl_file,
1529
           const char *dhp_file,
1530
           const char *tls_priority,
1531
           struct tstream_tls_params **_tlsp)
1532
0
{
1533
0
  struct tstream_tls_params *__tlsp = NULL;
1534
0
  struct tstream_tls_params_internal *tlsp = NULL;
1535
0
  int ret;
1536
0
  struct stat st;
1537
1538
0
  if (!enabled || key_file == NULL || *key_file == 0) {
1539
0
    __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1540
0
    if (__tlsp == NULL) {
1541
0
      return NT_STATUS_NO_MEMORY;
1542
0
    }
1543
1544
0
    tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1545
0
    if (tlsp == NULL) {
1546
0
      TALLOC_FREE(__tlsp);
1547
0
      return NT_STATUS_NO_MEMORY;
1548
0
    }
1549
1550
0
    talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1551
0
    __tlsp->internal = tlsp;
1552
0
    tlsp->tls_enabled = false;
1553
1554
0
    *_tlsp = __tlsp;
1555
0
    return NT_STATUS_OK;
1556
0
  }
1557
1558
0
  __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1559
0
  if (__tlsp == NULL) {
1560
0
    return NT_STATUS_NO_MEMORY;
1561
0
  }
1562
1563
0
  tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1564
0
  if (tlsp == NULL) {
1565
0
    TALLOC_FREE(__tlsp);
1566
0
    return NT_STATUS_NO_MEMORY;
1567
0
  }
1568
1569
0
  talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1570
0
  __tlsp->internal = tlsp;
1571
1572
0
  if (!file_exist(ca_file)) {
1573
0
    tls_cert_generate(tlsp, dns_host_name,
1574
0
          additional_dns_hostnames,
1575
0
          key_file, cert_file, ca_file);
1576
0
  }
1577
1578
0
  if (file_exist(key_file) &&
1579
0
      !file_check_permissions(key_file, geteuid(), 0600, &st))
1580
0
  {
1581
0
    DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
1582
0
        "owner uid %u should be %u, mode 0%o should be 0%o\n"
1583
0
        "This is known as CVE-2013-4476.\n"
1584
0
        "Removing all tls .pem files will cause an "
1585
0
        "auto-regeneration with the correct permissions.\n",
1586
0
        key_file,
1587
0
        (unsigned int)st.st_uid, geteuid(),
1588
0
        (unsigned int)(st.st_mode & 0777), 0600));
1589
0
    TALLOC_FREE(__tlsp);
1590
0
    return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1591
0
  }
1592
1593
0
  ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
1594
0
  if (ret != GNUTLS_E_SUCCESS) {
1595
0
    DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1596
0
    TALLOC_FREE(__tlsp);
1597
0
    return NT_STATUS_NO_MEMORY;
1598
0
  }
1599
1600
0
  if (ca_file && *ca_file) {
1601
0
    ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1602
0
                   ca_file,
1603
0
                   GNUTLS_X509_FMT_PEM);
1604
0
    if (ret < 0) {
1605
0
      DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1606
0
         ca_file, gnutls_strerror(ret)));
1607
0
      TALLOC_FREE(__tlsp);
1608
0
      return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1609
0
    }
1610
0
  }
1611
1612
0
  if (crl_file && *crl_file) {
1613
0
    ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1614
0
                 crl_file, 
1615
0
                 GNUTLS_X509_FMT_PEM);
1616
0
    if (ret < 0) {
1617
0
      DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1618
0
         crl_file, gnutls_strerror(ret)));
1619
0
      TALLOC_FREE(__tlsp);
1620
0
      return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1621
0
    }
1622
0
  }
1623
1624
0
  ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
1625
0
               cert_file, key_file,
1626
0
               GNUTLS_X509_FMT_PEM);
1627
0
  if (ret != GNUTLS_E_SUCCESS) {
1628
0
    DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1629
0
       cert_file, key_file, gnutls_strerror(ret)));
1630
0
    TALLOC_FREE(__tlsp);
1631
0
    return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1632
0
  }
1633
1634
0
  ret = gnutls_dh_params_init(&tlsp->dh_params);
1635
0
  if (ret != GNUTLS_E_SUCCESS) {
1636
0
    DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1637
0
    TALLOC_FREE(__tlsp);
1638
0
    return NT_STATUS_NO_MEMORY;
1639
0
  }
1640
1641
0
  if (dhp_file && *dhp_file) {
1642
0
    gnutls_datum_t dhparms;
1643
0
    size_t size;
1644
1645
0
    dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
1646
1647
0
    if (!dhparms.data) {
1648
0
      DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1649
0
         dhp_file, errno, strerror(errno)));
1650
0
      TALLOC_FREE(__tlsp);
1651
0
      return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1652
0
    }
1653
0
    dhparms.size = size;
1654
1655
0
    ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
1656
0
                &dhparms,
1657
0
                GNUTLS_X509_FMT_PEM);
1658
0
    if (ret != GNUTLS_E_SUCCESS) {
1659
0
      DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1660
0
         dhp_file, gnutls_strerror(ret)));
1661
0
      TALLOC_FREE(__tlsp);
1662
0
      return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1663
0
    }
1664
0
  } else {
1665
0
    ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
1666
0
    if (ret != GNUTLS_E_SUCCESS) {
1667
0
      DEBUG(0,("TLS failed to generate dh_params - %s\n",
1668
0
         gnutls_strerror(ret)));
1669
0
      TALLOC_FREE(__tlsp);
1670
0
      return NT_STATUS_INTERNAL_ERROR;
1671
0
    }
1672
0
  }
1673
1674
0
  gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
1675
1676
0
  tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
1677
0
  if (tlsp->tls_priority == NULL) {
1678
0
    TALLOC_FREE(__tlsp);
1679
0
    return NT_STATUS_NO_MEMORY;
1680
0
  }
1681
1682
0
  tlsp->tls_enabled = true;
1683
1684
0
  *_tlsp = __tlsp;
1685
0
  return NT_STATUS_OK;
1686
0
}
1687
1688
NTSTATUS tstream_tls_params_server_lpcfg(TALLOC_CTX *mem_ctx,
1689
           struct loadparm_context *lp_ctx,
1690
           struct tstream_tls_params **_tlsp)
1691
0
{
1692
0
  TALLOC_CTX *frame = talloc_stackframe();
1693
0
  NTSTATUS status;
1694
1695
0
  status = tstream_tls_params_server(mem_ctx,
1696
0
             lpcfg_dns_hostname(lp_ctx),
1697
0
             lpcfg_additional_dns_hostnames(lp_ctx),
1698
0
             lpcfg_tls_enabled(lp_ctx),
1699
0
             lpcfg_tls_keyfile(frame, lp_ctx),
1700
0
             lpcfg_tls_certfile(frame, lp_ctx),
1701
0
             lpcfg_tls_cafile(frame, lp_ctx),
1702
0
             lpcfg_tls_crlfile(frame, lp_ctx),
1703
0
             lpcfg_tls_dhpfile(frame, lp_ctx),
1704
0
             lpcfg_tls_priority(lp_ctx),
1705
0
             _tlsp);
1706
1707
0
  TALLOC_FREE(frame);
1708
0
  return status;
1709
0
}
1710
1711
struct tstream_tls_accept_state {
1712
  struct tstream_context *tls_stream;
1713
};
1714
1715
struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
1716
              struct tevent_context *ev,
1717
              struct tstream_context *plain_stream,
1718
              struct tstream_tls_params *_tlsp,
1719
              const char *location)
1720
0
{
1721
0
  struct tevent_req *req;
1722
0
  struct tstream_tls_accept_state *state;
1723
0
  struct tstream_tls *tlss;
1724
0
  NTSTATUS status;
1725
1726
0
  req = tevent_req_create(mem_ctx, &state,
1727
0
        struct tstream_tls_accept_state);
1728
0
  if (req == NULL) {
1729
0
    return NULL;
1730
0
  }
1731
1732
0
  state->tls_stream = tstream_context_create(state,
1733
0
               &tstream_tls_ops,
1734
0
               &tlss,
1735
0
               struct tstream_tls,
1736
0
               location);
1737
0
  if (tevent_req_nomem(state->tls_stream, req)) {
1738
0
    return tevent_req_post(req, ev);
1739
0
  }
1740
0
  ZERO_STRUCTP(tlss);
1741
0
  talloc_set_destructor(tlss, tstream_tls_destructor);
1742
0
  tlss->plain_stream = plain_stream;
1743
0
  tlss->is_server = true;
1744
0
  tlss->current_ev = ev;
1745
1746
0
  status = tstream_tls_prepare_gnutls(_tlsp, tlss);
1747
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1748
0
    tevent_req_oom(req);
1749
0
    return tevent_req_post(req, ev);
1750
0
  }
1751
0
  if (!NT_STATUS_IS_OK(status)) {
1752
0
    tevent_req_error(req, EINVAL);
1753
0
    return tevent_req_post(req, ev);
1754
0
  }
1755
1756
0
  gnutls_transport_set_ptr(tlss->tls_session,
1757
0
         (gnutls_transport_ptr_t)state->tls_stream);
1758
0
  gnutls_transport_set_pull_function(tlss->tls_session,
1759
0
             (gnutls_pull_func)tstream_tls_pull_function);
1760
0
  gnutls_transport_set_push_function(tlss->tls_session,
1761
0
             (gnutls_push_func)tstream_tls_push_function);
1762
1763
0
  tlss->handshake.req = req;
1764
0
  tstream_tls_retry_handshake(state->tls_stream);
1765
0
  if (!tevent_req_is_in_progress(req)) {
1766
0
    return tevent_req_post(req, ev);
1767
0
  }
1768
1769
0
  return req;
1770
0
}
1771
1772
static void tstream_tls_retry_handshake(struct tstream_context *stream)
1773
0
{
1774
0
  struct tstream_tls *tlss =
1775
0
    tstream_context_data(stream,
1776
0
    struct tstream_tls);
1777
0
  struct tevent_req *req = tlss->handshake.req;
1778
0
  NTSTATUS status;
1779
0
  int ret;
1780
1781
0
  if (tlss->error != 0) {
1782
0
    tevent_req_error(req, tlss->error);
1783
0
    return;
1784
0
  }
1785
1786
0
  ret = gnutls_handshake(tlss->tls_session);
1787
0
  if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
1788
0
    return;
1789
0
  }
1790
1791
0
  tlss->handshake.req = NULL;
1792
1793
0
  if (gnutls_error_is_fatal(ret) != 0) {
1794
0
    DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1795
0
    tlss->error = EIO;
1796
0
    tevent_req_error(req, tlss->error);
1797
0
    return;
1798
0
  }
1799
1800
0
  if (ret != GNUTLS_E_SUCCESS) {
1801
0
    DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1802
0
    tlss->error = EIO;
1803
0
    tevent_req_error(req, tlss->error);
1804
0
    return;
1805
0
  }
1806
1807
0
  status = tstream_tls_verify_peer(tlss);
1808
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_IMAGE_CERT_REVOKED)) {
1809
0
    tlss->error = EINVAL;
1810
0
    tevent_req_error(req, tlss->error);
1811
0
    return;
1812
0
  }
1813
0
  if (!NT_STATUS_IS_OK(status)) {
1814
0
    tlss->error = EIO;
1815
0
    tevent_req_error(req, tlss->error);
1816
0
    return;
1817
0
  }
1818
1819
0
  status = tstream_tls_setup_channel_bindings(tlss);
1820
0
  if (!NT_STATUS_IS_OK(status)) {
1821
0
    tlss->error = EIO;
1822
0
    tevent_req_error(req, tlss->error);
1823
0
    return;
1824
0
  }
1825
1826
0
  if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
1827
0
    tlss->waiting_flush.mgmt_req = req;
1828
0
    return;
1829
0
  }
1830
1831
0
  tevent_req_done(req);
1832
0
}
1833
1834
int tstream_tls_accept_recv(struct tevent_req *req,
1835
          int *perrno,
1836
          TALLOC_CTX *mem_ctx,
1837
          struct tstream_context **tls_stream)
1838
0
{
1839
0
  struct tstream_tls_accept_state *state =
1840
0
    tevent_req_data(req,
1841
0
    struct tstream_tls_accept_state);
1842
1843
0
  if (tevent_req_is_unix_error(req, perrno)) {
1844
0
    tevent_req_received(req);
1845
0
    return -1;
1846
0
  }
1847
1848
0
  *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1849
0
  tevent_req_received(req);
1850
0
  return 0;
1851
0
}
1852
1853
struct tstream_tls_sync {
1854
  struct tstream_tls *tlss;
1855
  void *io_private;
1856
  ssize_t (*io_send_fn)(void *io_private,
1857
            const uint8_t *buf,
1858
            size_t len);
1859
  ssize_t (*io_recv_fn)(void *io_private,
1860
            uint8_t *buf,
1861
            size_t len);
1862
};
1863
1864
const DATA_BLOB *tstream_tls_sync_channel_bindings(struct tstream_tls_sync *tlsss)
1865
0
{
1866
0
  return &tlsss->tlss->channel_bindings;
1867
0
}
1868
1869
static ssize_t tstream_tls_sync_push_function(gnutls_transport_ptr_t ptr,
1870
                const void *buf, size_t size)
1871
0
{
1872
0
  struct tstream_tls_sync *tlsss =
1873
0
    talloc_get_type_abort(ptr,
1874
0
    struct tstream_tls_sync);
1875
1876
0
  return tlsss->io_send_fn(tlsss->io_private, buf, size);
1877
0
}
1878
1879
static ssize_t tstream_tls_sync_pull_function(gnutls_transport_ptr_t ptr,
1880
                void *buf, size_t size)
1881
0
{
1882
0
  struct tstream_tls_sync *tlsss =
1883
0
    talloc_get_type_abort(ptr,
1884
0
    struct tstream_tls_sync);
1885
1886
0
  return tlsss->io_recv_fn(tlsss->io_private, buf, size);
1887
0
}
1888
1889
ssize_t tstream_tls_sync_read(struct tstream_tls_sync *tlsss,
1890
            void *buf, size_t len)
1891
0
{
1892
0
  int ret;
1893
1894
0
  ret = gnutls_record_recv(tlsss->tlss->tls_session, buf, len);
1895
0
  if (ret == GNUTLS_E_INTERRUPTED) {
1896
0
    errno = EINTR;
1897
0
    return -1;
1898
0
  }
1899
0
  if (ret == GNUTLS_E_AGAIN) {
1900
0
    errno = EAGAIN;
1901
0
    return -1;
1902
0
  }
1903
1904
0
  if (ret < 0) {
1905
0
    DBG_WARNING("TLS gnutls_record_recv(%zu) - %s\n",
1906
0
          (size_t)len, gnutls_strerror(ret));
1907
0
    errno = EIO;
1908
0
    return -1;
1909
0
  }
1910
1911
0
  return ret;
1912
0
}
1913
1914
ssize_t tstream_tls_sync_write(struct tstream_tls_sync *tlsss,
1915
             const void *buf, size_t len)
1916
0
{
1917
0
  int ret;
1918
1919
0
  ret = gnutls_record_send(tlsss->tlss->tls_session, buf, len);
1920
0
  if (ret == GNUTLS_E_INTERRUPTED) {
1921
0
    errno = EINTR;
1922
0
    return -1;
1923
0
  }
1924
0
  if (ret == GNUTLS_E_AGAIN) {
1925
0
    errno = EAGAIN;
1926
0
    return -1;
1927
0
  }
1928
1929
0
  if (ret < 0) {
1930
0
    DBG_WARNING("TLS gnutls_record_send(%zu) - %s\n",
1931
0
          (size_t)len, gnutls_strerror(ret));
1932
0
    errno = EIO;
1933
0
    return -1;
1934
0
  }
1935
1936
0
  return ret;
1937
0
}
1938
1939
size_t tstream_tls_sync_pending(struct tstream_tls_sync *tlsss)
1940
0
{
1941
0
  return gnutls_record_check_pending(tlsss->tlss->tls_session);
1942
0
}
1943
1944
NTSTATUS tstream_tls_sync_setup(struct tstream_tls_params *_tls_params,
1945
        void *io_private,
1946
        ssize_t (*io_send_fn)(void *io_private,
1947
                  const uint8_t *buf,
1948
                  size_t len),
1949
        ssize_t (*io_recv_fn)(void *io_private,
1950
                  uint8_t *buf,
1951
                  size_t len),
1952
        TALLOC_CTX *mem_ctx,
1953
        struct tstream_tls_sync **_tlsss)
1954
0
{
1955
0
  struct tstream_tls_sync *tlsss = NULL;
1956
0
  struct tstream_tls *tlss = NULL;
1957
0
  NTSTATUS status;
1958
0
  int ret;
1959
1960
0
  tlsss = talloc_zero(mem_ctx, struct tstream_tls_sync);
1961
0
  if (tlsss == NULL) {
1962
0
    return NT_STATUS_NO_MEMORY;
1963
0
  }
1964
1965
0
  tlsss->io_private = io_private;
1966
0
  tlsss->io_send_fn = io_send_fn;
1967
0
  tlsss->io_recv_fn = io_recv_fn;
1968
1969
0
  tlss = talloc_zero(tlsss, struct tstream_tls);
1970
0
  if (tlss == NULL) {
1971
0
    TALLOC_FREE(tlsss);
1972
0
    return NT_STATUS_NO_MEMORY;
1973
0
  }
1974
0
  talloc_set_destructor(tlss, tstream_tls_destructor);
1975
0
  tlss->is_server = false;
1976
1977
0
  tlsss->tlss = tlss;
1978
1979
0
  status = tstream_tls_prepare_gnutls(_tls_params, tlss);
1980
0
  if (!NT_STATUS_IS_OK(status)) {
1981
0
    TALLOC_FREE(tlsss);
1982
0
    return status;
1983
0
  }
1984
1985
0
  gnutls_transport_set_ptr(tlss->tls_session,
1986
0
         (gnutls_transport_ptr_t)tlsss);
1987
0
  gnutls_transport_set_pull_function(tlss->tls_session,
1988
0
             (gnutls_pull_func)tstream_tls_sync_pull_function);
1989
0
  gnutls_transport_set_push_function(tlss->tls_session,
1990
0
             (gnutls_push_func)tstream_tls_sync_push_function);
1991
1992
0
  do {
1993
    /*
1994
     * The caller should have the socket blocking
1995
     * and do the timeout handling in the
1996
     * io_send/recv_fn
1997
     */
1998
0
    ret = gnutls_handshake(tlss->tls_session);
1999
0
  } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
2000
2001
0
  if (gnutls_error_is_fatal(ret) != 0) {
2002
0
    TALLOC_FREE(tlsss);
2003
0
    return gnutls_error_to_ntstatus(ret,
2004
0
        NT_STATUS_CRYPTO_SYSTEM_INVALID);
2005
0
  }
2006
2007
0
  if (ret != GNUTLS_E_SUCCESS) {
2008
0
    TALLOC_FREE(tlsss);
2009
0
    return gnutls_error_to_ntstatus(ret,
2010
0
        NT_STATUS_CRYPTO_SYSTEM_INVALID);
2011
0
  }
2012
2013
0
  status = tstream_tls_verify_peer(tlss);
2014
0
  if (!NT_STATUS_IS_OK(status)) {
2015
0
    TALLOC_FREE(tlsss);
2016
0
    return status;
2017
0
  }
2018
2019
0
  status = tstream_tls_setup_channel_bindings(tlss);
2020
0
  if (!NT_STATUS_IS_OK(status)) {
2021
0
    TALLOC_FREE(tlsss);
2022
0
    return status;
2023
0
  }
2024
2025
0
  *_tlsss = tlsss;
2026
0
  return NT_STATUS_OK;
2027
0
}
2028
2029
struct tstream_tls_quic_handshake_state {
2030
  struct tstream_tls *tlss;
2031
  int sockfd;
2032
  struct tevent_fd *fde;
2033
#ifdef HAVE_LIBQUIC
2034
  struct quic_handshake_step *step;
2035
#endif /* HAVE_LIBQUIC */
2036
};
2037
2038
#ifdef HAVE_LIBQUIC
2039
static void tstream_tls_quic_handshake_cleanup(struct tevent_req *req,
2040
                 enum tevent_req_state req_state);
2041
static void tstream_tls_quic_handshake_run(struct tevent_req *req);
2042
static void tstream_tls_quic_handshake_fde(struct tevent_context *ev,
2043
             struct tevent_fd *fde,
2044
             uint16_t flags,
2045
             void *private_data);
2046
static void tstream_tls_quic_handshake_done(struct tevent_req *req);
2047
#endif /* HAVE_LIBQUIC */
2048
2049
struct tevent_req *tstream_tls_quic_handshake_send(TALLOC_CTX *mem_ctx,
2050
               struct tevent_context *ev,
2051
               struct tstream_tls_params *tlsp,
2052
               bool is_server,
2053
               uint32_t timeout_msec,
2054
               const char *alpn,
2055
               int sockfd)
2056
0
{
2057
0
  struct tevent_req *req = NULL;
2058
0
  struct tstream_tls_quic_handshake_state *state = NULL;
2059
#ifdef HAVE_LIBQUIC
2060
  NTSTATUS status;
2061
  int ret;
2062
#endif /* HAVE_LIBQUIC */
2063
0
  bool ok;
2064
2065
0
  req = tevent_req_create(mem_ctx, &state,
2066
0
        struct tstream_tls_quic_handshake_state);
2067
0
  if (req == NULL) {
2068
0
    return NULL;
2069
0
  }
2070
0
  state->sockfd = sockfd;
2071
2072
0
  ok = tevent_req_set_endtime(req, ev,
2073
0
            timeval_current_ofs_msec(timeout_msec));
2074
0
  if (!ok) {
2075
0
    tevent_req_oom(req);
2076
0
    return tevent_req_post(req, ev);
2077
0
  }
2078
2079
0
  ok = tstream_tls_params_quic_enabled(tlsp);
2080
0
  if (!ok) {
2081
0
    goto invalid_parameter_mix;
2082
0
  }
2083
2084
#ifdef HAVE_LIBQUIC
2085
  state->tlss = talloc_zero(state, struct tstream_tls);
2086
  if (tevent_req_nomem(state->tlss, req)) {
2087
    return tevent_req_post(req, ev);
2088
  }
2089
  talloc_set_destructor(state->tlss, tstream_tls_destructor);
2090
  state->tlss->is_server = is_server;
2091
2092
  status = tstream_tls_prepare_gnutls(tlsp, state->tlss);
2093
  if (tevent_req_nterror(req, status)) {
2094
    return tevent_req_post(req, ev);
2095
  }
2096
2097
  ret = quic_session_set_alpn(state->tlss->tls_session, alpn, strlen(alpn));
2098
  if (ret != 0) {
2099
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2100
    return tevent_req_post(req, ev);
2101
  }
2102
2103
  gnutls_transport_set_int(state->tlss->tls_session, state->sockfd);
2104
2105
  ret = quic_handshake_init(state->tlss->tls_session, &state->step);
2106
  if (ret != 0) {
2107
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2108
    return tevent_req_post(req, ev);
2109
  }
2110
2111
  tevent_req_set_cleanup_fn(req, tstream_tls_quic_handshake_cleanup);
2112
2113
  state->fde = tevent_add_fd(ev,
2114
           state,
2115
           state->sockfd,
2116
           TEVENT_FD_ERROR | TEVENT_FD_READ,
2117
           tstream_tls_quic_handshake_fde,
2118
           req);
2119
  if (tevent_req_nomem(state->fde, req)) {
2120
    return tevent_req_post(req, ev);
2121
  }
2122
2123
  tstream_tls_quic_handshake_run(req);
2124
  if (!tevent_req_is_in_progress(req)) {
2125
    return tevent_req_post(req, ev);
2126
  }
2127
2128
  return req;
2129
#endif /* HAVE_LIBQUIC */
2130
0
invalid_parameter_mix:
2131
0
  tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2132
0
  return tevent_req_post(req, ev);
2133
0
}
2134
2135
#ifdef HAVE_LIBQUIC
2136
static void tstream_tls_quic_handshake_cleanup(struct tevent_req *req,
2137
                 enum tevent_req_state req_state)
2138
{
2139
  struct tstream_tls_quic_handshake_state *state =
2140
    tevent_req_data(req,
2141
    struct tstream_tls_quic_handshake_state);
2142
2143
  if (state->tlss == NULL) {
2144
    return;
2145
  }
2146
2147
  TALLOC_FREE(state->fde);
2148
  quic_handshake_deinit(state->tlss->tls_session);
2149
  TALLOC_FREE(state->tlss);
2150
}
2151
2152
static void tstream_tls_quic_handshake_run(struct tevent_req *req)
2153
{
2154
  struct tstream_tls_quic_handshake_state *state =
2155
    tevent_req_data(req,
2156
    struct tstream_tls_quic_handshake_state);
2157
  struct tstream_tls *tlss = state->tlss;
2158
  struct quic_handshake_step_sendmsg *smsg = NULL;
2159
  struct quic_handshake_step_recvmsg *rmsg = NULL;
2160
  ssize_t len;
2161
  int ret;
2162
2163
next_step:
2164
2165
  SMB_ASSERT(state->step != NULL);
2166
  len = 0;
2167
2168
  switch (state->step->op) {
2169
  case QUIC_HANDSHAKE_STEP_OP_SENDMSG:
2170
    smsg = &state->step->s_sendmsg;
2171
    len = sendmsg(state->sockfd,
2172
            smsg->msg,
2173
            smsg->flags |
2174
            MSG_NOSIGNAL |
2175
            MSG_DONTWAIT);
2176
    if (len == -1 && errno == EINTR) {
2177
      /* do it again */
2178
      goto next_step;
2179
    }
2180
    if (len == -1 && (
2181
        errno == EAGAIN ||
2182
        errno == EWOULDBLOCK))
2183
    {
2184
      TEVENT_FD_WRITEABLE(state->fde);
2185
      return;
2186
    }
2187
    if (len == -1) {
2188
      len = -errno;
2189
    }
2190
    if (len == 0) {
2191
      len = -ECONNRESET;
2192
    }
2193
    smsg->retval = len;
2194
    break;
2195
  case QUIC_HANDSHAKE_STEP_OP_RECVMSG:
2196
    rmsg = &state->step->s_recvmsg;
2197
    len = recvmsg(state->sockfd,
2198
            rmsg->msg,
2199
            rmsg->flags |
2200
            MSG_DONTWAIT);
2201
    if (len == -1 && errno == EINTR) {
2202
      /* do it again */
2203
      goto next_step;
2204
    }
2205
    if (len == -1 && (
2206
        errno == EAGAIN ||
2207
        errno == EWOULDBLOCK))
2208
    {
2209
      return;
2210
    }
2211
    if (len == -1) {
2212
      len = -errno;
2213
    }
2214
    if (len == 0) {
2215
      len = -ECONNRESET;
2216
    }
2217
    rmsg->retval = len;
2218
    break;
2219
  }
2220
2221
  if (len == 0) {
2222
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2223
    return;
2224
  }
2225
2226
  ret = quic_handshake_step(tlss->tls_session, &state->step);
2227
  if (ret != 0) {
2228
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2229
    return;
2230
  }
2231
2232
  if (state->step == NULL) {
2233
    tstream_tls_quic_handshake_done(req);
2234
    return;
2235
  }
2236
2237
  goto next_step;
2238
};
2239
2240
static void tstream_tls_quic_handshake_fde(struct tevent_context *ev,
2241
             struct tevent_fd *fde,
2242
             uint16_t flags,
2243
             void *private_data)
2244
{
2245
  struct tevent_req *req =
2246
    talloc_get_type_abort(private_data,
2247
    struct tevent_req);
2248
  struct tstream_tls_quic_handshake_state *state =
2249
    tevent_req_data(req,
2250
    struct tstream_tls_quic_handshake_state);
2251
2252
  TEVENT_FD_NOT_WRITEABLE(state->fde);
2253
  tstream_tls_quic_handshake_run(req);
2254
}
2255
2256
static void tstream_tls_quic_handshake_done(struct tevent_req *req)
2257
{
2258
  struct tstream_tls_quic_handshake_state *state =
2259
    tevent_req_data(req,
2260
    struct tstream_tls_quic_handshake_state);
2261
2262
  if (!state->tlss->is_server) {
2263
    struct quic_stream_info info = {};
2264
    unsigned int optlen = sizeof(info);
2265
    NTSTATUS status;
2266
    int ret;
2267
2268
    status = tstream_tls_verify_peer(state->tlss);
2269
    if (tevent_req_nterror(req, status)) {
2270
      return;
2271
    }
2272
2273
    /*
2274
     * Use the next stream_id (0) as default
2275
     * client stream.
2276
     */
2277
    info.stream_id = -1;
2278
    ret = getsockopt(state->sockfd,
2279
         SOL_QUIC,
2280
         QUIC_SOCKOPT_STREAM_OPEN,
2281
         &info,
2282
         &optlen);
2283
    if (ret != 0) {
2284
      tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2285
      return;
2286
    }
2287
  }
2288
2289
  tevent_req_done(req);
2290
}
2291
#endif /* HAVE_LIBQUIC */
2292
2293
NTSTATUS tstream_tls_quic_handshake_recv(struct tevent_req *req)
2294
0
{
2295
0
  return tevent_req_simple_recv_ntstatus(req);
2296
0
}
2297
2298
NTSTATUS tstream_tls_quic_handshake(struct tstream_tls_params *tlsp,
2299
            bool is_server,
2300
            uint32_t timeout_msec,
2301
            const char *alpn,
2302
            int sockfd)
2303
0
{
2304
0
  TALLOC_CTX *frame = talloc_stackframe();
2305
0
  struct tevent_context *ev;
2306
0
  struct tevent_req *req;
2307
0
  NTSTATUS status = NT_STATUS_NO_MEMORY;
2308
2309
0
  ev = samba_tevent_context_init(frame);
2310
0
  if (ev == NULL) {
2311
0
    goto fail;
2312
0
  }
2313
0
  req = tstream_tls_quic_handshake_send(ev,
2314
0
                ev,
2315
0
                tlsp,
2316
0
                is_server,
2317
0
                timeout_msec,
2318
0
                alpn,
2319
0
                sockfd);
2320
0
  if (req == NULL) {
2321
0
    goto fail;
2322
0
  }
2323
0
  if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2324
0
    goto fail;
2325
0
  }
2326
0
  status = tstream_tls_quic_handshake_recv(req);
2327
0
fail:
2328
0
  TALLOC_FREE(frame);
2329
0
  return status;
2330
0
}
2331
2332
#ifdef HAVE_LIBNGTCP2
2333
2334
static const struct tstream_context_ops tstream_ngtcp2_ops;
2335
2336
struct tstream_ngtcp2_buffer {
2337
  struct tstream_ngtcp2_buffer *prev, *next;
2338
  uint64_t offset;
2339
  size_t length;
2340
  uint8_t buffer[NGTCP2_MAX_PMTUD_UDP_PAYLOAD_SIZE];
2341
};
2342
2343
struct tstream_ngtcp2 {
2344
  struct tdgram_context *plain_dgram;
2345
  int error;
2346
2347
  ngtcp2_tstamp last_expire;
2348
  ngtcp2_crypto_conn_ref conn_ref;
2349
  ngtcp2_conn *conn;
2350
  int64_t stream_id;
2351
  struct samba_sockaddr laddr;
2352
  struct samba_sockaddr raddr;
2353
  ngtcp2_path path;
2354
2355
  struct tevent_context *current_ev;
2356
2357
  struct tevent_immediate *retry_im;
2358
  uint32_t keepalive_usecs;
2359
  struct tevent_timer *keepalive_timer;
2360
2361
  struct {
2362
    struct tstream_tls *tlss;
2363
    struct tevent_req *req;
2364
    bool done;
2365
  } handshake;
2366
2367
  struct {
2368
    struct tstream_ngtcp2_buffer b;
2369
    struct tevent_req *subreq;
2370
    uint64_t blocked;
2371
  } push;
2372
2373
  struct {
2374
    struct tstream_ngtcp2_buffer b;
2375
    struct tevent_req *subreq;
2376
  } pull;
2377
2378
  struct {
2379
    struct tstream_ngtcp2_buffer *pushed;
2380
    uint64_t pushed_offset;
2381
    struct tstream_ngtcp2_buffer *pending;
2382
    struct tevent_req *req;
2383
  } writev;
2384
2385
  struct {
2386
    struct tstream_ngtcp2_buffer *buffers;
2387
    struct tevent_req *req;
2388
  } readv;
2389
2390
  struct {
2391
    struct tevent_req *req;
2392
  } disconnect;
2393
2394
  struct {
2395
    struct tevent_req *req;
2396
  } monitor;
2397
};
2398
2399
static void tstream_ngtcp2_close_stream(struct tstream_ngtcp2 *si);
2400
static void tstream_ngtcp2_retry_handshake(struct tstream_context *stream);
2401
static void tstream_ngtcp2_timer_start(struct tstream_context *stream);
2402
static void tstream_ngtcp2_timer_handler(struct tevent_context *ev,
2403
           struct tevent_timer *te,
2404
           struct timeval current_time,
2405
           void *private_data);
2406
static void tstream_ngtcp2_sendto_start(struct tstream_context *stream);
2407
static void tstream_ngtcp2_sendto_done(struct tevent_req *subreq);
2408
static void tstream_ngtcp2_recvfrom_start(struct tstream_context *stream);
2409
static void tstream_ngtcp2_recvfrom_done(struct tevent_req *subreq);
2410
static void tstream_ngtcp2_readv_retry(struct tstream_context *stream);
2411
static void tstream_ngtcp2_writev_retry(struct tstream_context *stream);
2412
static void tstream_ngtcp2_monitor_retry(struct tstream_context *stream);
2413
static void tstream_ngtcp2_deferred_retry(struct tstream_context *stream);
2414
2415
static ngtcp2_conn *qwrap_ngtcp2_conn_ref_get_conn(ngtcp2_crypto_conn_ref *conn_ref)
2416
{
2417
  struct tstream_context *stream =
2418
    talloc_get_type_abort(conn_ref->user_data,
2419
    struct tstream_context);
2420
  struct tstream_ngtcp2 *si =
2421
    tstream_context_data(stream,
2422
    struct tstream_ngtcp2);
2423
2424
  return si->conn;
2425
}
2426
2427
static bool tstream_ngtcp2_verbose;
2428
2429
static void tstream_ngtcp2_log_printf(void *user_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
2430
static void tstream_ngtcp2_log_printf(void *user_data, const char *fmt, ...)
2431
{
2432
  if (tstream_ngtcp2_verbose) {
2433
    char buffer[1024];
2434
    va_list ap;
2435
    struct timespec ts = timespec_current();
2436
    struct timeval_buf tsbuf;
2437
2438
    va_start(ap, fmt);
2439
    vsnprintf(buffer, sizeof(buffer), fmt, ap);
2440
    va_end(ap);
2441
2442
    D_ERR("NGTCP2:%s: %s\n",
2443
          timespec_string_buf(&ts, true, &tsbuf),
2444
          buffer);
2445
  }
2446
}
2447
2448
static void tstream_ngtcp2_qlog_write_cb(void *user_data, uint32_t flags,
2449
               const void *data, size_t datalen)
2450
{
2451
  if (tstream_ngtcp2_verbose) {
2452
    struct timespec ts = timespec_current();
2453
    struct timeval_buf tsbuf;
2454
2455
    D_ERR("NGTCP2:%s: flags[%"PRIu32"] len[%zu] %*.*s\n",
2456
          timespec_string_buf(&ts, true, &tsbuf),
2457
          flags, datalen,
2458
          (int)datalen, (int)datalen, (const char *)data);
2459
  }
2460
}
2461
2462
static inline ngtcp2_tstamp timespec2ngtcp2_tstamp(struct timespec ts)
2463
{
2464
  return (uint64_t)ts.tv_sec * NGTCP2_SECONDS + (uint64_t)ts.tv_nsec;
2465
}
2466
2467
static inline struct timespec ngtcp2_tstamp2timespec(ngtcp2_tstamp _ts,
2468
                 ngtcp2_duration rtc_offset)
2469
{
2470
  ngtcp2_tstamp ts = _ts + rtc_offset;
2471
  return (struct timespec) {
2472
    .tv_sec = ts / NGTCP2_SECONDS,
2473
    .tv_nsec = ts % NGTCP2_SECONDS,
2474
  };
2475
}
2476
2477
static inline struct timeval timespec2timeval(struct timespec ts)
2478
{
2479
  return (struct timeval) {
2480
    .tv_sec = ts.tv_sec,
2481
    .tv_usec = ts.tv_nsec / 1000,
2482
  };
2483
}
2484
2485
static ngtcp2_tstamp _tstream_ngtcp2_timestamp(ngtcp2_duration *_rtc_offsetp,
2486
                 const char *func,
2487
                 unsigned line)
2488
{
2489
  struct timespec ts_rtc = { .tv_sec = 0, };
2490
  struct timespec ts_mono;
2491
  ngtcp2_tstamp ret_rtc = 0;
2492
  ngtcp2_tstamp ret_mono;
2493
  bool need_rtc_offset = false;
2494
  ngtcp2_duration rtc_offset = 0;
2495
2496
  if (_rtc_offsetp != NULL || CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
2497
    need_rtc_offset = true;
2498
  }
2499
2500
  if (need_rtc_offset) {
2501
    ts_rtc = timespec_current();
2502
    ret_rtc = timespec2ngtcp2_tstamp(ts_rtc);
2503
  }
2504
2505
  clock_gettime_mono(&ts_mono);
2506
  ret_mono = timespec2ngtcp2_tstamp(ts_mono);
2507
2508
  if (need_rtc_offset) {
2509
    rtc_offset = ret_rtc - ret_mono;
2510
  }
2511
2512
  if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
2513
    struct timeval_buf rtc_buf;
2514
2515
    DBG_DEBUG("%s:%s:%u: rtc_offset=%"PRIu64" stamp=%"PRIu64"\n",
2516
        timespec_string_buf(&ts_rtc, true, &rtc_buf),
2517
        func, line, rtc_offset, ret_mono);
2518
  }
2519
2520
  if (_rtc_offsetp != NULL) {
2521
    *_rtc_offsetp = rtc_offset;
2522
  }
2523
2524
  return ret_mono;
2525
}
2526
#define tstream_ngtcp2_timestamp(__rtc_offsetp) \
2527
  _tstream_ngtcp2_timestamp(__rtc_offsetp, __func__, __LINE__)
2528
2529
static int tstream_ngtcp2_recv_stream_data_cb(ngtcp2_conn *conn, uint32_t flags,
2530
                int64_t stream_id, uint64_t offset,
2531
                const uint8_t *data, size_t datalen,
2532
                void *user_data, void *stream_user_data)
2533
{
2534
  struct tstream_context *stream =
2535
    talloc_get_type_abort(user_data,
2536
    struct tstream_context);
2537
  struct tstream_ngtcp2 *si =
2538
    tstream_context_data(stream,
2539
    struct tstream_ngtcp2);
2540
  struct tstream_ngtcp2_buffer *cbuf = NULL;
2541
2542
  DBG_DEBUG("Called stream_id[%"PRIi64"] "
2543
      "offset[%"PRIu64"] datalen[%"PRIu64"]\n",
2544
      stream_id, offset, datalen);
2545
2546
  if (si->stream_id != stream_id) {
2547
    return NGTCP2_ERR_STREAM_NOT_FOUND;
2548
  }
2549
2550
next_buf:
2551
  cbuf = talloc(si, struct tstream_ngtcp2_buffer);
2552
  if (cbuf == NULL) {
2553
    return NGTCP2_ERR_NOMEM;
2554
  }
2555
  cbuf->prev = cbuf->next = NULL;
2556
  cbuf->offset = 0;
2557
  cbuf->length = MIN(ARRAY_SIZE(cbuf->buffer), datalen);
2558
  memcpy(cbuf->buffer, data, cbuf->length);
2559
  DLIST_ADD_END(si->readv.buffers, cbuf);
2560
2561
  data += cbuf->length;
2562
  datalen -= cbuf->length;
2563
  if (datalen > 0) {
2564
    goto next_buf;
2565
  }
2566
2567
  return 0;
2568
}
2569
2570
static int tstream_ngtcp2_acked_stream_data_offset_cb(ngtcp2_conn *conn,
2571
                  int64_t stream_id,
2572
                  uint64_t offset,
2573
                  uint64_t datalen,
2574
                  void *user_data,
2575
                  void *stream_user_data)
2576
{
2577
  struct tstream_context *stream =
2578
    talloc_get_type_abort(user_data,
2579
    struct tstream_context);
2580
  struct tstream_ngtcp2 *si =
2581
    tstream_context_data(stream,
2582
    struct tstream_ngtcp2);
2583
  struct tstream_ngtcp2_buffer *cbuf = NULL;
2584
  struct tstream_ngtcp2_buffer *cnext = NULL;
2585
2586
  DBG_DEBUG("Called stream_id[%"PRIi64"] "
2587
      "offset[%"PRIu64"] datalen[%"PRIu64"]\n",
2588
      stream_id, offset, datalen);
2589
2590
  if (si->stream_id != stream_id) {
2591
    return NGTCP2_ERR_STREAM_NOT_FOUND;
2592
  }
2593
2594
  for (cbuf = si->writev.pushed; cbuf != NULL; cbuf = cnext) {
2595
    cnext = cbuf->next;
2596
2597
    if (cbuf->offset != offset) {
2598
      continue;
2599
    }
2600
    if (cbuf->length != datalen) {
2601
      continue;
2602
    }
2603
2604
    DBG_DEBUG("REMOVE pushed[%"PRIu64"][%zd]\n",
2605
        cbuf->offset, cbuf->length);
2606
    DLIST_REMOVE(si->writev.pushed, cbuf);
2607
    TALLOC_FREE(cbuf);
2608
  }
2609
2610
  DBG_DEBUG("SI stream_id[%"PRIi64"] "
2611
      "offset[%"PRIu64"] pushed[%"PRIu64"][%zd]\n",
2612
      si->stream_id, si->writev.pushed_offset,
2613
      si->writev.pushed ? si->writev.pushed->offset : 0,
2614
      si->writev.pushed ? (ssize_t)si->writev.pushed->length : -1);
2615
2616
  return 0;
2617
}
2618
2619
static int tstream_ngtcp2_stream_close_cb(ngtcp2_conn *conn,
2620
            uint32_t flags,
2621
            int64_t stream_id,
2622
            uint64_t app_error_code,
2623
            void *user_data,
2624
            void *stream_user_data)
2625
{
2626
  struct tstream_context *stream =
2627
    talloc_get_type_abort(user_data,
2628
    struct tstream_context);
2629
  struct tstream_ngtcp2 *si =
2630
    tstream_context_data(stream,
2631
    struct tstream_ngtcp2);
2632
2633
  DBG_WARNING("Called stream_id[%"PRIi64"] "
2634
        "flags[0x%x] app_error_code[%"PRIu64"]\n",
2635
        stream_id, flags, app_error_code);
2636
2637
  if (si->stream_id != stream_id) {
2638
    return NGTCP2_ERR_STREAM_NOT_FOUND;
2639
  }
2640
2641
  return 0;
2642
}
2643
2644
static int tstream_ngtcp2_recv_stateless_reset_cb(ngtcp2_conn *conn,
2645
          const ngtcp2_pkt_stateless_reset *sr,
2646
          void *user_data)
2647
{
2648
  struct tstream_context *stream =
2649
    talloc_get_type_abort(user_data,
2650
    struct tstream_context);
2651
  struct tstream_ngtcp2 *si =
2652
    tstream_context_data(stream,
2653
    struct tstream_ngtcp2);
2654
2655
  DBG_WARNING("Called stream_id[%"PRIi64"]\n",
2656
        si->stream_id);
2657
2658
  return 0;
2659
}
2660
2661
static void tstream_ngtcp2_rand_cb(uint8_t *dest, size_t destlen,
2662
           const ngtcp2_rand_ctx *rand_ctx)
2663
{
2664
  gnutls_rnd(GNUTLS_RND_RANDOM, dest, destlen);
2665
  return;
2666
}
2667
2668
static int tstream_ngtcp2_get_new_connection_id_cb(ngtcp2_conn *conn,
2669
               ngtcp2_cid *cid,
2670
               uint8_t *token,
2671
               size_t cidlen,
2672
               void *user_data)
2673
{
2674
  int ret;
2675
2676
  ret = gnutls_rnd(GNUTLS_RND_RANDOM, cid->data, cidlen);
2677
  if (ret != 0) {
2678
    return NGTCP2_ERR_CALLBACK_FAILURE;
2679
  }
2680
2681
  cid->datalen = cidlen;
2682
2683
  ret = gnutls_rnd(GNUTLS_RND_RANDOM, token,
2684
       NGTCP2_STATELESS_RESET_TOKENLEN);
2685
  if (ret != 0) {
2686
    return NGTCP2_ERR_CALLBACK_FAILURE;
2687
  }
2688
2689
  return 0;
2690
}
2691
2692
static int tstream_ngtcp2_stream_reset_cb(ngtcp2_conn *conn,
2693
            int64_t stream_id,
2694
            uint64_t final_size,
2695
            uint64_t app_error_code,
2696
            void *user_data,
2697
            void *stream_user_data)
2698
{
2699
  struct tstream_context *stream =
2700
    talloc_get_type_abort(user_data,
2701
    struct tstream_context);
2702
  struct tstream_ngtcp2 *si =
2703
    tstream_context_data(stream,
2704
    struct tstream_ngtcp2);
2705
2706
  DBG_WARNING("Called stream_id[%"PRIi64"] "
2707
        "final_size[%"PRIu64"] app_error_code[%"PRIu64"]\n",
2708
        stream_id, final_size, app_error_code);
2709
2710
  if (si->stream_id != stream_id) {
2711
    return NGTCP2_ERR_STREAM_NOT_FOUND;
2712
  }
2713
2714
  return 0;
2715
}
2716
2717
static int tstream_ngtcp2_destructor(struct tstream_ngtcp2 *si)
2718
{
2719
  /*
2720
   * We want tevent_req_poll()
2721
   * to return without any blocking.
2722
   *
2723
   * So we use tevent_context_set_wait_timeout(0)
2724
   * that will cause tevent_loop_once() in
2725
   * tevent_req_poll() to break with ENODATA.
2726
   */
2727
  si->current_ev = samba_tevent_context_init(NULL);
2728
  if (si->current_ev != NULL) {
2729
    tevent_context_set_wait_timeout(si->current_ev, 0);
2730
  }
2731
  tevent_reset_immediate(si->retry_im);
2732
  tstream_ngtcp2_close_stream(si);
2733
  if (si->push.subreq != NULL) {
2734
    /*
2735
     * We don't care about any success,
2736
     * we just want to send out the disconnect
2737
     * message if possible without blocking,
2738
     * using tevent_context_set_wait_timeout(0).
2739
     */
2740
    tevent_req_poll(si->push.subreq, si->current_ev);
2741
    TALLOC_FREE(si->push.subreq);
2742
  }
2743
  TALLOC_FREE(si->current_ev);
2744
2745
  return 0;
2746
}
2747
2748
static void tstream_ngtcp2_close_stream(struct tstream_ngtcp2 *si)
2749
{
2750
  struct tstream_ngtcp2_buffer *cbuf = NULL;
2751
  struct tstream_ngtcp2_buffer *cnext = NULL;
2752
  ngtcp2_ccerr ccerr;
2753
  ngtcp2_ssize ret;
2754
2755
  if (si->conn == NULL) {
2756
    return;
2757
  }
2758
2759
  si->error = ECONNABORTED;
2760
2761
  TALLOC_FREE(si->keepalive_timer);
2762
  TALLOC_FREE(si->pull.subreq);
2763
  TALLOC_FREE(si->push.subreq);
2764
2765
  for (cbuf = si->writev.pushed; cbuf != NULL; cbuf = cnext) {
2766
    cnext = cbuf->next;
2767
    DLIST_REMOVE(si->writev.pushed, cbuf);
2768
    TALLOC_FREE(cbuf);
2769
  }
2770
2771
  for (cbuf = si->writev.pending; cbuf != NULL; cbuf = cnext) {
2772
    cnext = cbuf->next;
2773
    DLIST_REMOVE(si->writev.pending, cbuf);
2774
    TALLOC_FREE(cbuf);
2775
  }
2776
2777
  for (cbuf = si->readv.buffers; cbuf != NULL; cbuf = cnext) {
2778
    cnext = cbuf->next;
2779
    DLIST_REMOVE(si->readv.buffers, cbuf);
2780
    TALLOC_FREE(cbuf);
2781
  }
2782
2783
  if (si->disconnect.req != NULL) {
2784
    tevent_req_received(si->disconnect.req);
2785
    si->disconnect.req = NULL;
2786
  }
2787
2788
  if (si->writev.req != NULL) {
2789
    tevent_req_received(si->writev.req);
2790
    si->writev.req = NULL;
2791
  }
2792
2793
  if (si->readv.req != NULL) {
2794
    tevent_req_received(si->readv.req);
2795
    si->readv.req = NULL;
2796
  }
2797
2798
  if (si->monitor.req != NULL) {
2799
    tevent_req_received(si->monitor.req);
2800
    si->monitor.req = NULL;
2801
  }
2802
2803
  ngtcp2_ccerr_default(&ccerr);
2804
  ret = ngtcp2_conn_write_connection_close(si->conn,
2805
             &si->path,
2806
             NULL,
2807
             si->push.b.buffer,
2808
             sizeof(si->push.b.buffer),
2809
             &ccerr,
2810
             tstream_ngtcp2_timestamp(NULL));
2811
  ngtcp2_conn_del(si->conn);
2812
  si->conn = NULL;
2813
2814
  if (ret <= 0) {
2815
    return;
2816
  }
2817
2818
  if (si->current_ev == NULL) {
2819
    return;
2820
  }
2821
2822
  si->push.b.length = ret;
2823
  si->push.subreq = tdgram_sendto_send(si,
2824
               si->current_ev,
2825
               si->plain_dgram,
2826
               si->push.b.buffer,
2827
               si->push.b.length,
2828
               NULL);
2829
  if (si->push.subreq == NULL) {
2830
    return;
2831
  }
2832
2833
  /*
2834
   * We don't call tevent_req_set_callback()
2835
   * here as we don't care about the
2836
   * result by default.
2837
   *
2838
   * We only care in tstream_ngtcp2_disconnect_send()
2839
   * so it's called there.
2840
   */
2841
  return;
2842
}
2843
2844
static void tstream_ngtcp2_retry_handshake(struct tstream_context *stream)
2845
{
2846
  struct tstream_ngtcp2 *si =
2847
    tstream_context_data(stream,
2848
    struct tstream_ngtcp2);
2849
  struct tevent_req *req = si->handshake.req;
2850
  NTSTATUS status;
2851
  ssize_t ret;
2852
2853
  si->handshake.req = NULL;
2854
2855
  if (si->error != 0) {
2856
    DBG_WARNING("si->error[%d] \n", si->error);
2857
    tevent_req_error(req, si->error);
2858
    return;
2859
  }
2860
2861
  if (si->handshake.done) {
2862
    si->error = EINVAL;
2863
    DBG_WARNING("si->error[%d] \n", si->error);
2864
    tevent_req_error(req, si->error);
2865
    return;
2866
  }
2867
2868
  si->handshake.done = ngtcp2_conn_get_handshake_completed(si->conn);
2869
  if (si->handshake.done) {
2870
    goto verify;
2871
  }
2872
2873
  si->handshake.req = req;
2874
  tstream_ngtcp2_sendto_start(stream);
2875
  tstream_ngtcp2_recvfrom_start(stream);
2876
  return;
2877
2878
verify:
2879
  status = tstream_tls_verify_peer(si->handshake.tlss);
2880
  if (NT_STATUS_EQUAL(status, NT_STATUS_IMAGE_CERT_REVOKED)) {
2881
    si->error = EINVAL;
2882
    DBG_WARNING("si->error[%d] \n", si->error);
2883
    tevent_req_error(req, si->error);
2884
    return;
2885
  }
2886
  if (!NT_STATUS_IS_OK(status)) {
2887
    si->error = EIO;
2888
    DBG_WARNING("si->error[%d] \n", si->error);
2889
    tevent_req_error(req, si->error);
2890
    return;
2891
  }
2892
2893
  ret = ngtcp2_conn_open_bidi_stream(si->conn,
2894
             &si->stream_id,
2895
             si);
2896
  if (ret != 0) {
2897
    si->error = EIO;
2898
    DBG_WARNING("si->error[%d] \n", si->error);
2899
    tevent_req_error(req, si->error);
2900
    return;
2901
  }
2902
2903
  /*
2904
   * We don't expect incoming messages for
2905
   * this handshake anymore.
2906
   */
2907
  TALLOC_FREE(si->pull.subreq);
2908
  if (si->push.subreq != NULL) {
2909
    /*
2910
     * But we need to wait until we flushed all
2911
     * pending messages to the kernel socket.
2912
     */
2913
    si->handshake.req = req;
2914
    return;
2915
  }
2916
2917
  tevent_req_done(req);
2918
}
2919
2920
static void tstream_ngtcp2_timer_start(struct tstream_context *stream)
2921
{
2922
  struct tstream_ngtcp2 *si =
2923
    tstream_context_data(stream,
2924
    struct tstream_ngtcp2);
2925
  ngtcp2_tstamp expire = ngtcp2_conn_get_expiry(si->conn);
2926
  struct timespec ts_expire = { .tv_sec = 0, };
2927
  struct timeval tv_expire = { .tv_sec = 0, };
2928
  struct timeval_buf expire_buf;
2929
  ngtcp2_duration rtc_offset = 0;
2930
  ngtcp2_tstamp now = tstream_ngtcp2_timestamp(&rtc_offset);
2931
  struct timespec ts_now = { .tv_sec = 0, };
2932
  struct timeval tv_now = { .tv_sec = 0, };
2933
  struct timeval_buf now_buf;
2934
  int64_t diff = 0;
2935
  bool was_last = (si->last_expire == expire);
2936
2937
  ts_expire = ngtcp2_tstamp2timespec(expire, rtc_offset);
2938
  tv_expire = timespec2timeval(ts_expire);
2939
  ts_now = ngtcp2_tstamp2timespec(now, rtc_offset);
2940
  tv_now = timespec2timeval(ts_now);
2941
2942
  DBG_DEBUG("\nNOW: %s\nEXP: %s\n",
2943
      timespec_string_buf(&ts_now, true, &now_buf),
2944
      timespec_string_buf(&ts_expire, true, &expire_buf));
2945
2946
  diff = expire - now;
2947
2948
  DBG_DEBUG("si->last_expire[%"PRIu64"] %c= expire[%"PRIu64"] "
2949
      "now[%"PRIu64"] diff[%"PRId64"]\n",
2950
      si->last_expire,
2951
      was_last ? '=' : '!',
2952
      expire,
2953
      now,
2954
      diff);
2955
2956
  if (!was_last) {
2957
    si->last_expire = expire;
2958
  }
2959
2960
  if (diff <= 0) {
2961
    /*
2962
     * already expired
2963
     *
2964
     * If we got the same value from
2965
     * ngtcp2_conn_get_expiry() as the
2966
     * last time we should avoid cpu spinning,
2967
     * so we always wait a keepalive cycle.
2968
     *
2969
     * Otherwise we want the timer to fire directly.
2970
     */
2971
    if (was_last) {
2972
      tv_expire = timeval_add(&tv_now, 0, si->keepalive_usecs);
2973
    } else {
2974
      tv_expire = (struct timeval) { .tv_sec = 0, };
2975
    }
2976
  }
2977
2978
  /*
2979
   * If we need to push out pending data from the caller
2980
   * and didn't hit a blocking state from
2981
   * ngtcp2_conn_writev_stream(), we want fire the timer
2982
   * directly.
2983
   */
2984
  if (si->writev.pending != NULL && si->push.blocked == 0) {
2985
    tv_expire = (struct timeval) { .tv_sec = 0, };
2986
  }
2987
2988
  DBG_DEBUG("NEW-TIMER:\nnow: %s\nexp: %s\n",
2989
      timeval_str_buf(&tv_now, false, true, &now_buf),
2990
      timeval_str_buf(&tv_expire, false, true, &expire_buf));
2991
2992
  TALLOC_FREE(si->keepalive_timer);
2993
  si->keepalive_timer = tevent_add_timer(si->current_ev,
2994
                 si,
2995
                 tv_expire,
2996
                 tstream_ngtcp2_timer_handler,
2997
                 stream);
2998
  if (si->keepalive_timer == NULL) {
2999
    si->error = ENOMEM;
3000
    DBG_WARNING("si->error[%d] \n", si->error);
3001
    tstream_ngtcp2_deferred_retry(stream);
3002
    return;
3003
  }
3004
}
3005
3006
static void tstream_ngtcp2_timer_handler(struct tevent_context *ev,
3007
           struct tevent_timer *te,
3008
           struct timeval current_time,
3009
           void *private_data)
3010
{
3011
  struct tstream_context *stream =
3012
    talloc_get_type_abort(private_data,
3013
    struct tstream_context);
3014
  struct tstream_ngtcp2 *si =
3015
    tstream_context_data(stream,
3016
    struct tstream_ngtcp2);
3017
3018
  TALLOC_FREE(si->keepalive_timer);
3019
3020
  DBG_DEBUG("tstream_ngtcp2_sendto_start...\n");
3021
  tstream_ngtcp2_sendto_start(stream);
3022
}
3023
3024
static void tstream_ngtcp2_sendto_start(struct tstream_context *stream)
3025
{
3026
  struct tstream_ngtcp2 *si =
3027
    tstream_context_data(stream,
3028
    struct tstream_ngtcp2);
3029
  struct tevent_req *req = si->writev.req;
3030
  struct tstream_ngtcp2_buffer *cbuf = NULL;
3031
  ngtcp2_ssize nwritten = -1;
3032
  ngtcp2_vec _datav[1] = {{}};
3033
  ngtcp2_ssize *pnwritten = NULL;
3034
  int64_t stream_id = -1;
3035
  ngtcp2_vec *datav = NULL;
3036
  size_t datavcnt = 0;
3037
  uint32_t sflags = NGTCP2_WRITE_STREAM_FLAG_NONE;
3038
  ssize_t ret;
3039
  size_t dbytes = 0;
3040
3041
  if (si->error != 0) {
3042
    DBG_WARNING("si->error[%d] \n", si->error);
3043
    tevent_req_error(req, si->error);
3044
    return;
3045
  }
3046
3047
  if (si->push.subreq != NULL) {
3048
    DBG_DEBUG("ALREADY...\n");
3049
    return;
3050
  }
3051
3052
  if (si->push.b.length != 0) {
3053
    DBG_DEBUG("DIRECTLY(%zu)...\n", si->push.b.length);
3054
    goto send_directly;
3055
  }
3056
3057
write_more:
3058
  cbuf = si->writev.pending;
3059
  if (cbuf != NULL) {
3060
    _datav[0].base = cbuf->buffer + cbuf->offset;
3061
    _datav[0].len = cbuf->length - cbuf->offset;
3062
    dbytes = _datav[0].len;
3063
    datav = _datav;
3064
    datavcnt = ARRAY_SIZE(_datav);
3065
    pnwritten = &nwritten;
3066
    stream_id = si->stream_id;
3067
    if (cbuf->next != NULL) {
3068
      sflags |= NGTCP2_WRITE_STREAM_FLAG_MORE;
3069
    } else {
3070
      sflags &= ~NGTCP2_WRITE_STREAM_FLAG_MORE;
3071
    }
3072
  }
3073
3074
  ret = ngtcp2_conn_writev_stream(si->conn,
3075
          &si->path,
3076
          NULL,
3077
          si->push.b.buffer,
3078
          sizeof(si->push.b.buffer),
3079
          pnwritten,
3080
          sflags,
3081
          stream_id,
3082
          datav,
3083
          datavcnt,
3084
          tstream_ngtcp2_timestamp(NULL));
3085
3086
  DBG_DEBUG("sid[%"PRIi64"] "
3087
      "ngtcp2_conn_writev_stream ret[%zd] %s "
3088
      "dbytes[%zu] nwritten[%zd]\n",
3089
      si->stream_id,
3090
      ret, ngtcp2_strerror(ret),
3091
      dbytes, nwritten);
3092
3093
  if (ret == 0 || ret == NGTCP2_ERR_STREAM_DATA_BLOCKED) {
3094
    if (dbytes != 0) {
3095
      /*
3096
       * The congestion windows is full
3097
       * we need to stop send and wait
3098
       * for incoming messages.
3099
       *
3100
       * We still call tstream_ngtcp2_timer_start()
3101
       * but that will see si->push.blocked.
3102
       */
3103
      si->push.blocked += 1;
3104
      tstream_ngtcp2_recvfrom_start(stream);
3105
    }
3106
    DBG_DEBUG("tstream_ngtcp2_timer_start...\n");
3107
    tstream_ngtcp2_timer_start(stream);
3108
    return;
3109
  }
3110
3111
  if (ret == NGTCP2_ERR_WRITE_MORE) {
3112
    if (nwritten < 1) {
3113
      ngtcp2_conn_set_tls_error(si->conn, ret);
3114
      si->error = EPIPE;
3115
      DBG_WARNING("si->error[%d] \n", si->error);
3116
      tstream_ngtcp2_deferred_retry(stream);
3117
      return;
3118
    }
3119
    /* handled below */
3120
  } else if (ret < 0) {
3121
    ngtcp2_conn_set_tls_error(si->conn, ret);
3122
    si->error = EPIPE;
3123
    DBG_WARNING("si->error[%d] \n", si->error);
3124
    tstream_ngtcp2_deferred_retry(stream);
3125
    return;
3126
  }
3127
3128
  if (nwritten > 0) {
3129
    cbuf->offset += nwritten;
3130
    if (cbuf->offset == cbuf->length) {
3131
      DLIST_REMOVE(si->writev.pending, cbuf);
3132
      cbuf->offset = si->writev.pushed_offset;
3133
      si->writev.pushed_offset += cbuf->length;
3134
      DLIST_ADD_END(si->writev.pushed, cbuf);
3135
    }
3136
  }
3137
  if (ret == NGTCP2_ERR_WRITE_MORE) {
3138
    DBG_DEBUG("MORE...\n");
3139
    goto write_more;
3140
  }
3141
3142
  DBG_DEBUG("tstream_ngtcp2_timer_start...\n");
3143
  tstream_ngtcp2_timer_start(stream);
3144
3145
  si->push.b.length = ret;
3146
send_directly:
3147
  si->push.subreq = tdgram_sendto_send(si,
3148
               si->current_ev,
3149
               si->plain_dgram,
3150
               si->push.b.buffer,
3151
               si->push.b.length,
3152
               NULL);
3153
  if (si->push.subreq == NULL) {
3154
    si->error = ENOMEM;
3155
    DBG_WARNING("si->error[%d] \n", si->error);
3156
    tstream_ngtcp2_deferred_retry(stream);
3157
    return;
3158
  }
3159
  tevent_req_set_callback(si->push.subreq,
3160
        tstream_ngtcp2_sendto_done,
3161
        stream);
3162
3163
  return;
3164
}
3165
3166
static void tstream_ngtcp2_sendto_done(struct tevent_req *subreq)
3167
{
3168
  struct tstream_context *stream =
3169
    tevent_req_callback_data(subreq,
3170
    struct tstream_context);
3171
  struct tstream_ngtcp2 *si =
3172
    tstream_context_data(stream,
3173
    struct tstream_ngtcp2);
3174
  ssize_t ret;
3175
  int error = 0;
3176
3177
  SMB_ASSERT(si->push.subreq == subreq);
3178
  si->push.subreq = NULL;
3179
3180
  ret = tdgram_sendto_recv(subreq, &error);
3181
  TALLOC_FREE(subreq);
3182
  if (ret == -1) {
3183
    si->error = error;
3184
    DBG_WARNING("si->error[%d] \n", si->error);
3185
    tstream_ngtcp2_deferred_retry(stream);
3186
    return;
3187
  }
3188
3189
  if (si->push.b.length != ret) {
3190
    si->error = EIO;
3191
    tstream_ngtcp2_deferred_retry(stream);
3192
    return;
3193
  }
3194
  si->push.b.length = 0;
3195
3196
  DBG_DEBUG("tstream_ngtcp2_deferred_retry...\n");
3197
  tstream_ngtcp2_deferred_retry(stream);
3198
}
3199
3200
static void tstream_ngtcp2_recvfrom_start(struct tstream_context *stream)
3201
{
3202
  struct tstream_ngtcp2 *si =
3203
    tstream_context_data(stream,
3204
    struct tstream_ngtcp2);
3205
  struct timespec ts = timespec_current();
3206
  struct timeval_buf tsbuf;
3207
3208
  if (si->pull.subreq != NULL) {
3209
    DBG_DEBUG("%s: ALREADY... in_progress[%u]\n",
3210
        timespec_string_buf(&ts, true, &tsbuf),
3211
        tevent_req_is_in_progress(si->pull.subreq));
3212
    return;
3213
  }
3214
3215
  DBG_DEBUG("RECVFROM...\n");
3216
  si->pull.subreq = tdgram_recvfrom_send(si,
3217
                 si->current_ev,
3218
                 si->plain_dgram);
3219
  if (si->pull.subreq == NULL) {
3220
    si->error = ENOMEM;
3221
    DBG_WARNING("si->error[%d] \n", si->error);
3222
    tstream_ngtcp2_deferred_retry(stream);
3223
    return;
3224
  }
3225
  DBG_DEBUG("%s: ...RECVFROM in_progress[%u]\n",
3226
      timespec_string_buf(&ts, true, &tsbuf),
3227
      tevent_req_is_in_progress(si->pull.subreq));
3228
  tevent_req_set_callback(si->pull.subreq,
3229
        tstream_ngtcp2_recvfrom_done,
3230
        stream);
3231
}
3232
3233
static void tstream_ngtcp2_recvfrom_done(struct tevent_req *subreq)
3234
{
3235
  struct tstream_context *stream =
3236
    tevent_req_callback_data(subreq,
3237
    struct tstream_context);
3238
  struct tstream_ngtcp2 *si =
3239
    tstream_context_data(stream,
3240
    struct tstream_ngtcp2);
3241
  ssize_t ret;
3242
  int error = 0;
3243
  uint8_t *buf = NULL;
3244
  struct timespec ts = timespec_current();
3245
  struct timeval_buf tsbuf;
3246
3247
  SMB_ASSERT(si->pull.subreq == subreq);
3248
  si->pull.subreq = NULL;
3249
3250
  ret = tdgram_recvfrom_recv(subreq, &error, si, &buf, NULL);
3251
  TALLOC_FREE(subreq);
3252
  if (ret == -1) {
3253
    si->error = error;
3254
    DBG_WARNING("si->error[%d] \n", si->error);
3255
    tstream_ngtcp2_deferred_retry(stream);
3256
    return;
3257
  }
3258
3259
  ret = ngtcp2_conn_read_pkt(si->conn,
3260
           &si->path,
3261
           NULL,
3262
           buf,
3263
           ret,
3264
           tstream_ngtcp2_timestamp(NULL));
3265
3266
  DBG_DEBUG("%s: handshake_done[%u] sid[%"PRIi64"] "
3267
      "ngtcp2_conn_read_pkt ret[%zd] %s\n",
3268
      timespec_string_buf(&ts, true, &tsbuf),
3269
      si->handshake.done, si->stream_id,
3270
      ret, ngtcp2_strerror(ret));
3271
  if (ret < 0) {
3272
    si->error = ret;
3273
    tstream_ngtcp2_deferred_retry(stream);
3274
    return;
3275
  }
3276
3277
  /*
3278
   * Once we got a message from the peer
3279
   * ngtcp2_conn_read_pkt() reset the
3280
   * internal state, so we might be able
3281
   * to send more data now or need to
3282
   * send some acks or pings.
3283
   */
3284
  si->push.blocked = 0;
3285
  DBG_DEBUG("tstream_ngtcp2_sendto_start...\n");
3286
  tstream_ngtcp2_sendto_start(stream);
3287
3288
  /*
3289
   * We likely also got some incoming stream
3290
   * data so we need to check if a pending
3291
   * readv_send can make some progress.
3292
   */
3293
  DBG_DEBUG("tstream_ngtcp2_deferred_retry...\n");
3294
  tstream_ngtcp2_deferred_retry(stream);
3295
}
3296
3297
static size_t tstream_ngtcp2_common_retry(struct tstream_context *stream)
3298
{
3299
  struct tstream_ngtcp2 *si =
3300
    tstream_context_data(stream,
3301
    struct tstream_ngtcp2);
3302
  size_t num_requests = 0;
3303
3304
  if (si->handshake.req != NULL && !si->handshake.done) {
3305
    num_requests += 1;
3306
  }
3307
3308
  if (si->writev.req != NULL) {
3309
    num_requests += 1;
3310
  }
3311
3312
  if (si->readv.req != NULL) {
3313
    num_requests += 1;
3314
  }
3315
3316
  if (si->monitor.req != NULL) {
3317
    num_requests += 1;
3318
  }
3319
3320
  if (num_requests == 0) {
3321
    DBG_DEBUG("%s: DISMANTLE\n", __location__);
3322
    si->last_expire = 0;
3323
    TALLOC_FREE(si->keepalive_timer);
3324
    TALLOC_FREE(si->pull.subreq);
3325
    TALLOC_FREE(si->push.subreq);
3326
    tevent_reset_immediate(si->retry_im);
3327
    si->current_ev = NULL;
3328
  }
3329
3330
  if (si->push.subreq == NULL && si->pull.subreq == NULL) {
3331
    if (si->handshake.req != NULL && si->handshake.done) {
3332
      struct tevent_req *req = si->handshake.req;
3333
3334
      si->handshake.req = NULL;
3335
3336
      /* tevent_req_defer_callback was used */
3337
      tevent_req_done(req);
3338
    }
3339
3340
    if (si->disconnect.req != NULL) {
3341
      struct tevent_req *req = si->disconnect.req;
3342
3343
      si->disconnect.req = NULL;
3344
3345
      /* tevent_req_defer_callback was used */
3346
      tevent_req_done(req);
3347
    }
3348
  }
3349
3350
  return num_requests;
3351
}
3352
3353
static void tstream_ngtcp2_direct_retry(struct tstream_context *stream)
3354
{
3355
  struct tstream_ngtcp2 *si =
3356
    tstream_context_data(stream,
3357
    struct tstream_ngtcp2);
3358
  size_t num_requests = tstream_ngtcp2_common_retry(stream);
3359
3360
  /*
3361
   * If there are more than one pending highlevel
3362
   * request we need to retry again.
3363
   *
3364
   * But we can't do that if
3365
   * ngtcp2_conn_writev_stream() indicated
3366
   * a blocking situation. So we need to
3367
   * wait for [e]poll to notice an incoming
3368
   * message or the keepalive timer to
3369
   * trigger more progress.
3370
   */
3371
  if (num_requests > 1 && si->push.blocked == 0) {
3372
    DBG_DEBUG("tstream_ngtcp2_deferred_retry...\n");
3373
    tstream_ngtcp2_deferred_retry(stream);
3374
  }
3375
3376
  if (si->handshake.req != NULL && !si->handshake.done) {
3377
    tstream_ngtcp2_retry_handshake(stream);
3378
    return;
3379
  }
3380
3381
  if (si->writev.req != NULL) {
3382
    tstream_ngtcp2_writev_retry(stream);
3383
    return;
3384
  }
3385
3386
  if (si->readv.req != NULL) {
3387
    tstream_ngtcp2_readv_retry(stream);
3388
    return;
3389
  }
3390
3391
  if (si->monitor.req != NULL) {
3392
    tstream_ngtcp2_monitor_retry(stream);
3393
    return;
3394
  }
3395
}
3396
3397
static void tstream_ngtcp2_retry_trigger(struct tevent_context *ctx,
3398
           struct tevent_immediate *im,
3399
           void *private_data)
3400
{
3401
  struct tstream_context *stream =
3402
    talloc_get_type_abort(private_data,
3403
    struct tstream_context);
3404
3405
  tstream_ngtcp2_direct_retry(stream);
3406
}
3407
3408
static void tstream_ngtcp2_deferred_retry(struct tstream_context *stream)
3409
{
3410
  struct tstream_ngtcp2 *si =
3411
    tstream_context_data(stream,
3412
    struct tstream_ngtcp2);
3413
  size_t num_requests = tstream_ngtcp2_common_retry(stream);
3414
3415
  if (num_requests == 0) {
3416
    /*
3417
     * connection is dismantled
3418
     * and si->current_ev is NULL,
3419
     * so we need to stop here
3420
     * and wait for the next
3421
     * highlevel request to start
3422
     * the engine again.
3423
     */
3424
    return;
3425
  }
3426
3427
  tevent_schedule_immediate(si->retry_im,
3428
          si->current_ev,
3429
          tstream_ngtcp2_retry_trigger,
3430
          stream);
3431
}
3432
3433
static ssize_t tstream_ngtcp2_pending_bytes(struct tstream_context *stream)
3434
{
3435
  struct tstream_ngtcp2 *si =
3436
    tstream_context_data(stream,
3437
    struct tstream_ngtcp2);
3438
  struct tstream_ngtcp2_buffer *cbuf = NULL;
3439
  size_t ret = 0;
3440
3441
  if (si->error != 0) {
3442
    DBG_WARNING("si->error[%d] \n", si->error);
3443
    errno = si->error;
3444
    return -1;
3445
  }
3446
3447
  for (cbuf = si->readv.buffers; cbuf != NULL; cbuf = cbuf->next) {
3448
    ret += cbuf->length - cbuf->offset;
3449
  }
3450
3451
  DBG_DEBUG("ret[%zu]\n", ret);
3452
3453
  return ret;
3454
}
3455
3456
struct tstream_ngtcp2_readv_state {
3457
  struct tstream_context *stream;
3458
3459
  struct iovec *vector;
3460
  int count;
3461
3462
  int ret;
3463
};
3464
3465
static void tstream_ngtcp2_readv_cleanup(struct tevent_req *req,
3466
           enum tevent_req_state req_state)
3467
{
3468
  struct tstream_ngtcp2_readv_state *state =
3469
    tevent_req_data(req,
3470
    struct tstream_ngtcp2_readv_state);
3471
3472
  if (state->stream != NULL) {
3473
    struct tstream_context *stream = state->stream;
3474
    struct tstream_ngtcp2 *si =
3475
      tstream_context_data(stream,
3476
      struct tstream_ngtcp2);
3477
3478
    state->stream = NULL;
3479
3480
    SMB_ASSERT(si->readv.req == req);
3481
    si->readv.req = NULL;
3482
3483
    tstream_ngtcp2_deferred_retry(stream);
3484
  }
3485
}
3486
3487
static void tstream_ngtcp2_readv_next(struct tevent_req *req);
3488
3489
static struct tevent_req *tstream_ngtcp2_readv_send(TALLOC_CTX *mem_ctx,
3490
          struct tevent_context *ev,
3491
          struct tstream_context *stream,
3492
          struct iovec *vector,
3493
          size_t count)
3494
{
3495
  struct tstream_ngtcp2 *si =
3496
    tstream_context_data(stream,
3497
    struct tstream_ngtcp2);
3498
  struct tevent_req *req;
3499
  struct tstream_ngtcp2_readv_state *state;
3500
3501
  SMB_ASSERT(si->readv.req == NULL);
3502
3503
  if (si->current_ev != ev) {
3504
    SMB_ASSERT(si->push.subreq == NULL);
3505
    SMB_ASSERT(si->pull.subreq == NULL);
3506
    SMB_ASSERT(si->keepalive_timer == NULL);
3507
  }
3508
3509
  si->current_ev = ev;
3510
3511
  req = tevent_req_create(mem_ctx, &state,
3512
        struct tstream_ngtcp2_readv_state);
3513
  if (req == NULL) {
3514
    return NULL;
3515
  }
3516
3517
  state->stream = stream;
3518
  state->ret = 0;
3519
3520
  if (si->error != 0) {
3521
    DBG_WARNING("si->error[%d] \n", si->error);
3522
    tevent_req_error(req, si->error);
3523
    return tevent_req_post(req, ev);
3524
  }
3525
3526
  /*
3527
   * we make a copy of the vector so we can change the structure
3528
   */
3529
  state->vector = talloc_array(state, struct iovec, count);
3530
  if (tevent_req_nomem(state->vector, req)) {
3531
    return tevent_req_post(req, ev);
3532
  }
3533
  memcpy(state->vector, vector, sizeof(struct iovec) * count);
3534
  state->count = count;
3535
3536
  DBG_DEBUG("tstream_ngtcp2_readv_next...\n");
3537
  si->readv.req = req;
3538
  tevent_req_defer_callback(req, ev);
3539
  tevent_req_set_cleanup_fn(req, tstream_ngtcp2_readv_cleanup);
3540
  tstream_ngtcp2_readv_next(req);
3541
  if (!tevent_req_is_in_progress(req)) {
3542
    return tevent_req_post(req, ev);
3543
  }
3544
3545
  return req;
3546
}
3547
3548
static void tstream_ngtcp2_readv_next(struct tevent_req *req)
3549
{
3550
  struct tstream_ngtcp2_readv_state *state =
3551
    tevent_req_data(req,
3552
    struct tstream_ngtcp2_readv_state);
3553
  struct tstream_ngtcp2 *si =
3554
    tstream_context_data(state->stream,
3555
    struct tstream_ngtcp2);
3556
3557
  DBG_DEBUG("START si->read.buffers[%u] state->count[%u] state->ret[%u]\n",
3558
      !!si->readv.buffers, state->count, state->ret);
3559
3560
  /*
3561
   * copy the pending buffer first
3562
   */
3563
  while (si->readv.buffers != NULL && state->count > 0) {
3564
    struct tstream_ngtcp2_buffer *cbuf = si->readv.buffers;
3565
    uint8_t *base = (uint8_t *)state->vector[0].iov_base;
3566
    size_t len = MIN(cbuf->length - cbuf->offset, state->vector[0].iov_len);
3567
3568
    memcpy(base, cbuf->buffer + cbuf->offset, len);
3569
3570
    base += len;
3571
    state->vector[0].iov_base = (char *) base;
3572
    state->vector[0].iov_len -= len;
3573
3574
    cbuf->offset += len;
3575
    if (cbuf->offset == cbuf->length) {
3576
      DLIST_REMOVE(si->readv.buffers, cbuf);
3577
      ngtcp2_conn_extend_max_offset(si->conn, cbuf->length);
3578
      ngtcp2_conn_extend_max_stream_offset(si->conn,
3579
                   si->stream_id,
3580
                   cbuf->length);
3581
      TALLOC_FREE(cbuf);
3582
    }
3583
3584
    if (state->vector[0].iov_len == 0) {
3585
      state->vector += 1;
3586
      state->count -= 1;
3587
    }
3588
3589
    state->ret += len;
3590
  }
3591
3592
  if (state->count == 0) {
3593
    DBG_DEBUG("DONE state->red[%d]\n", state->ret);
3594
    tevent_req_done(req);
3595
    return;
3596
  }
3597
3598
  DBG_DEBUG("tstream_ngtcp2_recvfrom_start...\n");
3599
  tstream_ngtcp2_recvfrom_start(state->stream);
3600
}
3601
3602
static void tstream_ngtcp2_readv_retry(struct tstream_context *stream)
3603
{
3604
  struct tstream_ngtcp2 *si =
3605
    tstream_context_data(stream,
3606
    struct tstream_ngtcp2);
3607
  struct tevent_req *req = si->readv.req;
3608
3609
  if (si->error != 0) {
3610
    DBG_WARNING("si->error[%d] \n", si->error);
3611
    tevent_req_error(req, si->error);
3612
    return;
3613
  }
3614
3615
  DBG_DEBUG("tstream_ngtcp2_readv_next...\n");
3616
  tstream_ngtcp2_readv_next(req);
3617
}
3618
3619
static int tstream_ngtcp2_readv_recv(struct tevent_req *req,
3620
             int *perrno)
3621
{
3622
  struct tstream_ngtcp2_readv_state *state =
3623
    tevent_req_data(req,
3624
    struct tstream_ngtcp2_readv_state);
3625
  int ret;
3626
3627
  ret = tsocket_simple_int_recv(req, perrno);
3628
  if (ret == 0) {
3629
    ret = state->ret;
3630
  }
3631
  DBG_DEBUG("tsocket_simple_int_recv... %d: %s\n",
3632
      ret, strerror(ret == -1 ? *perrno : 0));
3633
3634
  tevent_req_received(req);
3635
  return ret;
3636
}
3637
3638
struct tstream_ngtcp2_writev_state {
3639
  struct tstream_context *stream;
3640
3641
  int ret;
3642
};
3643
3644
static void tstream_ngtcp2_writev_cleanup(struct tevent_req *req,
3645
            enum tevent_req_state req_state)
3646
{
3647
  struct tstream_ngtcp2_writev_state *state =
3648
    tevent_req_data(req,
3649
    struct tstream_ngtcp2_writev_state);
3650
3651
  if (state->stream != NULL) {
3652
    struct tstream_context *stream = state->stream;
3653
    struct tstream_ngtcp2 *si =
3654
      tstream_context_data(stream,
3655
      struct tstream_ngtcp2);
3656
3657
    state->stream = NULL;
3658
3659
    SMB_ASSERT(si->writev.req == req);
3660
    si->writev.req = NULL;
3661
3662
    tstream_ngtcp2_deferred_retry(stream);
3663
  }
3664
}
3665
3666
static struct tevent_req *tstream_ngtcp2_writev_send(TALLOC_CTX *mem_ctx,
3667
          struct tevent_context *ev,
3668
          struct tstream_context *stream,
3669
          const struct iovec *vector,
3670
          size_t count)
3671
{
3672
  struct tstream_ngtcp2 *si =
3673
    tstream_context_data(stream,
3674
    struct tstream_ngtcp2);
3675
  struct tevent_req *req = NULL;
3676
  struct tstream_ngtcp2_writev_state *state = NULL;
3677
  struct tstream_ngtcp2_buffer *buffers = NULL;
3678
  struct tstream_ngtcp2_buffer *cbuf = NULL;
3679
  size_t vi = 0;
3680
  size_t vofs = 0;
3681
  size_t nbytes = 0;
3682
  size_t nbuffers = 0;
3683
3684
  SMB_ASSERT(si->writev.req == NULL);
3685
3686
  if (si->current_ev != ev) {
3687
    SMB_ASSERT(si->push.subreq == NULL);
3688
    SMB_ASSERT(si->pull.subreq == NULL);
3689
    SMB_ASSERT(si->keepalive_timer == NULL);
3690
  }
3691
3692
  si->current_ev = ev;
3693
3694
  req = tevent_req_create(mem_ctx, &state,
3695
        struct tstream_ngtcp2_writev_state);
3696
  if (req == NULL) {
3697
    return NULL;
3698
  }
3699
3700
  state->stream = stream;
3701
  state->ret = 0;
3702
3703
  if (si->error != 0) {
3704
    DBG_WARNING("si->error[%d] \n", si->error);
3705
    tevent_req_error(req, si->error);
3706
    return tevent_req_post(req, ev);
3707
  }
3708
3709
  for (vi = 0; vi < count;) {
3710
    const uint8_t *b = vector[vi].iov_base;
3711
    size_t l = vector[vi].iov_len;
3712
    size_t n;
3713
3714
    b += vofs;
3715
    l -= vofs;
3716
3717
    if (l == 0) {
3718
      vofs = 0;
3719
      vi += 1;
3720
      continue;
3721
    }
3722
3723
    if (cbuf == NULL) {
3724
      cbuf = talloc(si, struct tstream_ngtcp2_buffer);
3725
      if (cbuf == NULL) {
3726
        si->error = ENOMEM;
3727
        DBG_WARNING("si->error[%d] \n", si->error);
3728
        tevent_req_error(req, si->error);
3729
        return tevent_req_post(req, ev);
3730
      }
3731
      cbuf->prev = cbuf->next = NULL;
3732
      cbuf->offset = 0;
3733
      cbuf->length = 0;
3734
      talloc_reparent(si, state, cbuf);
3735
      DLIST_ADD_END(buffers, cbuf);
3736
    }
3737
3738
    n = ARRAY_SIZE(cbuf->buffer) - cbuf->length;
3739
    n = MIN(n, l);
3740
3741
    memcpy(cbuf->buffer + cbuf->length, b, n);
3742
3743
    nbytes += n;
3744
3745
    vofs += n;
3746
    cbuf->length += n;
3747
    if (ARRAY_SIZE(cbuf->buffer) == cbuf->length) {
3748
      cbuf = NULL;
3749
    }
3750
  }
3751
3752
  while (buffers != NULL) {
3753
    cbuf = buffers;
3754
3755
    DLIST_REMOVE(buffers, cbuf);
3756
3757
    nbuffers += 1;
3758
    DLIST_ADD_END(si->writev.pending, cbuf);
3759
    talloc_reparent(state, si, cbuf);
3760
  }
3761
3762
  DBG_DEBUG("tstream_ngtcp2_writev_retry... "
3763
      "count[%zu] buffers[%zu] bytes[%zu]\n",
3764
      count, nbuffers, nbytes);
3765
  si->writev.req = req;
3766
  tevent_req_defer_callback(req, ev);
3767
  tevent_req_set_cleanup_fn(req, tstream_ngtcp2_writev_cleanup);
3768
  tstream_ngtcp2_writev_retry(state->stream);
3769
  if (!tevent_req_is_in_progress(req)) {
3770
    return tevent_req_post(req, ev);
3771
  }
3772
3773
  return req;
3774
}
3775
3776
static void tstream_ngtcp2_writev_retry(struct tstream_context *stream)
3777
{
3778
  struct tstream_ngtcp2 *si =
3779
    tstream_context_data(stream,
3780
    struct tstream_ngtcp2);
3781
  struct tevent_req *req = si->writev.req;
3782
3783
  if (si->error != 0) {
3784
    DBG_WARNING("si->error[%d] \n", si->error);
3785
    tevent_req_error(req, si->error);
3786
    return;
3787
  }
3788
3789
  if (si->writev.pending == NULL) {
3790
    DBG_DEBUG("sid[%"PRIi64"] done\n", si->stream_id);
3791
    tevent_req_done(req);
3792
    return;
3793
  }
3794
3795
  DBG_DEBUG("tstream_ngtcp2_sendto_start...\n");
3796
  tstream_ngtcp2_sendto_start(stream);
3797
}
3798
3799
static int tstream_ngtcp2_writev_recv(struct tevent_req *req,
3800
              int *perrno)
3801
{
3802
  struct tstream_ngtcp2_writev_state *state =
3803
    tevent_req_data(req,
3804
    struct tstream_ngtcp2_writev_state);
3805
  int ret;
3806
3807
  ret = tsocket_simple_int_recv(req, perrno);
3808
  if (ret == 0) {
3809
    ret = state->ret;
3810
  }
3811
  DBG_DEBUG("tsocket_simple_int_recv... %d: %s\n",
3812
      ret, strerror(ret == -1 ? *perrno : 0));
3813
3814
  tevent_req_received(req);
3815
  return ret;
3816
}
3817
3818
struct tstream_ngtcp2_disconnect_state {
3819
  struct tstream_context *stream;
3820
};
3821
3822
static void tstream_ngtcp2_disconnect_cleanup(struct tevent_req *req,
3823
                enum tevent_req_state req_state)
3824
{
3825
  struct tstream_ngtcp2_disconnect_state *state =
3826
    tevent_req_data(req,
3827
    struct tstream_ngtcp2_disconnect_state);
3828
3829
  if (state->stream != NULL) {
3830
    struct tstream_ngtcp2 *si =
3831
      tstream_context_data(state->stream,
3832
      struct tstream_ngtcp2);
3833
3834
    SMB_ASSERT(si->disconnect.req == req);
3835
    si->disconnect.req = NULL;
3836
    state->stream = NULL;
3837
  }
3838
}
3839
3840
static struct tevent_req *tstream_ngtcp2_disconnect_send(TALLOC_CTX *mem_ctx,
3841
            struct tevent_context *ev,
3842
            struct tstream_context *stream)
3843
{
3844
  struct tstream_ngtcp2 *si =
3845
    tstream_context_data(stream,
3846
    struct tstream_ngtcp2);
3847
  struct tevent_req *req;
3848
  struct tstream_ngtcp2_disconnect_state *state;
3849
3850
  SMB_ASSERT(si->disconnect.req == NULL);
3851
3852
  if (si->current_ev != ev) {
3853
    SMB_ASSERT(si->push.subreq == NULL);
3854
    SMB_ASSERT(si->pull.subreq == NULL);
3855
    SMB_ASSERT(si->keepalive_timer == NULL);
3856
  }
3857
3858
  si->current_ev = ev;
3859
3860
  req = tevent_req_create(mem_ctx, &state,
3861
        struct tstream_ngtcp2_disconnect_state);
3862
  if (req == NULL) {
3863
    return NULL;
3864
  }
3865
  state->stream = stream;
3866
3867
  if (si->error != 0) {
3868
    DBG_WARNING("si->error[%d] \n", si->error);
3869
    tevent_req_error(req, si->error);
3870
    return tevent_req_post(req, ev);
3871
  }
3872
3873
  tevent_req_defer_callback(req, ev);
3874
  tevent_req_set_cleanup_fn(req, tstream_ngtcp2_disconnect_cleanup);
3875
3876
  tstream_ngtcp2_close_stream(si);
3877
3878
  si->disconnect.req = req;
3879
  if (si->push.subreq != NULL) {
3880
    /*
3881
     * We need to wait until we flushed all
3882
     * pending messages to the kernel socket.
3883
     */
3884
    tevent_req_set_callback(si->push.subreq,
3885
          tstream_ngtcp2_sendto_done,
3886
          stream);
3887
    return req;
3888
  }
3889
3890
  tevent_req_done(req);
3891
  return tevent_req_post(req, ev);
3892
}
3893
3894
static int tstream_ngtcp2_disconnect_recv(struct tevent_req *req,
3895
            int *perrno)
3896
{
3897
  int ret;
3898
3899
  ret = tsocket_simple_int_recv(req, perrno);
3900
  DBG_DEBUG("tsocket_simple_int_recv... %d: %s\n",
3901
      ret, strerror(ret == -1 ? *perrno : 0));
3902
3903
  tevent_req_received(req);
3904
  return ret;
3905
}
3906
3907
struct tstream_ngtcp2_monitor_state {
3908
  struct tstream_context *stream;
3909
};
3910
3911
static void tstream_ngtcp2_monitor_cleanup(struct tevent_req *req,
3912
             enum tevent_req_state req_state)
3913
{
3914
  struct tstream_ngtcp2_monitor_state *state =
3915
    tevent_req_data(req,
3916
    struct tstream_ngtcp2_monitor_state);
3917
3918
  if (state->stream != NULL) {
3919
    struct tstream_context *stream = state->stream;
3920
    struct tstream_ngtcp2 *si =
3921
      tstream_context_data(stream,
3922
      struct tstream_ngtcp2);
3923
3924
    state->stream = NULL;
3925
3926
    SMB_ASSERT(si->monitor.req == req);
3927
    si->monitor.req = NULL;
3928
3929
    tstream_ngtcp2_deferred_retry(stream);
3930
  }
3931
}
3932
3933
static struct tevent_req *tstream_ngtcp2_monitor_send(
3934
  TALLOC_CTX *mem_ctx,
3935
  struct tevent_context *ev,
3936
  struct tstream_context *stream)
3937
{
3938
  struct tstream_ngtcp2 *si = tstream_context_data(stream,
3939
               struct tstream_ngtcp2);
3940
  struct tevent_req *req;
3941
  struct tstream_ngtcp2_monitor_state *state;
3942
3943
  SMB_ASSERT(si->monitor.req == NULL);
3944
3945
  if (si->current_ev != ev) {
3946
    SMB_ASSERT(si->push.subreq == NULL);
3947
    SMB_ASSERT(si->pull.subreq == NULL);
3948
    SMB_ASSERT(si->keepalive_timer == NULL);
3949
  }
3950
3951
  si->current_ev = ev;
3952
3953
  req = tevent_req_create(mem_ctx, &state,
3954
        struct tstream_ngtcp2_monitor_state);
3955
  if (req == NULL) {
3956
    return NULL;
3957
  }
3958
  state->stream = stream;
3959
3960
  if (si->error != 0) {
3961
    DBG_WARNING("si->error[%d] \n", si->error);
3962
    tevent_req_error(req, si->error);
3963
    return tevent_req_post(req, ev);
3964
  }
3965
3966
  DBG_DEBUG("tstream_ngtcp2_monitor_retry...\n");
3967
  si->monitor.req = req;
3968
  tevent_req_defer_callback(req, ev);
3969
  tevent_req_set_cleanup_fn(req, tstream_ngtcp2_monitor_cleanup);
3970
  tstream_ngtcp2_monitor_retry(stream);
3971
  if (!tevent_req_is_in_progress(req)) {
3972
    return tevent_req_post(req, ev);
3973
  }
3974
3975
  return req;
3976
}
3977
3978
static void tstream_ngtcp2_monitor_retry(struct tstream_context *stream)
3979
{
3980
  struct tstream_ngtcp2 *si = tstream_context_data(stream,
3981
               struct tstream_ngtcp2);
3982
  struct tevent_req *req = si->monitor.req;
3983
3984
  if (si->error != 0) {
3985
    DBG_WARNING("si->error[%d] \n", si->error);
3986
    tevent_req_error(req, si->error);
3987
    return;
3988
  }
3989
3990
  DBG_DEBUG("AGAIN...\n");
3991
3992
  tstream_ngtcp2_timer_start(stream);
3993
  tstream_ngtcp2_recvfrom_start(stream);
3994
}
3995
3996
static int tstream_ngtcp2_monitor_recv(struct tevent_req *req, int *perrno)
3997
{
3998
  int ret;
3999
4000
  ret = tsocket_simple_int_recv(req, perrno);
4001
  DBG_DEBUG("tsocket_simple_int_recv... %d: %s\n",
4002
      ret, strerror(ret == -1 ? *perrno : 0));
4003
4004
  tevent_req_received(req);
4005
  return ret;
4006
}
4007
4008
static const struct tstream_context_ops tstream_ngtcp2_ops = {
4009
  .name     = "ngtcp2",
4010
4011
  .pending_bytes    = tstream_ngtcp2_pending_bytes,
4012
4013
  .readv_send   = tstream_ngtcp2_readv_send,
4014
  .readv_recv   = tstream_ngtcp2_readv_recv,
4015
4016
  .writev_send    = tstream_ngtcp2_writev_send,
4017
  .writev_recv    = tstream_ngtcp2_writev_recv,
4018
4019
  .disconnect_send  = tstream_ngtcp2_disconnect_send,
4020
  .disconnect_recv  = tstream_ngtcp2_disconnect_recv,
4021
4022
  .monitor_send   = tstream_ngtcp2_monitor_send,
4023
  .monitor_recv   = tstream_ngtcp2_monitor_recv,
4024
};
4025
4026
#endif /* HAVE_LIBNGTCP2 */
4027
4028
struct tstream_tls_ngtcp2_connect_state {
4029
  struct tstream_context *quic_stream;
4030
};
4031
4032
static void tstream_tls_ngtcp2_connect_cleanup(struct tevent_req *req,
4033
                 enum tevent_req_state req_state);
4034
4035
struct tevent_req *_tstream_tls_ngtcp2_connect_send(TALLOC_CTX *mem_ctx,
4036
                struct tevent_context *ev,
4037
                struct tstream_tls_params *tlsp,
4038
                uint32_t timeout_msec,
4039
                const char *alpn,
4040
                int *sockfd,
4041
                const char *location)
4042
0
{
4043
0
  struct tevent_req *req = NULL;
4044
0
  struct tstream_tls_ngtcp2_connect_state *state = NULL;
4045
#ifdef HAVE_LIBNGTCP2
4046
  struct tstream_ngtcp2 *si = NULL;
4047
  gnutls_datum_t alpn_data = {
4048
    .data = discard_const_p(unsigned char, "smb"),
4049
    .size = 3,
4050
  };
4051
  ngtcp2_callbacks callbacks = {
4052
    .client_initial = /* required client */
4053
      ngtcp2_crypto_client_initial_cb,
4054
    .recv_crypto_data = /* required */
4055
      ngtcp2_crypto_recv_crypto_data_cb,
4056
    .encrypt = ngtcp2_crypto_encrypt_cb, /* required */
4057
    .decrypt = ngtcp2_crypto_decrypt_cb, /* required */
4058
    .hp_mask = ngtcp2_crypto_hp_mask_cb, /* required */
4059
    .recv_stream_data =
4060
      tstream_ngtcp2_recv_stream_data_cb, /* used */
4061
    .acked_stream_data_offset =
4062
      tstream_ngtcp2_acked_stream_data_offset_cb, /* used */
4063
    .stream_close =
4064
      tstream_ngtcp2_stream_close_cb, /* used */
4065
    .recv_stateless_reset =
4066
      tstream_ngtcp2_recv_stateless_reset_cb, /* used */
4067
    .recv_retry = ngtcp2_crypto_recv_retry_cb, /* required client */
4068
    .rand = tstream_ngtcp2_rand_cb, /* required */
4069
    .get_new_connection_id = /* required */
4070
      tstream_ngtcp2_get_new_connection_id_cb,
4071
    .update_key = ngtcp2_crypto_update_key_cb, /* required */
4072
    .stream_reset =
4073
      tstream_ngtcp2_stream_reset_cb, /* used */
4074
    .delete_crypto_aead_ctx = /* required */
4075
      ngtcp2_crypto_delete_crypto_aead_ctx_cb,
4076
    .delete_crypto_cipher_ctx = /* required */
4077
      ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
4078
    .get_path_challenge_data = /* required */
4079
      ngtcp2_crypto_get_path_challenge_data_cb,
4080
    .version_negotiation = /* required */
4081
      ngtcp2_crypto_version_negotiation_cb,
4082
  };
4083
  ngtcp2_cid dcid = {
4084
    .datalen = NGTCP2_MIN_INITIAL_DCIDLEN,
4085
  };
4086
  ngtcp2_cid scid = {
4087
    .datalen = NGTCP2_MIN_INITIAL_DCIDLEN,
4088
  };
4089
  ngtcp2_settings settings = {};
4090
  ngtcp2_transport_params params = {};
4091
  uint32_t available_versions32[2];
4092
  union {
4093
    uint32_t v32[2];
4094
    uint8_t v8[8];
4095
  } available_versions;
4096
  NTSTATUS status;
4097
  int ret;
4098
#endif /* HAVE_LIBNGTCP2 */
4099
0
  bool ok;
4100
4101
0
  req = tevent_req_create(mem_ctx, &state,
4102
0
        struct tstream_tls_ngtcp2_connect_state);
4103
0
  if (req == NULL) {
4104
0
    return NULL;
4105
0
  }
4106
0
  tevent_req_defer_callback(req, ev);
4107
0
  tevent_req_set_cleanup_fn(req, tstream_tls_ngtcp2_connect_cleanup);
4108
4109
#ifdef HAVE_LIBNGTCP2
4110
  state->quic_stream = tstream_context_create(state,
4111
                &tstream_ngtcp2_ops,
4112
                &si,
4113
                struct tstream_ngtcp2,
4114
                location);
4115
  if (tevent_req_nomem(state->quic_stream, req)) {
4116
    return tevent_req_post(req, ev);
4117
  }
4118
  ZERO_STRUCTP(si);
4119
  talloc_set_destructor(si, tstream_ngtcp2_destructor);
4120
4121
  si->laddr = (struct samba_sockaddr) {
4122
    .sa_socklen = sizeof(struct sockaddr_storage),
4123
  };
4124
  si->raddr = (struct samba_sockaddr) {
4125
    .sa_socklen = sizeof(struct sockaddr_storage),
4126
  };
4127
4128
  ret = getsockname(*sockfd, &si->laddr.u.sa, &si->laddr.sa_socklen);
4129
  if (ret != 0) {
4130
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
4131
    return tevent_req_post(req, ev);
4132
  }
4133
4134
  ret = getpeername(*sockfd, &si->raddr.u.sa, &si->raddr.sa_socklen);
4135
  if (ret != 0) {
4136
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
4137
    return tevent_req_post(req, ev);
4138
  }
4139
4140
  ret = tdgram_bsd_existing_socket(si, *sockfd, &si->plain_dgram);
4141
  if (ret != 0) {
4142
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
4143
    return tevent_req_post(req, ev);
4144
  }
4145
  *sockfd = -1;
4146
  tdgram_bsd_optimize_recvfrom(si->plain_dgram, true);
4147
#endif /* HAVE_LIBNGTCP2 */
4148
4149
0
  ok = tevent_req_set_endtime(req, ev,
4150
0
            timeval_current_ofs_msec(timeout_msec));
4151
0
  if (!ok) {
4152
0
    tevent_req_oom(req);
4153
0
    return tevent_req_post(req, ev);
4154
0
  }
4155
4156
0
  ok = tstream_tls_params_quic_enabled(tlsp);
4157
0
  if (!ok) {
4158
0
    goto invalid_parameter_mix;
4159
0
  }
4160
4161
#ifdef HAVE_LIBNGTCP2
4162
4163
  si->conn_ref.get_conn = qwrap_ngtcp2_conn_ref_get_conn;
4164
  si->conn_ref.user_data = state->quic_stream;
4165
4166
  si->handshake.tlss = talloc_zero(state, struct tstream_tls);
4167
  if (tevent_req_nomem(si->handshake.tlss, req)) {
4168
    return tevent_req_post(req, ev);
4169
  }
4170
  talloc_set_destructor(si->handshake.tlss, tstream_tls_destructor);
4171
  si->handshake.tlss->is_server = false;
4172
4173
  status = tstream_tls_prepare_gnutls(tlsp, si->handshake.tlss);
4174
  if (tevent_req_nterror(req, status)) {
4175
    return tevent_req_post(req, ev);
4176
  }
4177
4178
  gnutls_session_set_ptr(si->handshake.tlss->tls_session, &si->conn_ref);
4179
  ngtcp2_crypto_gnutls_configure_client_session(si->handshake.tlss->tls_session);
4180
4181
  ret = gnutls_alpn_set_protocols(si->handshake.tlss->tls_session,
4182
          &alpn_data, 1,
4183
          GNUTLS_ALPN_MANDATORY);
4184
  if (ret != 0) {
4185
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
4186
    return tevent_req_post(req, ev);
4187
  }
4188
4189
  ret = gnutls_rnd(GNUTLS_RND_RANDOM, dcid.data, dcid.datalen);
4190
  if (ret != 0) {
4191
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
4192
    return tevent_req_post(req, ev);
4193
  }
4194
4195
  ret = gnutls_rnd(GNUTLS_RND_RANDOM, scid.data, scid.datalen);
4196
  if (ret != 0) {
4197
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
4198
    return tevent_req_post(req, ev);
4199
  }
4200
4201
  si->path = (ngtcp2_path) {
4202
    .local = {
4203
      .addr = &si->laddr.u.sa,
4204
      .addrlen = si->laddr.sa_socklen,
4205
    },
4206
    .remote = {
4207
      .addr = &si->raddr.u.sa,
4208
      .addrlen = si->raddr.sa_socklen,
4209
    },
4210
  };
4211
4212
  available_versions32[0] = NGTCP2_PROTO_VER_V2;
4213
  available_versions32[1] = NGTCP2_PROTO_VER_V1;
4214
4215
  available_versions.v32[0] = htonl(available_versions32[0]);
4216
  available_versions.v32[1] = htonl(available_versions32[1]);
4217
4218
  ngtcp2_settings_default(&settings);
4219
4220
  settings.initial_ts = tstream_ngtcp2_timestamp(NULL);
4221
  settings.handshake_timeout = timeout_msec * NGTCP2_MILLISECONDS;
4222
  settings.log_printf = tstream_ngtcp2_log_printf;
4223
  settings.qlog_write = tstream_ngtcp2_qlog_write_cb;
4224
4225
  if (CHECK_DEBUGLVL(11)) {
4226
    tstream_ngtcp2_verbose = true;
4227
  }
4228
4229
  settings.available_versions = available_versions32;
4230
  settings.available_versionslen = ARRAY_SIZE(available_versions32);
4231
4232
  /*
4233
   * Copied from quic_transport_param_init
4234
   */
4235
  params.max_udp_payload_size = 65527 /* QUIC_MAX_UDP_PAYLOAD */;
4236
  params.ack_delay_exponent = 3 /* QUIC_DEF_ACK_DELAY_EXPONENT */;
4237
  params.max_ack_delay = 25000 /* QUIC_DEF_ACK_DELAY */;
4238
  params.active_connection_id_limit = 7 /* QUIC_CONN_ID_DEF */;
4239
  params.max_idle_timeout = 30000000 /* QUIC_DEF_IDLE_TIMEOUT */;
4240
  params.initial_max_data = (uint64_t)65536U /* QUIC_PATH_MAX_PMTU */ * 32;
4241
  params.initial_max_stream_data_bidi_local = (uint64_t)65536U /* QUIC_PATH_MAX_PMTU */ * 16;
4242
  params.initial_max_stream_data_bidi_remote = (uint64_t)65536U /* QUIC_PATH_MAX_PMTU */ * 16;
4243
  params.initial_max_stream_data_uni = (uint64_t)65536U /* QUIC_PATH_MAX_PMTU */ * 16;
4244
  params.initial_max_streams_bidi = 100 /* QUIC_DEF_STREAMS */;
4245
  params.initial_max_streams_uni = 100 /* QUIC_DEF_STREAMS */;
4246
4247
  params.version_info_present = 1;
4248
  params.version_info.chosen_version = NGTCP2_PROTO_VER_V1;
4249
  params.version_info.available_versions = available_versions.v8;
4250
  params.version_info.available_versionslen = ARRAY_SIZE(available_versions.v8);
4251
4252
  params.max_ack_delay *= NGTCP2_MICROSECONDS;
4253
  params.max_idle_timeout *= NGTCP2_MICROSECONDS;
4254
4255
  ret = ngtcp2_conn_client_new(&si->conn,
4256
             &dcid,
4257
             &scid,
4258
             &si->path,
4259
             NGTCP2_PROTO_VER_V1,
4260
             &callbacks,
4261
             &settings,
4262
             &params,
4263
             NULL,
4264
             state->quic_stream);
4265
  if (ret != 0) {
4266
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
4267
    return tevent_req_post(req, ev);
4268
  }
4269
4270
  si->keepalive_usecs = 1500 * 1000;
4271
  ngtcp2_conn_set_keep_alive_timeout(si->conn, si->keepalive_usecs * NGTCP2_MICROSECONDS);
4272
  ngtcp2_conn_set_tls_native_handle(si->conn,
4273
            si->handshake.tlss->tls_session);
4274
4275
  si->retry_im = tevent_create_immediate(si);
4276
  if (tevent_req_nomem(si->retry_im, req)) {
4277
    return tevent_req_post(req, ev);
4278
  }
4279
4280
  si->current_ev = ev;
4281
  si->handshake.req = req;
4282
  tstream_ngtcp2_retry_handshake(state->quic_stream);
4283
  if (!tevent_req_is_in_progress(req)) {
4284
    return tevent_req_post(req, ev);
4285
  }
4286
4287
  return req;
4288
#endif /* HAVE_LIBNGTCP2 */
4289
0
invalid_parameter_mix:
4290
0
  tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
4291
0
  return tevent_req_post(req, ev);
4292
0
}
4293
4294
static void tstream_tls_ngtcp2_connect_cleanup(struct tevent_req *req,
4295
                 enum tevent_req_state req_state)
4296
0
{
4297
0
  struct tstream_tls_ngtcp2_connect_state *state =
4298
0
    tevent_req_data(req,
4299
0
    struct tstream_tls_ngtcp2_connect_state);
4300
4301
0
  if (req_state == TEVENT_REQ_DONE) {
4302
0
    return;
4303
0
  }
4304
4305
0
  TALLOC_FREE(state->quic_stream);
4306
0
}
4307
4308
int tstream_tls_ngtcp2_connect_recv(struct tevent_req *req,
4309
            int *perrno,
4310
            TALLOC_CTX *mem_ctx,
4311
            struct tstream_context **quic_stream)
4312
0
{
4313
0
  struct tstream_tls_ngtcp2_connect_state *state =
4314
0
    tevent_req_data(req,
4315
0
    struct tstream_tls_ngtcp2_connect_state);
4316
4317
0
  if (tevent_req_is_unix_error(req, perrno)) {
4318
0
    tevent_req_received(req);
4319
0
    return -1;
4320
0
  }
4321
4322
0
  *quic_stream = talloc_move(mem_ctx, &state->quic_stream);
4323
0
  tevent_req_received(req);
4324
0
  return 0;
4325
0
}