Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Copyright (C) Stefan Metzmacher 2010
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/util_file.h"
25 : #include "../util/tevent_unix.h"
26 : #include "../lib/tsocket/tsocket.h"
27 : #include "../lib/tsocket/tsocket_internal.h"
28 : #include "../lib/util/util_net.h"
29 : #include "lib/tls/tls.h"
30 : #include "lib/param/param.h"
31 :
32 : #include <gnutls/gnutls.h>
33 : #include <gnutls/x509.h>
34 : #include "lib/crypto/gnutls_helpers.h"
35 :
36 : #define DH_BITS 2048
37 :
38 17 : const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer)
39 : {
40 17 : switch (verify_peer) {
41 0 : case TLS_VERIFY_PEER_NO_CHECK:
42 0 : return TLS_VERIFY_PEER_NO_CHECK_STRING;
43 :
44 0 : case TLS_VERIFY_PEER_CA_ONLY:
45 0 : return TLS_VERIFY_PEER_CA_ONLY_STRING;
46 :
47 3 : case TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE:
48 3 : return TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING;
49 :
50 6 : case TLS_VERIFY_PEER_CA_AND_NAME:
51 6 : return TLS_VERIFY_PEER_CA_AND_NAME_STRING;
52 :
53 8 : case TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE:
54 8 : return TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING;
55 : }
56 :
57 0 : return "unknown tls_verify_peer_state";
58 : }
59 :
60 : static const struct tstream_context_ops tstream_tls_ops;
61 :
62 : struct tstream_tls {
63 : struct tstream_context *plain_stream;
64 : int error;
65 :
66 : gnutls_session_t tls_session;
67 :
68 : bool is_server;
69 :
70 : enum tls_verify_peer_state verify_peer;
71 : const char *peer_name;
72 :
73 : DATA_BLOB channel_bindings;
74 :
75 : struct tevent_context *current_ev;
76 :
77 : struct tevent_immediate *retry_im;
78 :
79 : struct {
80 : struct tevent_req *mgmt_req;
81 : } waiting_flush;
82 :
83 : struct {
84 : uint8_t *buf;
85 : off_t ofs;
86 : struct iovec iov;
87 : struct tevent_req *subreq;
88 : } push;
89 :
90 : struct {
91 : uint8_t *buf;
92 : struct iovec iov;
93 : struct tevent_req *subreq;
94 : } pull;
95 :
96 : struct {
97 : struct tevent_req *req;
98 : } handshake;
99 :
100 : struct {
101 : off_t ofs;
102 : size_t left;
103 : uint8_t buffer[1024];
104 : struct tevent_req *req;
105 : } write;
106 :
107 : struct {
108 : off_t ofs;
109 : size_t left;
110 : uint8_t buffer[1024];
111 : struct tevent_req *req;
112 : } read;
113 :
114 : struct {
115 : struct tevent_req *req;
116 : } disconnect;
117 : };
118 :
119 : static void tstream_tls_retry_handshake(struct tstream_context *stream);
120 : static void tstream_tls_retry_read(struct tstream_context *stream);
121 : static void tstream_tls_retry_write(struct tstream_context *stream);
122 : static void tstream_tls_retry_disconnect(struct tstream_context *stream);
123 : static void tstream_tls_retry_trigger(struct tevent_context *ctx,
124 : struct tevent_immediate *im,
125 : void *private_data);
126 :
127 3466209 : static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
128 : {
129 :
130 0 : struct tstream_tls *tlss =
131 3466209 : tstream_context_data(stream,
132 : struct tstream_tls);
133 :
134 3466209 : if (tlss->push.subreq == NULL && tlss->pull.subreq == NULL) {
135 3463222 : if (tlss->waiting_flush.mgmt_req != NULL) {
136 588 : struct tevent_req *req = tlss->waiting_flush.mgmt_req;
137 :
138 588 : tlss->waiting_flush.mgmt_req = NULL;
139 :
140 588 : tevent_req_done(req);
141 588 : return;
142 : }
143 : }
144 :
145 3465621 : if (tlss->disconnect.req) {
146 0 : tstream_tls_retry_disconnect(stream);
147 0 : return;
148 : }
149 :
150 3465621 : if (tlss->handshake.req) {
151 19632 : tstream_tls_retry_handshake(stream);
152 19632 : return;
153 : }
154 :
155 3445989 : if (tlss->write.req && tlss->read.req && !deferred) {
156 0 : tevent_schedule_immediate(tlss->retry_im, tlss->current_ev,
157 : tstream_tls_retry_trigger,
158 0 : stream);
159 : }
160 :
161 3445989 : if (tlss->write.req) {
162 1137050 : tstream_tls_retry_write(stream);
163 1137050 : return;
164 : }
165 :
166 2308939 : if (tlss->read.req) {
167 2301559 : tstream_tls_retry_read(stream);
168 2301559 : return;
169 : }
170 : }
171 :
172 0 : static void tstream_tls_retry_trigger(struct tevent_context *ctx,
173 : struct tevent_immediate *im,
174 : void *private_data)
175 : {
176 0 : struct tstream_context *stream =
177 0 : talloc_get_type_abort(private_data,
178 : struct tstream_context);
179 :
180 0 : tstream_tls_retry(stream, true);
181 0 : }
182 :
183 : static void tstream_tls_push_done(struct tevent_req *subreq);
184 :
185 2293926 : static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
186 : const void *buf, size_t size)
187 : {
188 0 : struct tstream_context *stream =
189 2293926 : talloc_get_type_abort(ptr,
190 : struct tstream_context);
191 0 : struct tstream_tls *tlss =
192 2293926 : tstream_context_data(stream,
193 : struct tstream_tls);
194 2293926 : struct tevent_req *subreq = NULL;
195 0 : uint8_t *nbuf;
196 0 : size_t len;
197 :
198 2293926 : if (tlss->error != 0) {
199 0 : errno = tlss->error;
200 0 : return -1;
201 : }
202 :
203 2293926 : if (tlss->push.subreq) {
204 1141480 : errno = EAGAIN;
205 1141480 : return -1;
206 : }
207 :
208 1152446 : len = MIN(size, UINT16_MAX - tlss->push.ofs);
209 :
210 1152446 : if (len == 0) {
211 0 : errno = EAGAIN;
212 0 : return -1;
213 : }
214 :
215 1152446 : nbuf = talloc_realloc(tlss, tlss->push.buf,
216 : uint8_t, tlss->push.ofs + len);
217 1152446 : if (nbuf == NULL) {
218 0 : if (tlss->push.buf) {
219 0 : errno = EAGAIN;
220 0 : return -1;
221 : }
222 :
223 0 : return -1;
224 : }
225 1152446 : tlss->push.buf = nbuf;
226 :
227 1152446 : memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
228 1152446 : tlss->push.ofs += len;
229 :
230 1152446 : tlss->push.iov.iov_base = (char *)tlss->push.buf;
231 1152446 : tlss->push.iov.iov_len = tlss->push.ofs;
232 :
233 1152446 : subreq = tstream_writev_send(tlss,
234 : tlss->current_ev,
235 : tlss->plain_stream,
236 1152446 : &tlss->push.iov, 1);
237 1152446 : if (subreq == NULL) {
238 0 : errno = ENOMEM;
239 0 : return -1;
240 : }
241 1152446 : tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
242 :
243 1152446 : tlss->push.subreq = subreq;
244 1152446 : return len;
245 : }
246 :
247 1152435 : static void tstream_tls_push_done(struct tevent_req *subreq)
248 : {
249 0 : struct tstream_context *stream =
250 1152435 : tevent_req_callback_data(subreq,
251 : struct tstream_context);
252 0 : struct tstream_tls *tlss =
253 1152435 : tstream_context_data(stream,
254 : struct tstream_tls);
255 0 : int ret;
256 0 : int sys_errno;
257 :
258 1152435 : tlss->push.subreq = NULL;
259 1152435 : ZERO_STRUCT(tlss->push.iov);
260 1152435 : TALLOC_FREE(tlss->push.buf);
261 1152435 : tlss->push.ofs = 0;
262 :
263 1152435 : ret = tstream_writev_recv(subreq, &sys_errno);
264 1152435 : TALLOC_FREE(subreq);
265 1152435 : if (ret == -1) {
266 2 : tlss->error = sys_errno;
267 2 : tstream_tls_retry(stream, false);
268 2 : return;
269 : }
270 :
271 1152433 : tstream_tls_retry(stream, false);
272 : }
273 :
274 : static void tstream_tls_pull_done(struct tevent_req *subreq);
275 :
276 4629913 : static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
277 : void *buf, size_t size)
278 : {
279 0 : struct tstream_context *stream =
280 4629913 : talloc_get_type_abort(ptr,
281 : struct tstream_context);
282 0 : struct tstream_tls *tlss =
283 4629913 : tstream_context_data(stream,
284 : struct tstream_tls);
285 0 : struct tevent_req *subreq;
286 0 : size_t len;
287 :
288 4629913 : if (tlss->error != 0) {
289 0 : errno = tlss->error;
290 0 : return -1;
291 : }
292 :
293 4629913 : if (tlss->pull.subreq) {
294 2986 : errno = EAGAIN;
295 2986 : return -1;
296 : }
297 :
298 4626927 : if (tlss->pull.iov.iov_base) {
299 0 : uint8_t *b;
300 0 : size_t n;
301 :
302 2313150 : b = (uint8_t *)tlss->pull.iov.iov_base;
303 :
304 2313150 : n = MIN(tlss->pull.iov.iov_len, size);
305 2313150 : memcpy(buf, b, n);
306 :
307 2313150 : tlss->pull.iov.iov_len -= n;
308 2313150 : b += n;
309 2313150 : tlss->pull.iov.iov_base = (char *)b;
310 2313150 : if (tlss->pull.iov.iov_len == 0) {
311 2313150 : tlss->pull.iov.iov_base = NULL;
312 2313150 : TALLOC_FREE(tlss->pull.buf);
313 : }
314 :
315 2313150 : return n;
316 : }
317 :
318 2313777 : if (size == 0) {
319 0 : return 0;
320 : }
321 :
322 2313777 : len = MIN(size, UINT16_MAX);
323 :
324 2313777 : tlss->pull.buf = talloc_array(tlss, uint8_t, len);
325 2313777 : if (tlss->pull.buf == NULL) {
326 0 : return -1;
327 : }
328 :
329 2313777 : tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
330 2313777 : tlss->pull.iov.iov_len = len;
331 :
332 2313777 : subreq = tstream_readv_send(tlss,
333 : tlss->current_ev,
334 : tlss->plain_stream,
335 : &tlss->pull.iov, 1);
336 2313777 : if (subreq == NULL) {
337 0 : errno = ENOMEM;
338 0 : return -1;
339 : }
340 2313777 : tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
341 :
342 2313777 : tlss->pull.subreq = subreq;
343 2313777 : errno = EAGAIN;
344 2313777 : return -1;
345 : }
346 :
347 2313774 : static void tstream_tls_pull_done(struct tevent_req *subreq)
348 : {
349 0 : struct tstream_context *stream =
350 2313774 : tevent_req_callback_data(subreq,
351 : struct tstream_context);
352 0 : struct tstream_tls *tlss =
353 2313774 : tstream_context_data(stream,
354 : struct tstream_tls);
355 0 : int ret;
356 0 : int sys_errno;
357 :
358 2313774 : tlss->pull.subreq = NULL;
359 :
360 2313774 : ret = tstream_readv_recv(subreq, &sys_errno);
361 2313774 : TALLOC_FREE(subreq);
362 2313774 : if (ret == -1) {
363 624 : tlss->error = sys_errno;
364 624 : tstream_tls_retry(stream, false);
365 624 : return;
366 : }
367 :
368 2313150 : tstream_tls_retry(stream, false);
369 : }
370 :
371 1257 : static int tstream_tls_destructor(struct tstream_tls *tlss)
372 : {
373 1257 : if (tlss->tls_session) {
374 1257 : gnutls_deinit(tlss->tls_session);
375 1257 : tlss->tls_session = NULL;
376 : }
377 :
378 1257 : return 0;
379 : }
380 :
381 220 : static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
382 : {
383 0 : struct tstream_tls *tlss =
384 220 : tstream_context_data(stream,
385 : struct tstream_tls);
386 0 : size_t ret;
387 :
388 220 : if (tlss->error != 0) {
389 0 : errno = tlss->error;
390 0 : return -1;
391 : }
392 :
393 220 : ret = gnutls_record_check_pending(tlss->tls_session);
394 220 : ret += tlss->read.left;
395 :
396 220 : return ret;
397 : }
398 :
399 : struct tstream_tls_readv_state {
400 : struct tstream_context *stream;
401 :
402 : struct iovec *vector;
403 : int count;
404 :
405 : int ret;
406 : };
407 :
408 : static void tstream_tls_readv_crypt_next(struct tevent_req *req);
409 :
410 28100 : static struct tevent_req *tstream_tls_readv_send(TALLOC_CTX *mem_ctx,
411 : struct tevent_context *ev,
412 : struct tstream_context *stream,
413 : struct iovec *vector,
414 : size_t count)
415 : {
416 0 : struct tstream_tls *tlss =
417 28100 : tstream_context_data(stream,
418 : struct tstream_tls);
419 0 : struct tevent_req *req;
420 0 : struct tstream_tls_readv_state *state;
421 :
422 28100 : tlss->read.req = NULL;
423 :
424 28100 : if (tlss->current_ev != ev) {
425 12 : SMB_ASSERT(tlss->push.subreq == NULL);
426 12 : SMB_ASSERT(tlss->pull.subreq == NULL);
427 : }
428 :
429 28100 : tlss->current_ev = ev;
430 :
431 28100 : req = tevent_req_create(mem_ctx, &state,
432 : struct tstream_tls_readv_state);
433 28100 : if (req == NULL) {
434 0 : return NULL;
435 : }
436 :
437 28100 : state->stream = stream;
438 28100 : state->ret = 0;
439 :
440 28100 : if (tlss->error != 0) {
441 0 : tevent_req_error(req, tlss->error);
442 0 : return tevent_req_post(req, ev);
443 : }
444 :
445 : /*
446 : * we make a copy of the vector so we can change the structure
447 : */
448 28100 : state->vector = talloc_array(state, struct iovec, count);
449 28100 : if (tevent_req_nomem(state->vector, req)) {
450 0 : return tevent_req_post(req, ev);
451 : }
452 28100 : memcpy(state->vector, vector, sizeof(struct iovec) * count);
453 28100 : state->count = count;
454 :
455 28100 : tstream_tls_readv_crypt_next(req);
456 28100 : if (!tevent_req_is_in_progress(req)) {
457 16531 : return tevent_req_post(req, ev);
458 : }
459 :
460 11569 : return req;
461 : }
462 :
463 1242269 : static void tstream_tls_readv_crypt_next(struct tevent_req *req)
464 : {
465 0 : struct tstream_tls_readv_state *state =
466 1242269 : tevent_req_data(req,
467 : struct tstream_tls_readv_state);
468 0 : struct tstream_tls *tlss =
469 1242269 : tstream_context_data(state->stream,
470 : struct tstream_tls);
471 :
472 : /*
473 : * copy the pending buffer first
474 : */
475 2475304 : while (tlss->read.left > 0 && state->count > 0) {
476 1233035 : uint8_t *base = (uint8_t *)state->vector[0].iov_base;
477 1233035 : size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
478 :
479 1233035 : memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
480 :
481 1233035 : base += len;
482 1233035 : state->vector[0].iov_base = (char *) base;
483 1233035 : state->vector[0].iov_len -= len;
484 :
485 1233035 : tlss->read.ofs += len;
486 1233035 : tlss->read.left -= len;
487 :
488 1233035 : if (state->vector[0].iov_len == 0) {
489 27469 : state->vector += 1;
490 27469 : state->count -= 1;
491 : }
492 :
493 1233035 : state->ret += len;
494 : }
495 :
496 1242269 : if (state->count == 0) {
497 27469 : tevent_req_done(req);
498 27469 : return;
499 : }
500 :
501 1214800 : tlss->read.req = req;
502 1214800 : tstream_tls_retry_read(state->stream);
503 : }
504 :
505 3516359 : static void tstream_tls_retry_read(struct tstream_context *stream)
506 : {
507 0 : struct tstream_tls *tlss =
508 3516359 : tstream_context_data(stream,
509 : struct tstream_tls);
510 3516359 : struct tevent_req *req = tlss->read.req;
511 0 : int ret;
512 :
513 3516359 : if (tlss->error != 0) {
514 623 : tevent_req_error(req, tlss->error);
515 623 : return;
516 : }
517 :
518 3515736 : tlss->read.left = 0;
519 3515736 : tlss->read.ofs = 0;
520 :
521 7031472 : ret = gnutls_record_recv(tlss->tls_session,
522 3515736 : tlss->read.buffer,
523 : sizeof(tlss->read.buffer));
524 3515736 : if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
525 2301561 : return;
526 : }
527 :
528 1214175 : tlss->read.req = NULL;
529 :
530 1214175 : if (gnutls_error_is_fatal(ret) != 0) {
531 0 : DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
532 0 : tlss->error = EIO;
533 0 : tevent_req_error(req, tlss->error);
534 0 : return;
535 : }
536 :
537 1214175 : if (ret == 0) {
538 6 : tlss->error = EPIPE;
539 6 : tevent_req_error(req, tlss->error);
540 6 : return;
541 : }
542 :
543 1214169 : tlss->read.left = ret;
544 1214169 : tstream_tls_readv_crypt_next(req);
545 : }
546 :
547 28098 : static int tstream_tls_readv_recv(struct tevent_req *req,
548 : int *perrno)
549 : {
550 0 : struct tstream_tls_readv_state *state =
551 28098 : tevent_req_data(req,
552 : struct tstream_tls_readv_state);
553 0 : struct tstream_tls *tlss =
554 28098 : tstream_context_data(state->stream,
555 : struct tstream_tls);
556 0 : int ret;
557 :
558 28098 : tlss->read.req = NULL;
559 :
560 28098 : ret = tsocket_simple_int_recv(req, perrno);
561 28098 : if (ret == 0) {
562 27469 : ret = state->ret;
563 : }
564 :
565 28098 : tevent_req_received(req);
566 28098 : return ret;
567 : }
568 :
569 : struct tstream_tls_writev_state {
570 : struct tstream_context *stream;
571 :
572 : struct iovec *vector;
573 : int count;
574 :
575 : int ret;
576 : };
577 :
578 : static void tstream_tls_writev_crypt_next(struct tevent_req *req);
579 :
580 8575 : static struct tevent_req *tstream_tls_writev_send(TALLOC_CTX *mem_ctx,
581 : struct tevent_context *ev,
582 : struct tstream_context *stream,
583 : const struct iovec *vector,
584 : size_t count)
585 : {
586 0 : struct tstream_tls *tlss =
587 8575 : tstream_context_data(stream,
588 : struct tstream_tls);
589 0 : struct tevent_req *req;
590 0 : struct tstream_tls_writev_state *state;
591 :
592 8575 : tlss->write.req = NULL;
593 :
594 8575 : if (tlss->current_ev != ev) {
595 0 : SMB_ASSERT(tlss->push.subreq == NULL);
596 0 : SMB_ASSERT(tlss->pull.subreq == NULL);
597 : }
598 :
599 8575 : tlss->current_ev = ev;
600 :
601 8575 : req = tevent_req_create(mem_ctx, &state,
602 : struct tstream_tls_writev_state);
603 8575 : if (req == NULL) {
604 0 : return NULL;
605 : }
606 :
607 8575 : state->stream = stream;
608 8575 : state->ret = 0;
609 :
610 8575 : if (tlss->error != 0) {
611 0 : tevent_req_error(req, tlss->error);
612 0 : return tevent_req_post(req, ev);
613 : }
614 :
615 : /*
616 : * we make a copy of the vector so we can change the structure
617 : */
618 8575 : state->vector = talloc_array(state, struct iovec, count);
619 8575 : if (tevent_req_nomem(state->vector, req)) {
620 0 : return tevent_req_post(req, ev);
621 : }
622 8575 : memcpy(state->vector, vector, sizeof(struct iovec) * count);
623 8575 : state->count = count;
624 :
625 8575 : tstream_tls_writev_crypt_next(req);
626 8575 : if (!tevent_req_is_in_progress(req)) {
627 7600 : return tevent_req_post(req, ev);
628 : }
629 :
630 975 : return req;
631 : }
632 :
633 1154171 : static void tstream_tls_writev_crypt_next(struct tevent_req *req)
634 : {
635 0 : struct tstream_tls_writev_state *state =
636 1154171 : tevent_req_data(req,
637 : struct tstream_tls_writev_state);
638 0 : struct tstream_tls *tlss =
639 1154171 : tstream_context_data(state->stream,
640 : struct tstream_tls);
641 :
642 1154171 : tlss->write.left = sizeof(tlss->write.buffer);
643 1154171 : tlss->write.ofs = 0;
644 :
645 : /*
646 : * first fill our buffer
647 : */
648 2304951 : while (tlss->write.left > 0 && state->count > 0) {
649 1150780 : uint8_t *base = (uint8_t *)state->vector[0].iov_base;
650 1150780 : size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
651 :
652 1150780 : memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
653 :
654 1150780 : base += len;
655 1150780 : state->vector[0].iov_base = (char *) base;
656 1150780 : state->vector[0].iov_len -= len;
657 :
658 1150780 : tlss->write.ofs += len;
659 1150780 : tlss->write.left -= len;
660 :
661 1150780 : if (state->vector[0].iov_len == 0) {
662 13776 : state->vector += 1;
663 13776 : state->count -= 1;
664 : }
665 :
666 1150780 : state->ret += len;
667 : }
668 :
669 1154171 : if (tlss->write.ofs == 0) {
670 8575 : tevent_req_done(req);
671 8575 : return;
672 : }
673 :
674 1145596 : tlss->write.left = tlss->write.ofs;
675 1145596 : tlss->write.ofs = 0;
676 :
677 1145596 : tlss->write.req = req;
678 1145596 : tstream_tls_retry_write(state->stream);
679 : }
680 :
681 2282646 : static void tstream_tls_retry_write(struct tstream_context *stream)
682 : {
683 0 : struct tstream_tls *tlss =
684 2282646 : tstream_context_data(stream,
685 : struct tstream_tls);
686 2282646 : struct tevent_req *req = tlss->write.req;
687 0 : int ret;
688 :
689 2282646 : if (tlss->error != 0) {
690 0 : tevent_req_error(req, tlss->error);
691 0 : return;
692 : }
693 :
694 4565292 : ret = gnutls_record_send(tlss->tls_session,
695 2282646 : tlss->write.buffer + tlss->write.ofs,
696 : tlss->write.left);
697 2282646 : if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
698 1137050 : return;
699 : }
700 :
701 1145596 : tlss->write.req = NULL;
702 :
703 1145596 : if (gnutls_error_is_fatal(ret) != 0) {
704 0 : DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
705 0 : tlss->error = EIO;
706 0 : tevent_req_error(req, tlss->error);
707 0 : return;
708 : }
709 :
710 1145596 : if (ret == 0) {
711 0 : tlss->error = EPIPE;
712 0 : tevent_req_error(req, tlss->error);
713 0 : return;
714 : }
715 :
716 1145596 : tlss->write.ofs += ret;
717 1145596 : tlss->write.left -= ret;
718 :
719 1145596 : if (tlss->write.left > 0) {
720 0 : tlss->write.req = req;
721 0 : tstream_tls_retry_write(stream);
722 0 : return;
723 : }
724 :
725 1145596 : tstream_tls_writev_crypt_next(req);
726 : }
727 :
728 8575 : static int tstream_tls_writev_recv(struct tevent_req *req,
729 : int *perrno)
730 : {
731 0 : struct tstream_tls_writev_state *state =
732 8575 : tevent_req_data(req,
733 : struct tstream_tls_writev_state);
734 0 : struct tstream_tls *tlss =
735 8575 : tstream_context_data(state->stream,
736 : struct tstream_tls);
737 0 : int ret;
738 :
739 8575 : tlss->write.req = NULL;
740 :
741 8575 : ret = tsocket_simple_int_recv(req, perrno);
742 8575 : if (ret == 0) {
743 8575 : ret = state->ret;
744 : }
745 :
746 8575 : tevent_req_received(req);
747 8575 : return ret;
748 : }
749 :
750 : struct tstream_tls_disconnect_state {
751 : uint8_t _dummy;
752 : };
753 :
754 638 : static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
755 : struct tevent_context *ev,
756 : struct tstream_context *stream)
757 : {
758 0 : struct tstream_tls *tlss =
759 638 : tstream_context_data(stream,
760 : struct tstream_tls);
761 0 : struct tevent_req *req;
762 0 : struct tstream_tls_disconnect_state *state;
763 :
764 638 : tlss->disconnect.req = NULL;
765 :
766 638 : if (tlss->current_ev != ev) {
767 0 : SMB_ASSERT(tlss->push.subreq == NULL);
768 0 : SMB_ASSERT(tlss->pull.subreq == NULL);
769 : }
770 :
771 638 : tlss->current_ev = ev;
772 :
773 638 : req = tevent_req_create(mem_ctx, &state,
774 : struct tstream_tls_disconnect_state);
775 638 : if (req == NULL) {
776 0 : return NULL;
777 : }
778 :
779 638 : if (tlss->error != 0) {
780 629 : tevent_req_error(req, tlss->error);
781 629 : return tevent_req_post(req, ev);
782 : }
783 :
784 9 : tlss->disconnect.req = req;
785 9 : tstream_tls_retry_disconnect(stream);
786 9 : if (!tevent_req_is_in_progress(req)) {
787 0 : return tevent_req_post(req, ev);
788 : }
789 :
790 9 : return req;
791 : }
792 :
793 9 : static void tstream_tls_retry_disconnect(struct tstream_context *stream)
794 : {
795 0 : struct tstream_tls *tlss =
796 9 : tstream_context_data(stream,
797 : struct tstream_tls);
798 9 : struct tevent_req *req = tlss->disconnect.req;
799 0 : int ret;
800 :
801 9 : if (tlss->error != 0) {
802 0 : tevent_req_error(req, tlss->error);
803 0 : return;
804 : }
805 :
806 9 : ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
807 9 : if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
808 0 : return;
809 : }
810 :
811 9 : tlss->disconnect.req = NULL;
812 :
813 9 : if (gnutls_error_is_fatal(ret) != 0) {
814 0 : DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
815 0 : tlss->error = EIO;
816 0 : tevent_req_error(req, tlss->error);
817 0 : return;
818 : }
819 :
820 9 : if (ret != GNUTLS_E_SUCCESS) {
821 0 : DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
822 0 : tlss->error = EIO;
823 0 : tevent_req_error(req, tlss->error);
824 0 : return;
825 : }
826 :
827 9 : if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
828 9 : tlss->waiting_flush.mgmt_req = req;
829 9 : return;
830 : }
831 :
832 0 : tevent_req_done(req);
833 : }
834 :
835 638 : static int tstream_tls_disconnect_recv(struct tevent_req *req,
836 : int *perrno)
837 : {
838 0 : int ret;
839 :
840 638 : ret = tsocket_simple_int_recv(req, perrno);
841 :
842 638 : tevent_req_received(req);
843 638 : return ret;
844 : }
845 :
846 : static const struct tstream_context_ops tstream_tls_ops = {
847 : .name = "tls",
848 :
849 : .pending_bytes = tstream_tls_pending_bytes,
850 :
851 : .readv_send = tstream_tls_readv_send,
852 : .readv_recv = tstream_tls_readv_recv,
853 :
854 : .writev_send = tstream_tls_writev_send,
855 : .writev_recv = tstream_tls_writev_recv,
856 :
857 : .disconnect_send = tstream_tls_disconnect_send,
858 : .disconnect_recv = tstream_tls_disconnect_recv,
859 : };
860 :
861 : struct tstream_tls_params_internal {
862 : gnutls_certificate_credentials_t x509_cred;
863 : gnutls_dh_params_t dh_params;
864 : const char *tls_priority;
865 : bool tls_enabled;
866 : enum tls_verify_peer_state verify_peer;
867 : const char *peer_name;
868 : };
869 :
870 : struct tstream_tls_params {
871 : struct tstream_tls_params_internal *internal;
872 : };
873 :
874 15966 : static int tstream_tls_params_internal_destructor(struct tstream_tls_params_internal *tlsp)
875 : {
876 15966 : if (tlsp->x509_cred) {
877 15966 : gnutls_certificate_free_credentials(tlsp->x509_cred);
878 15966 : tlsp->x509_cred = NULL;
879 : }
880 15966 : if (tlsp->dh_params) {
881 15344 : gnutls_dh_params_deinit(tlsp->dh_params);
882 15344 : tlsp->dh_params = NULL;
883 : }
884 :
885 15966 : return 0;
886 : }
887 :
888 240 : bool tstream_tls_params_enabled(struct tstream_tls_params *tls_params)
889 : {
890 240 : struct tstream_tls_params_internal *tlsp = tls_params->internal;
891 :
892 240 : return tlsp->tls_enabled;
893 : }
894 :
895 1243 : static NTSTATUS tstream_tls_setup_channel_bindings(struct tstream_tls *tlss)
896 : {
897 1243 : gnutls_datum_t cb = { .size = 0 };
898 0 : int ret;
899 :
900 : #ifdef HAVE_GNUTLS_CB_TLS_SERVER_END_POINT
901 1243 : ret = gnutls_session_channel_binding(tlss->tls_session,
902 : GNUTLS_CB_TLS_SERVER_END_POINT,
903 : &cb);
904 : #else /* not HAVE_GNUTLS_CB_TLS_SERVER_END_POINT */
905 : ret = legacy_gnutls_server_end_point_cb(tlss->tls_session,
906 : tlss->is_server,
907 : &cb);
908 : #endif /* not HAVE_GNUTLS_CB_TLS_SERVER_END_POINT */
909 1243 : if (ret != GNUTLS_E_SUCCESS) {
910 0 : return gnutls_error_to_ntstatus(ret,
911 : NT_STATUS_CRYPTO_SYSTEM_INVALID);
912 : }
913 :
914 1243 : if (cb.size != 0) {
915 : /*
916 : * Looking at the OpenLDAP implementation
917 : * for LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT
918 : * revealed that we need to prefix it with
919 : * 'tls-server-end-point:'
920 : */
921 1243 : const char endpoint_prefix[] = "tls-server-end-point:";
922 1243 : size_t prefix_size = strlen(endpoint_prefix);
923 1243 : size_t size = prefix_size + cb.size;
924 :
925 1243 : tlss->channel_bindings = data_blob_talloc_named(tlss, NULL, size,
926 : "tls_channel_bindings");
927 1243 : if (tlss->channel_bindings.data == NULL) {
928 0 : gnutls_free(cb.data);
929 0 : return NT_STATUS_NO_MEMORY;
930 : }
931 1243 : memcpy(tlss->channel_bindings.data, endpoint_prefix, prefix_size);
932 1243 : memcpy(tlss->channel_bindings.data + prefix_size, cb.data, cb.size);
933 1243 : gnutls_free(cb.data);
934 : }
935 :
936 1243 : return NT_STATUS_OK;
937 : }
938 :
939 350 : const DATA_BLOB *tstream_tls_channel_bindings(struct tstream_context *tls_tstream)
940 : {
941 0 : struct tstream_tls *tlss =
942 350 : talloc_get_type(_tstream_context_data(tls_tstream),
943 : struct tstream_tls);
944 :
945 350 : if (tlss == NULL) {
946 0 : return NULL;
947 : }
948 :
949 350 : return &tlss->channel_bindings;
950 : }
951 :
952 622 : NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
953 : bool system_cas,
954 : const char * const *ca_dirs,
955 : const char *ca_file,
956 : const char *crl_file,
957 : const char *tls_priority,
958 : enum tls_verify_peer_state verify_peer,
959 : const char *peer_name,
960 : struct tstream_tls_params **_tlsp)
961 : {
962 622 : struct tstream_tls_params *__tlsp = NULL;
963 622 : struct tstream_tls_params_internal *tlsp = NULL;
964 622 : bool got_ca = false;
965 0 : size_t i;
966 0 : int ret;
967 :
968 622 : __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
969 622 : if (__tlsp == NULL) {
970 0 : return NT_STATUS_NO_MEMORY;
971 : }
972 :
973 622 : tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
974 622 : if (tlsp == NULL) {
975 0 : TALLOC_FREE(__tlsp);
976 0 : return NT_STATUS_NO_MEMORY;
977 : }
978 622 : talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
979 622 : __tlsp->internal = tlsp;
980 :
981 622 : tlsp->verify_peer = verify_peer;
982 622 : if (peer_name != NULL) {
983 622 : tlsp->peer_name = talloc_strdup(tlsp, peer_name);
984 622 : if (tlsp->peer_name == NULL) {
985 0 : TALLOC_FREE(__tlsp);
986 0 : return NT_STATUS_NO_MEMORY;
987 : }
988 0 : } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
989 0 : DEBUG(0,("TLS failed to missing peer_name - "
990 : "with 'tls verify peer = %s'\n",
991 : tls_verify_peer_string(tlsp->verify_peer)));
992 0 : TALLOC_FREE(__tlsp);
993 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
994 : }
995 :
996 622 : ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
997 622 : if (ret != GNUTLS_E_SUCCESS) {
998 0 : DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
999 0 : TALLOC_FREE(__tlsp);
1000 0 : return NT_STATUS_NO_MEMORY;
1001 : }
1002 :
1003 622 : if (system_cas) {
1004 0 : ret = gnutls_certificate_set_x509_system_trust(tlsp->x509_cred);
1005 0 : if (ret < 0) {
1006 0 : DBG_ERR("gnutls_certificate_set_x509_system_trust() - %s\n",
1007 : gnutls_strerror(ret));
1008 0 : TALLOC_FREE(__tlsp);
1009 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1010 : }
1011 0 : if (ret > 0) {
1012 0 : got_ca = true;
1013 : }
1014 : }
1015 :
1016 622 : for (i = 0; ca_dirs != NULL && ca_dirs[i] != NULL; i++) {
1017 0 : const char *ca_dir = ca_dirs[i];
1018 :
1019 0 : if (!directory_exist(ca_dir)) {
1020 0 : continue;
1021 : }
1022 :
1023 0 : ret = gnutls_certificate_set_x509_trust_dir(tlsp->x509_cred,
1024 : ca_dir,
1025 : GNUTLS_X509_FMT_PEM);
1026 0 : if (ret < 0) {
1027 0 : DBG_ERR("gnutls_certificate_set_x509_trust_dir(%s) - %s\n",
1028 : ca_dir, gnutls_strerror(ret));
1029 0 : TALLOC_FREE(__tlsp);
1030 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1031 : }
1032 0 : if (ret > 0) {
1033 0 : got_ca = true;
1034 : }
1035 : }
1036 :
1037 622 : if (ca_file && *ca_file && file_exist(ca_file)) {
1038 598 : ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1039 : ca_file,
1040 : GNUTLS_X509_FMT_PEM);
1041 598 : if (ret < 0) {
1042 0 : DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1043 : ca_file, gnutls_strerror(ret)));
1044 0 : TALLOC_FREE(__tlsp);
1045 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1046 : }
1047 598 : if (ret > 0) {
1048 598 : got_ca = true;
1049 : }
1050 : }
1051 :
1052 622 : if (!got_ca && tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
1053 0 : D_ERR("TLS: 'tls verify peer = %s' requires "
1054 : "'tls trust system cas', "
1055 : "'tls ca directories' or "
1056 : "'tls cafile'\n",
1057 : tls_verify_peer_string(tlsp->verify_peer));
1058 0 : TALLOC_FREE(__tlsp);
1059 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1060 : }
1061 :
1062 622 : if (crl_file && *crl_file && file_exist(crl_file)) {
1063 481 : ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1064 : crl_file,
1065 : GNUTLS_X509_FMT_PEM);
1066 481 : if (ret < 0) {
1067 0 : DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1068 : crl_file, gnutls_strerror(ret)));
1069 0 : TALLOC_FREE(__tlsp);
1070 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1071 : }
1072 141 : } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE) {
1073 6 : DEBUG(0,("TLS failed to missing crlfile %s - "
1074 : "with 'tls verify peer = %s'\n",
1075 : crl_file,
1076 : tls_verify_peer_string(tlsp->verify_peer)));
1077 6 : TALLOC_FREE(__tlsp);
1078 6 : return NT_STATUS_INVALID_PARAMETER_MIX;
1079 : }
1080 :
1081 616 : tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
1082 616 : if (tlsp->tls_priority == NULL) {
1083 0 : TALLOC_FREE(__tlsp);
1084 0 : return NT_STATUS_NO_MEMORY;
1085 : }
1086 :
1087 616 : tlsp->tls_enabled = true;
1088 :
1089 616 : *_tlsp = __tlsp;
1090 616 : return NT_STATUS_OK;
1091 : }
1092 :
1093 622 : NTSTATUS tstream_tls_params_client_lpcfg(TALLOC_CTX *mem_ctx,
1094 : struct loadparm_context *lp_ctx,
1095 : const char *peer_name,
1096 : struct tstream_tls_params **tlsp)
1097 : {
1098 622 : TALLOC_CTX *frame = talloc_stackframe();
1099 622 : bool system_cas = false;
1100 622 : const char * const *ca_dirs = NULL;
1101 622 : const char *ptr = NULL;
1102 622 : char *ca_file = NULL;
1103 622 : char *crl_file = NULL;
1104 622 : const char *tls_priority = NULL;
1105 622 : enum tls_verify_peer_state verify_peer =
1106 : TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE;
1107 0 : NTSTATUS status;
1108 :
1109 622 : system_cas = lpcfg_tls_trust_system_cas(lp_ctx);
1110 622 : ca_dirs = lpcfg_tls_ca_directories(lp_ctx);
1111 :
1112 622 : ptr = lpcfg__tls_cafile(lp_ctx);
1113 622 : if (ptr != NULL) {
1114 622 : ca_file = lpcfg_tls_cafile(frame, lp_ctx);
1115 622 : if (ca_file == NULL) {
1116 0 : TALLOC_FREE(frame);
1117 0 : return NT_STATUS_NO_MEMORY;
1118 : }
1119 : }
1120 :
1121 622 : ptr = lpcfg__tls_crlfile(lp_ctx);
1122 622 : if (ptr != NULL) {
1123 622 : crl_file = lpcfg_tls_crlfile(frame, lp_ctx);
1124 622 : if (crl_file == NULL) {
1125 0 : TALLOC_FREE(frame);
1126 0 : return NT_STATUS_NO_MEMORY;
1127 : }
1128 : }
1129 :
1130 622 : tls_priority = lpcfg_tls_priority(lp_ctx);
1131 622 : verify_peer = lpcfg_tls_verify_peer(lp_ctx);
1132 :
1133 622 : status = tstream_tls_params_client(mem_ctx,
1134 : system_cas,
1135 : ca_dirs,
1136 : ca_file,
1137 : crl_file,
1138 : tls_priority,
1139 : verify_peer,
1140 : peer_name,
1141 : tlsp);
1142 622 : TALLOC_FREE(frame);
1143 622 : return status;
1144 : }
1145 :
1146 1257 : static NTSTATUS tstream_tls_prepare_gnutls(struct tstream_tls_params *_tlsp,
1147 : struct tstream_tls *tlss)
1148 : {
1149 1257 : struct tstream_tls_params_internal *tlsp = NULL;
1150 0 : int ret;
1151 0 : unsigned int flags;
1152 1257 : const char *hostname = NULL;
1153 :
1154 1257 : if (tlss->is_server) {
1155 641 : flags = GNUTLS_SERVER;
1156 : } else {
1157 616 : flags = GNUTLS_CLIENT;
1158 : /*
1159 : * tls_tstream can't properly handle 'New Session Ticket'
1160 : * messages sent 'after' the client sends the 'Finished'
1161 : * message. GNUTLS_NO_TICKETS was introduced in GnuTLS 3.5.6.
1162 : * This flag is to indicate the session Flag session should not
1163 : * use resumption with session tickets.
1164 : */
1165 616 : flags |= GNUTLS_NO_TICKETS;
1166 : }
1167 :
1168 : /*
1169 : * Note we need to make sure x509_cred and dh_params
1170 : * from tstream_tls_params_internal stay alive for
1171 : * the whole lifetime of this session!
1172 : *
1173 : * See 'man gnutls_credentials_set' and
1174 : * 'man gnutls_certificate_set_dh_params'.
1175 : *
1176 : * Note: here we use talloc_reference() in a way
1177 : * that does not expose it to the caller.
1178 : */
1179 1257 : tlsp = talloc_reference(tlss, _tlsp->internal);
1180 1257 : if (tlsp == NULL) {
1181 0 : return NT_STATUS_NO_MEMORY;
1182 : }
1183 :
1184 1257 : tlss->verify_peer = tlsp->verify_peer;
1185 1257 : if (tlsp->peer_name != NULL) {
1186 616 : bool ip = is_ipaddress(tlsp->peer_name);
1187 :
1188 616 : tlss->peer_name = talloc_strdup(tlss, tlsp->peer_name);
1189 616 : if (tlss->peer_name == NULL) {
1190 0 : return NT_STATUS_NO_MEMORY;
1191 : }
1192 :
1193 616 : if (!ip) {
1194 564 : hostname = tlss->peer_name;
1195 : }
1196 :
1197 616 : if (tlss->verify_peer < TLS_VERIFY_PEER_CA_AND_NAME) {
1198 604 : hostname = NULL;
1199 : }
1200 : }
1201 :
1202 1257 : if (tlss->current_ev != NULL) {
1203 1233 : tlss->retry_im = tevent_create_immediate(tlss);
1204 1233 : if (tlss->retry_im == NULL) {
1205 0 : return NT_STATUS_NO_MEMORY;
1206 : }
1207 : }
1208 :
1209 1257 : ret = gnutls_init(&tlss->tls_session, flags);
1210 1257 : if (ret != GNUTLS_E_SUCCESS) {
1211 0 : return gnutls_error_to_ntstatus(ret,
1212 : NT_STATUS_CRYPTO_SYSTEM_INVALID);
1213 : }
1214 :
1215 1257 : ret = gnutls_set_default_priority(tlss->tls_session);
1216 1257 : if (ret != GNUTLS_E_SUCCESS) {
1217 0 : return gnutls_error_to_ntstatus(ret,
1218 : NT_STATUS_CRYPTO_SYSTEM_INVALID);
1219 : }
1220 :
1221 1257 : if (strlen(tlsp->tls_priority) > 0) {
1222 1257 : const char *error_pos = NULL;
1223 :
1224 1257 : ret = gnutls_priority_set_direct(tlss->tls_session,
1225 : tlsp->tls_priority,
1226 : &error_pos);
1227 1257 : if (ret != GNUTLS_E_SUCCESS) {
1228 1 : return gnutls_error_to_ntstatus(ret,
1229 : NT_STATUS_CRYPTO_SYSTEM_INVALID);
1230 : }
1231 : }
1232 :
1233 1256 : ret = gnutls_credentials_set(tlss->tls_session,
1234 : GNUTLS_CRD_CERTIFICATE,
1235 1256 : tlsp->x509_cred);
1236 1256 : if (ret != GNUTLS_E_SUCCESS) {
1237 0 : return gnutls_error_to_ntstatus(ret,
1238 : NT_STATUS_CRYPTO_SYSTEM_INVALID);
1239 : }
1240 :
1241 1256 : if (hostname != NULL) {
1242 8 : ret = gnutls_server_name_set(tlss->tls_session,
1243 : GNUTLS_NAME_DNS,
1244 : hostname,
1245 : strlen(hostname));
1246 8 : if (ret != GNUTLS_E_SUCCESS) {
1247 0 : return gnutls_error_to_ntstatus(ret,
1248 : NT_STATUS_CRYPTO_SYSTEM_INVALID);
1249 : }
1250 : }
1251 :
1252 1256 : if (tlss->is_server) {
1253 641 : gnutls_certificate_server_set_request(tlss->tls_session,
1254 : GNUTLS_CERT_REQUEST);
1255 641 : gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
1256 : }
1257 :
1258 1256 : return NT_STATUS_OK;
1259 : }
1260 :
1261 1254 : static NTSTATUS tstream_tls_verify_peer(struct tstream_tls *tlss)
1262 : {
1263 1254 : unsigned int status = UINT32_MAX;
1264 1254 : bool ip = true;
1265 1254 : const char *hostname = NULL;
1266 0 : int ret;
1267 :
1268 1254 : if (tlss->verify_peer == TLS_VERIFY_PEER_NO_CHECK) {
1269 1224 : return NT_STATUS_OK;
1270 : }
1271 :
1272 30 : if (tlss->peer_name != NULL) {
1273 30 : ip = is_ipaddress(tlss->peer_name);
1274 : }
1275 :
1276 30 : if (!ip) {
1277 20 : hostname = tlss->peer_name;
1278 : }
1279 :
1280 30 : if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
1281 9 : hostname = NULL;
1282 : }
1283 :
1284 30 : if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
1285 12 : if (hostname == NULL) {
1286 4 : DEBUG(1,("TLS %s - no hostname available for "
1287 : "verify_peer[%s] and peer_name[%s]\n",
1288 : __location__,
1289 : tls_verify_peer_string(tlss->verify_peer),
1290 : tlss->peer_name));
1291 4 : return NT_STATUS_IMAGE_CERT_REVOKED;
1292 : }
1293 : }
1294 :
1295 26 : ret = gnutls_certificate_verify_peers3(tlss->tls_session,
1296 : hostname,
1297 : &status);
1298 26 : if (ret != GNUTLS_E_SUCCESS) {
1299 0 : return gnutls_error_to_ntstatus(ret,
1300 : NT_STATUS_CRYPTO_SYSTEM_INVALID);
1301 : }
1302 :
1303 26 : if (status != 0) {
1304 7 : DEBUG(1,("TLS %s - check failed for "
1305 : "verify_peer[%s] and peer_name[%s] "
1306 : "status 0x%x (%s%s%s%s%s%s%s%s)\n",
1307 : __location__,
1308 : tls_verify_peer_string(tlss->verify_peer),
1309 : tlss->peer_name,
1310 : status,
1311 : status & GNUTLS_CERT_INVALID ? "invalid " : "",
1312 : status & GNUTLS_CERT_REVOKED ? "revoked " : "",
1313 : status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
1314 : "signer_not_found " : "",
1315 : status & GNUTLS_CERT_SIGNER_NOT_CA ?
1316 : "signer_not_ca " : "",
1317 : status & GNUTLS_CERT_INSECURE_ALGORITHM ?
1318 : "insecure_algorithm " : "",
1319 : status & GNUTLS_CERT_NOT_ACTIVATED ?
1320 : "not_activated " : "",
1321 : status & GNUTLS_CERT_EXPIRED ?
1322 : "expired " : "",
1323 : status & GNUTLS_CERT_UNEXPECTED_OWNER ?
1324 : "unexpected_owner " : ""));
1325 7 : return NT_STATUS_IMAGE_CERT_REVOKED;
1326 : }
1327 :
1328 19 : return NT_STATUS_OK;
1329 : }
1330 :
1331 : struct tstream_tls_connect_state {
1332 : struct tstream_context *tls_stream;
1333 : };
1334 :
1335 592 : struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
1336 : struct tevent_context *ev,
1337 : struct tstream_context *plain_stream,
1338 : struct tstream_tls_params *_tls_params,
1339 : const char *location)
1340 : {
1341 0 : struct tevent_req *req;
1342 0 : struct tstream_tls_connect_state *state;
1343 0 : struct tstream_tls *tlss;
1344 0 : NTSTATUS status;
1345 :
1346 592 : req = tevent_req_create(mem_ctx, &state,
1347 : struct tstream_tls_connect_state);
1348 592 : if (req == NULL) {
1349 0 : return NULL;
1350 : }
1351 :
1352 592 : state->tls_stream = tstream_context_create(state,
1353 : &tstream_tls_ops,
1354 : &tlss,
1355 : struct tstream_tls,
1356 : location);
1357 592 : if (tevent_req_nomem(state->tls_stream, req)) {
1358 0 : return tevent_req_post(req, ev);
1359 : }
1360 592 : ZERO_STRUCTP(tlss);
1361 592 : talloc_set_destructor(tlss, tstream_tls_destructor);
1362 592 : tlss->plain_stream = plain_stream;
1363 592 : tlss->is_server = false;
1364 592 : tlss->current_ev = ev;
1365 :
1366 592 : status = tstream_tls_prepare_gnutls(_tls_params, tlss);
1367 592 : if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1368 0 : tevent_req_oom(req);
1369 0 : return tevent_req_post(req, ev);
1370 : }
1371 592 : if (!NT_STATUS_IS_OK(status)) {
1372 1 : tevent_req_error(req, EINVAL);
1373 1 : return tevent_req_post(req, ev);
1374 : }
1375 :
1376 591 : gnutls_transport_set_ptr(tlss->tls_session,
1377 591 : (gnutls_transport_ptr_t)state->tls_stream);
1378 591 : gnutls_transport_set_pull_function(tlss->tls_session,
1379 : (gnutls_pull_func)tstream_tls_pull_function);
1380 591 : gnutls_transport_set_push_function(tlss->tls_session,
1381 : (gnutls_push_func)tstream_tls_push_function);
1382 :
1383 591 : tlss->handshake.req = req;
1384 591 : tstream_tls_retry_handshake(state->tls_stream);
1385 591 : if (!tevent_req_is_in_progress(req)) {
1386 0 : return tevent_req_post(req, ev);
1387 : }
1388 :
1389 591 : return req;
1390 : }
1391 :
1392 592 : int tstream_tls_connect_recv(struct tevent_req *req,
1393 : int *perrno,
1394 : TALLOC_CTX *mem_ctx,
1395 : struct tstream_context **tls_stream)
1396 : {
1397 0 : struct tstream_tls_connect_state *state =
1398 592 : tevent_req_data(req,
1399 : struct tstream_tls_connect_state);
1400 :
1401 592 : if (tevent_req_is_unix_error(req, perrno)) {
1402 13 : tevent_req_received(req);
1403 13 : return -1;
1404 : }
1405 :
1406 579 : *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1407 579 : tevent_req_received(req);
1408 579 : return 0;
1409 : }
1410 :
1411 : /*
1412 : initialise global tls state
1413 : */
1414 62 : NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
1415 : const char *dns_host_name,
1416 : bool enabled,
1417 : const char *key_file,
1418 : const char *cert_file,
1419 : const char *ca_file,
1420 : const char *crl_file,
1421 : const char *dhp_file,
1422 : const char *tls_priority,
1423 : struct tstream_tls_params **_tlsp)
1424 : {
1425 62 : struct tstream_tls_params *__tlsp = NULL;
1426 62 : struct tstream_tls_params_internal *tlsp = NULL;
1427 2 : int ret;
1428 2 : struct stat st;
1429 :
1430 62 : if (!enabled || key_file == NULL || *key_file == 0) {
1431 0 : __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1432 0 : if (__tlsp == NULL) {
1433 0 : return NT_STATUS_NO_MEMORY;
1434 : }
1435 :
1436 0 : tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1437 0 : if (tlsp == NULL) {
1438 0 : TALLOC_FREE(__tlsp);
1439 0 : return NT_STATUS_NO_MEMORY;
1440 : }
1441 :
1442 0 : talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1443 0 : __tlsp->internal = tlsp;
1444 0 : tlsp->tls_enabled = false;
1445 :
1446 0 : *_tlsp = __tlsp;
1447 0 : return NT_STATUS_OK;
1448 : }
1449 :
1450 62 : __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1451 62 : if (__tlsp == NULL) {
1452 0 : return NT_STATUS_NO_MEMORY;
1453 : }
1454 :
1455 62 : tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1456 62 : if (tlsp == NULL) {
1457 0 : TALLOC_FREE(__tlsp);
1458 0 : return NT_STATUS_NO_MEMORY;
1459 : }
1460 :
1461 62 : talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1462 62 : __tlsp->internal = tlsp;
1463 :
1464 62 : if (!file_exist(ca_file)) {
1465 33 : tls_cert_generate(tlsp, dns_host_name,
1466 : key_file, cert_file, ca_file);
1467 : }
1468 :
1469 64 : if (file_exist(key_file) &&
1470 62 : !file_check_permissions(key_file, geteuid(), 0600, &st))
1471 : {
1472 0 : DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
1473 : "owner uid %u should be %u, mode 0%o should be 0%o\n"
1474 : "This is known as CVE-2013-4476.\n"
1475 : "Removing all tls .pem files will cause an "
1476 : "auto-regeneration with the correct permissions.\n",
1477 : key_file,
1478 : (unsigned int)st.st_uid, geteuid(),
1479 : (unsigned int)(st.st_mode & 0777), 0600));
1480 0 : TALLOC_FREE(__tlsp);
1481 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1482 : }
1483 :
1484 62 : ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
1485 62 : if (ret != GNUTLS_E_SUCCESS) {
1486 0 : DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1487 0 : TALLOC_FREE(__tlsp);
1488 0 : return NT_STATUS_NO_MEMORY;
1489 : }
1490 :
1491 62 : if (ca_file && *ca_file) {
1492 62 : ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1493 : ca_file,
1494 : GNUTLS_X509_FMT_PEM);
1495 62 : if (ret < 0) {
1496 0 : DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1497 : ca_file, gnutls_strerror(ret)));
1498 0 : TALLOC_FREE(__tlsp);
1499 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1500 : }
1501 : }
1502 :
1503 62 : if (crl_file && *crl_file) {
1504 27 : ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1505 : crl_file,
1506 : GNUTLS_X509_FMT_PEM);
1507 27 : if (ret < 0) {
1508 0 : DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1509 : crl_file, gnutls_strerror(ret)));
1510 0 : TALLOC_FREE(__tlsp);
1511 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1512 : }
1513 : }
1514 :
1515 62 : ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
1516 : cert_file, key_file,
1517 : GNUTLS_X509_FMT_PEM);
1518 62 : if (ret != GNUTLS_E_SUCCESS) {
1519 0 : DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1520 : cert_file, key_file, gnutls_strerror(ret)));
1521 0 : TALLOC_FREE(__tlsp);
1522 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1523 : }
1524 :
1525 62 : ret = gnutls_dh_params_init(&tlsp->dh_params);
1526 62 : if (ret != GNUTLS_E_SUCCESS) {
1527 0 : DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1528 0 : TALLOC_FREE(__tlsp);
1529 0 : return NT_STATUS_NO_MEMORY;
1530 : }
1531 :
1532 124 : if (dhp_file && *dhp_file) {
1533 2 : gnutls_datum_t dhparms;
1534 2 : size_t size;
1535 :
1536 62 : dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
1537 :
1538 62 : if (!dhparms.data) {
1539 0 : DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1540 : dhp_file, errno, strerror(errno)));
1541 0 : TALLOC_FREE(__tlsp);
1542 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1543 : }
1544 62 : dhparms.size = size;
1545 :
1546 62 : ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
1547 : &dhparms,
1548 : GNUTLS_X509_FMT_PEM);
1549 62 : if (ret != GNUTLS_E_SUCCESS) {
1550 0 : DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1551 : dhp_file, gnutls_strerror(ret)));
1552 0 : TALLOC_FREE(__tlsp);
1553 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1554 : }
1555 : } else {
1556 0 : ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
1557 0 : if (ret != GNUTLS_E_SUCCESS) {
1558 0 : DEBUG(0,("TLS failed to generate dh_params - %s\n",
1559 : gnutls_strerror(ret)));
1560 0 : TALLOC_FREE(__tlsp);
1561 0 : return NT_STATUS_INTERNAL_ERROR;
1562 : }
1563 : }
1564 :
1565 62 : gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
1566 :
1567 62 : tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
1568 62 : if (tlsp->tls_priority == NULL) {
1569 0 : TALLOC_FREE(__tlsp);
1570 0 : return NT_STATUS_NO_MEMORY;
1571 : }
1572 :
1573 62 : tlsp->tls_enabled = true;
1574 :
1575 62 : *_tlsp = __tlsp;
1576 62 : return NT_STATUS_OK;
1577 : }
1578 :
1579 : struct tstream_tls_accept_state {
1580 : struct tstream_context *tls_stream;
1581 : };
1582 :
1583 641 : struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
1584 : struct tevent_context *ev,
1585 : struct tstream_context *plain_stream,
1586 : struct tstream_tls_params *_tlsp,
1587 : const char *location)
1588 : {
1589 0 : struct tevent_req *req;
1590 0 : struct tstream_tls_accept_state *state;
1591 0 : struct tstream_tls *tlss;
1592 0 : NTSTATUS status;
1593 :
1594 641 : req = tevent_req_create(mem_ctx, &state,
1595 : struct tstream_tls_accept_state);
1596 641 : if (req == NULL) {
1597 0 : return NULL;
1598 : }
1599 :
1600 641 : state->tls_stream = tstream_context_create(state,
1601 : &tstream_tls_ops,
1602 : &tlss,
1603 : struct tstream_tls,
1604 : location);
1605 641 : if (tevent_req_nomem(state->tls_stream, req)) {
1606 0 : return tevent_req_post(req, ev);
1607 : }
1608 641 : ZERO_STRUCTP(tlss);
1609 641 : talloc_set_destructor(tlss, tstream_tls_destructor);
1610 641 : tlss->plain_stream = plain_stream;
1611 641 : tlss->is_server = true;
1612 641 : tlss->current_ev = ev;
1613 :
1614 641 : status = tstream_tls_prepare_gnutls(_tlsp, tlss);
1615 641 : if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1616 0 : tevent_req_oom(req);
1617 0 : return tevent_req_post(req, ev);
1618 : }
1619 641 : if (!NT_STATUS_IS_OK(status)) {
1620 0 : tevent_req_error(req, EINVAL);
1621 0 : return tevent_req_post(req, ev);
1622 : }
1623 :
1624 641 : gnutls_transport_set_ptr(tlss->tls_session,
1625 641 : (gnutls_transport_ptr_t)state->tls_stream);
1626 641 : gnutls_transport_set_pull_function(tlss->tls_session,
1627 : (gnutls_pull_func)tstream_tls_pull_function);
1628 641 : gnutls_transport_set_push_function(tlss->tls_session,
1629 : (gnutls_push_func)tstream_tls_push_function);
1630 :
1631 641 : tlss->handshake.req = req;
1632 641 : tstream_tls_retry_handshake(state->tls_stream);
1633 641 : if (!tevent_req_is_in_progress(req)) {
1634 0 : return tevent_req_post(req, ev);
1635 : }
1636 :
1637 641 : return req;
1638 : }
1639 :
1640 20864 : static void tstream_tls_retry_handshake(struct tstream_context *stream)
1641 : {
1642 0 : struct tstream_tls *tlss =
1643 20864 : tstream_context_data(stream,
1644 : struct tstream_tls);
1645 20864 : struct tevent_req *req = tlss->handshake.req;
1646 0 : NTSTATUS status;
1647 0 : int ret;
1648 :
1649 20864 : if (tlss->error != 0) {
1650 2 : tevent_req_error(req, tlss->error);
1651 20224 : return;
1652 : }
1653 :
1654 20862 : ret = gnutls_handshake(tlss->tls_session);
1655 20862 : if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
1656 19632 : return;
1657 : }
1658 :
1659 1230 : tlss->handshake.req = NULL;
1660 :
1661 1230 : if (gnutls_error_is_fatal(ret) != 0) {
1662 0 : DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1663 0 : tlss->error = EIO;
1664 0 : tevent_req_error(req, tlss->error);
1665 0 : return;
1666 : }
1667 :
1668 1230 : if (ret != GNUTLS_E_SUCCESS) {
1669 0 : DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1670 0 : tlss->error = EIO;
1671 0 : tevent_req_error(req, tlss->error);
1672 0 : return;
1673 : }
1674 :
1675 1230 : status = tstream_tls_verify_peer(tlss);
1676 1230 : if (NT_STATUS_EQUAL(status, NT_STATUS_IMAGE_CERT_REVOKED)) {
1677 11 : tlss->error = EINVAL;
1678 11 : tevent_req_error(req, tlss->error);
1679 11 : return;
1680 : }
1681 1219 : if (!NT_STATUS_IS_OK(status)) {
1682 0 : tlss->error = EIO;
1683 0 : tevent_req_error(req, tlss->error);
1684 0 : return;
1685 : }
1686 :
1687 1219 : status = tstream_tls_setup_channel_bindings(tlss);
1688 1219 : if (!NT_STATUS_IS_OK(status)) {
1689 0 : tlss->error = EIO;
1690 0 : tevent_req_error(req, tlss->error);
1691 0 : return;
1692 : }
1693 :
1694 1219 : if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
1695 579 : tlss->waiting_flush.mgmt_req = req;
1696 579 : return;
1697 : }
1698 :
1699 640 : tevent_req_done(req);
1700 : }
1701 :
1702 641 : int tstream_tls_accept_recv(struct tevent_req *req,
1703 : int *perrno,
1704 : TALLOC_CTX *mem_ctx,
1705 : struct tstream_context **tls_stream)
1706 : {
1707 0 : struct tstream_tls_accept_state *state =
1708 641 : tevent_req_data(req,
1709 : struct tstream_tls_accept_state);
1710 :
1711 641 : if (tevent_req_is_unix_error(req, perrno)) {
1712 1 : tevent_req_received(req);
1713 1 : return -1;
1714 : }
1715 :
1716 640 : *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1717 640 : tevent_req_received(req);
1718 640 : return 0;
1719 : }
1720 :
1721 : struct tstream_tls_sync {
1722 : struct tstream_tls *tlss;
1723 : void *io_private;
1724 : ssize_t (*io_send_fn)(void *io_private,
1725 : const uint8_t *buf,
1726 : size_t len);
1727 : ssize_t (*io_recv_fn)(void *io_private,
1728 : uint8_t *buf,
1729 : size_t len);
1730 : };
1731 :
1732 48 : const DATA_BLOB *tstream_tls_sync_channel_bindings(struct tstream_tls_sync *tlsss)
1733 : {
1734 48 : return &tlsss->tlss->channel_bindings;
1735 : }
1736 :
1737 224 : static ssize_t tstream_tls_sync_push_function(gnutls_transport_ptr_t ptr,
1738 : const void *buf, size_t size)
1739 : {
1740 0 : struct tstream_tls_sync *tlsss =
1741 224 : talloc_get_type_abort(ptr,
1742 : struct tstream_tls_sync);
1743 :
1744 224 : return tlsss->io_send_fn(tlsss->io_private, buf, size);
1745 : }
1746 :
1747 504 : static ssize_t tstream_tls_sync_pull_function(gnutls_transport_ptr_t ptr,
1748 : void *buf, size_t size)
1749 : {
1750 0 : struct tstream_tls_sync *tlsss =
1751 504 : talloc_get_type_abort(ptr,
1752 : struct tstream_tls_sync);
1753 :
1754 504 : return tlsss->io_recv_fn(tlsss->io_private, buf, size);
1755 : }
1756 :
1757 240 : ssize_t tstream_tls_sync_read(struct tstream_tls_sync *tlsss,
1758 : void *buf, size_t len)
1759 : {
1760 0 : int ret;
1761 :
1762 240 : ret = gnutls_record_recv(tlsss->tlss->tls_session, buf, len);
1763 240 : if (ret == GNUTLS_E_INTERRUPTED) {
1764 0 : errno = EINTR;
1765 0 : return -1;
1766 : }
1767 240 : if (ret == GNUTLS_E_AGAIN) {
1768 0 : errno = EAGAIN;
1769 0 : return -1;
1770 : }
1771 :
1772 240 : if (ret < 0) {
1773 0 : DBG_WARNING("TLS gnutls_record_recv(%zu) - %s\n",
1774 : (size_t)len, gnutls_strerror(ret));
1775 0 : errno = EIO;
1776 0 : return -1;
1777 : }
1778 :
1779 240 : return ret;
1780 : }
1781 :
1782 96 : ssize_t tstream_tls_sync_write(struct tstream_tls_sync *tlsss,
1783 : const void *buf, size_t len)
1784 : {
1785 0 : int ret;
1786 :
1787 96 : ret = gnutls_record_send(tlsss->tlss->tls_session, buf, len);
1788 96 : if (ret == GNUTLS_E_INTERRUPTED) {
1789 0 : errno = EINTR;
1790 0 : return -1;
1791 : }
1792 96 : if (ret == GNUTLS_E_AGAIN) {
1793 0 : errno = EAGAIN;
1794 0 : return -1;
1795 : }
1796 :
1797 96 : if (ret < 0) {
1798 0 : DBG_WARNING("TLS gnutls_record_send(%zu) - %s\n",
1799 : (size_t)len, gnutls_strerror(ret));
1800 0 : errno = EIO;
1801 0 : return -1;
1802 : }
1803 :
1804 96 : return ret;
1805 : }
1806 :
1807 192 : size_t tstream_tls_sync_pending(struct tstream_tls_sync *tlsss)
1808 : {
1809 192 : return gnutls_record_check_pending(tlsss->tlss->tls_session);
1810 : }
1811 :
1812 24 : NTSTATUS tstream_tls_sync_setup(struct tstream_tls_params *_tls_params,
1813 : void *io_private,
1814 : ssize_t (*io_send_fn)(void *io_private,
1815 : const uint8_t *buf,
1816 : size_t len),
1817 : ssize_t (*io_recv_fn)(void *io_private,
1818 : uint8_t *buf,
1819 : size_t len),
1820 : TALLOC_CTX *mem_ctx,
1821 : struct tstream_tls_sync **_tlsss)
1822 : {
1823 24 : struct tstream_tls_sync *tlsss = NULL;
1824 24 : struct tstream_tls *tlss = NULL;
1825 0 : NTSTATUS status;
1826 0 : int ret;
1827 :
1828 24 : tlsss = talloc_zero(mem_ctx, struct tstream_tls_sync);
1829 24 : if (tlsss == NULL) {
1830 0 : return NT_STATUS_NO_MEMORY;
1831 : }
1832 :
1833 24 : tlsss->io_private = io_private;
1834 24 : tlsss->io_send_fn = io_send_fn;
1835 24 : tlsss->io_recv_fn = io_recv_fn;
1836 :
1837 24 : tlss = talloc_zero(tlsss, struct tstream_tls);
1838 24 : if (tlss == NULL) {
1839 0 : TALLOC_FREE(tlsss);
1840 0 : return NT_STATUS_NO_MEMORY;
1841 : }
1842 24 : talloc_set_destructor(tlss, tstream_tls_destructor);
1843 24 : tlss->is_server = false;
1844 :
1845 24 : tlsss->tlss = tlss;
1846 :
1847 24 : status = tstream_tls_prepare_gnutls(_tls_params, tlss);
1848 24 : if (!NT_STATUS_IS_OK(status)) {
1849 0 : TALLOC_FREE(tlsss);
1850 0 : return status;
1851 : }
1852 :
1853 24 : gnutls_transport_set_ptr(tlss->tls_session,
1854 : (gnutls_transport_ptr_t)tlsss);
1855 24 : gnutls_transport_set_pull_function(tlss->tls_session,
1856 : (gnutls_pull_func)tstream_tls_sync_pull_function);
1857 24 : gnutls_transport_set_push_function(tlss->tls_session,
1858 : (gnutls_push_func)tstream_tls_sync_push_function);
1859 :
1860 0 : do {
1861 : /*
1862 : * The caller should have the socket blocking
1863 : * and do the timeout handling in the
1864 : * io_send/recv_fn
1865 : */
1866 24 : ret = gnutls_handshake(tlss->tls_session);
1867 24 : } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
1868 :
1869 24 : if (gnutls_error_is_fatal(ret) != 0) {
1870 0 : TALLOC_FREE(tlsss);
1871 0 : return gnutls_error_to_ntstatus(ret,
1872 : NT_STATUS_CRYPTO_SYSTEM_INVALID);
1873 : }
1874 :
1875 24 : if (ret != GNUTLS_E_SUCCESS) {
1876 0 : TALLOC_FREE(tlsss);
1877 0 : return gnutls_error_to_ntstatus(ret,
1878 : NT_STATUS_CRYPTO_SYSTEM_INVALID);
1879 : }
1880 :
1881 24 : status = tstream_tls_verify_peer(tlss);
1882 24 : if (!NT_STATUS_IS_OK(status)) {
1883 0 : TALLOC_FREE(tlsss);
1884 0 : return status;
1885 : }
1886 :
1887 24 : status = tstream_tls_setup_channel_bindings(tlss);
1888 24 : if (!NT_STATUS_IS_OK(status)) {
1889 0 : TALLOC_FREE(tlsss);
1890 0 : return status;
1891 : }
1892 :
1893 24 : *_tlsss = tlsss;
1894 24 : return NT_STATUS_OK;
1895 : }
|