ctdb-scripts: Move connection tracking to 10.interface
[samba4-gss.git] / source4 / lib / tls / tls_tstream.c
blob081bddfe21b49a7da0619d0c6e9b1cf73b5458df
1 /*
2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2010
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.
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.
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/>.
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"
32 #include <gnutls/gnutls.h>
33 #include <gnutls/x509.h>
34 #include "lib/crypto/gnutls_helpers.h"
36 #define DH_BITS 2048
38 const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer)
40 switch (verify_peer) {
41 case TLS_VERIFY_PEER_NO_CHECK:
42 return TLS_VERIFY_PEER_NO_CHECK_STRING;
44 case TLS_VERIFY_PEER_CA_ONLY:
45 return TLS_VERIFY_PEER_CA_ONLY_STRING;
47 case TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE:
48 return TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING;
50 case TLS_VERIFY_PEER_CA_AND_NAME:
51 return TLS_VERIFY_PEER_CA_AND_NAME_STRING;
53 case TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE:
54 return TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING;
57 return "unknown tls_verify_peer_state";
60 static const struct tstream_context_ops tstream_tls_ops;
62 struct tstream_tls {
63 struct tstream_context *plain_stream;
64 int error;
66 gnutls_session_t tls_session;
68 bool is_server;
70 enum tls_verify_peer_state verify_peer;
71 const char *peer_name;
73 DATA_BLOB channel_bindings;
75 struct tevent_context *current_ev;
77 struct tevent_immediate *retry_im;
79 struct {
80 struct tevent_req *mgmt_req;
81 } waiting_flush;
83 struct {
84 uint8_t *buf;
85 off_t ofs;
86 struct iovec iov;
87 struct tevent_req *subreq;
88 } push;
90 struct {
91 uint8_t *buf;
92 struct iovec iov;
93 struct tevent_req *subreq;
94 } pull;
96 struct {
97 struct tevent_req *req;
98 } handshake;
100 struct {
101 off_t ofs;
102 size_t left;
103 uint8_t buffer[1024];
104 struct tevent_req *req;
105 } write;
107 struct {
108 off_t ofs;
109 size_t left;
110 uint8_t buffer[1024];
111 struct tevent_req *req;
112 } read;
114 struct {
115 struct tevent_req *req;
116 } disconnect;
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);
127 static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
130 struct tstream_tls *tlss =
131 tstream_context_data(stream,
132 struct tstream_tls);
134 if (tlss->push.subreq == NULL && tlss->pull.subreq == NULL) {
135 if (tlss->waiting_flush.mgmt_req != NULL) {
136 struct tevent_req *req = tlss->waiting_flush.mgmt_req;
138 tlss->waiting_flush.mgmt_req = NULL;
140 tevent_req_done(req);
141 return;
145 if (tlss->disconnect.req) {
146 tstream_tls_retry_disconnect(stream);
147 return;
150 if (tlss->handshake.req) {
151 tstream_tls_retry_handshake(stream);
152 return;
155 if (tlss->write.req && tlss->read.req && !deferred) {
156 tevent_schedule_immediate(tlss->retry_im, tlss->current_ev,
157 tstream_tls_retry_trigger,
158 stream);
161 if (tlss->write.req) {
162 tstream_tls_retry_write(stream);
163 return;
166 if (tlss->read.req) {
167 tstream_tls_retry_read(stream);
168 return;
172 static void tstream_tls_retry_trigger(struct tevent_context *ctx,
173 struct tevent_immediate *im,
174 void *private_data)
176 struct tstream_context *stream =
177 talloc_get_type_abort(private_data,
178 struct tstream_context);
180 tstream_tls_retry(stream, true);
183 static void tstream_tls_push_done(struct tevent_req *subreq);
185 static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
186 const void *buf, size_t size)
188 struct tstream_context *stream =
189 talloc_get_type_abort(ptr,
190 struct tstream_context);
191 struct tstream_tls *tlss =
192 tstream_context_data(stream,
193 struct tstream_tls);
194 struct tevent_req *subreq = NULL;
195 uint8_t *nbuf;
196 size_t len;
198 if (tlss->error != 0) {
199 errno = tlss->error;
200 return -1;
203 if (tlss->push.subreq) {
204 errno = EAGAIN;
205 return -1;
208 len = MIN(size, UINT16_MAX - tlss->push.ofs);
210 if (len == 0) {
211 errno = EAGAIN;
212 return -1;
215 nbuf = talloc_realloc(tlss, tlss->push.buf,
216 uint8_t, tlss->push.ofs + len);
217 if (nbuf == NULL) {
218 if (tlss->push.buf) {
219 errno = EAGAIN;
220 return -1;
223 return -1;
225 tlss->push.buf = nbuf;
227 memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
228 tlss->push.ofs += len;
230 tlss->push.iov.iov_base = (char *)tlss->push.buf;
231 tlss->push.iov.iov_len = tlss->push.ofs;
233 subreq = tstream_writev_send(tlss,
234 tlss->current_ev,
235 tlss->plain_stream,
236 &tlss->push.iov, 1);
237 if (subreq == NULL) {
238 errno = ENOMEM;
239 return -1;
241 tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
243 tlss->push.subreq = subreq;
244 return len;
247 static void tstream_tls_push_done(struct tevent_req *subreq)
249 struct tstream_context *stream =
250 tevent_req_callback_data(subreq,
251 struct tstream_context);
252 struct tstream_tls *tlss =
253 tstream_context_data(stream,
254 struct tstream_tls);
255 int ret;
256 int sys_errno;
258 tlss->push.subreq = NULL;
259 ZERO_STRUCT(tlss->push.iov);
260 TALLOC_FREE(tlss->push.buf);
261 tlss->push.ofs = 0;
263 ret = tstream_writev_recv(subreq, &sys_errno);
264 TALLOC_FREE(subreq);
265 if (ret == -1) {
266 tlss->error = sys_errno;
267 tstream_tls_retry(stream, false);
268 return;
271 tstream_tls_retry(stream, false);
274 static void tstream_tls_pull_done(struct tevent_req *subreq);
276 static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
277 void *buf, size_t size)
279 struct tstream_context *stream =
280 talloc_get_type_abort(ptr,
281 struct tstream_context);
282 struct tstream_tls *tlss =
283 tstream_context_data(stream,
284 struct tstream_tls);
285 struct tevent_req *subreq;
286 size_t len;
288 if (tlss->error != 0) {
289 errno = tlss->error;
290 return -1;
293 if (tlss->pull.subreq) {
294 errno = EAGAIN;
295 return -1;
298 if (tlss->pull.iov.iov_base) {
299 uint8_t *b;
300 size_t n;
302 b = (uint8_t *)tlss->pull.iov.iov_base;
304 n = MIN(tlss->pull.iov.iov_len, size);
305 memcpy(buf, b, n);
307 tlss->pull.iov.iov_len -= n;
308 b += n;
309 tlss->pull.iov.iov_base = (char *)b;
310 if (tlss->pull.iov.iov_len == 0) {
311 tlss->pull.iov.iov_base = NULL;
312 TALLOC_FREE(tlss->pull.buf);
315 return n;
318 if (size == 0) {
319 return 0;
322 len = MIN(size, UINT16_MAX);
324 tlss->pull.buf = talloc_array(tlss, uint8_t, len);
325 if (tlss->pull.buf == NULL) {
326 return -1;
329 tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
330 tlss->pull.iov.iov_len = len;
332 subreq = tstream_readv_send(tlss,
333 tlss->current_ev,
334 tlss->plain_stream,
335 &tlss->pull.iov, 1);
336 if (subreq == NULL) {
337 errno = ENOMEM;
338 return -1;
340 tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
342 tlss->pull.subreq = subreq;
343 errno = EAGAIN;
344 return -1;
347 static void tstream_tls_pull_done(struct tevent_req *subreq)
349 struct tstream_context *stream =
350 tevent_req_callback_data(subreq,
351 struct tstream_context);
352 struct tstream_tls *tlss =
353 tstream_context_data(stream,
354 struct tstream_tls);
355 int ret;
356 int sys_errno;
358 tlss->pull.subreq = NULL;
360 ret = tstream_readv_recv(subreq, &sys_errno);
361 TALLOC_FREE(subreq);
362 if (ret == -1) {
363 tlss->error = sys_errno;
364 tstream_tls_retry(stream, false);
365 return;
368 tstream_tls_retry(stream, false);
371 static int tstream_tls_destructor(struct tstream_tls *tlss)
373 if (tlss->tls_session) {
374 gnutls_deinit(tlss->tls_session);
375 tlss->tls_session = NULL;
378 return 0;
381 static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
383 struct tstream_tls *tlss =
384 tstream_context_data(stream,
385 struct tstream_tls);
386 size_t ret;
388 if (tlss->error != 0) {
389 errno = tlss->error;
390 return -1;
393 ret = gnutls_record_check_pending(tlss->tls_session);
394 ret += tlss->read.left;
396 return ret;
399 struct tstream_tls_readv_state {
400 struct tstream_context *stream;
402 struct iovec *vector;
403 int count;
405 int ret;
408 static void tstream_tls_readv_crypt_next(struct tevent_req *req);
410 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)
416 struct tstream_tls *tlss =
417 tstream_context_data(stream,
418 struct tstream_tls);
419 struct tevent_req *req;
420 struct tstream_tls_readv_state *state;
422 tlss->read.req = NULL;
424 if (tlss->current_ev != ev) {
425 SMB_ASSERT(tlss->push.subreq == NULL);
426 SMB_ASSERT(tlss->pull.subreq == NULL);
429 tlss->current_ev = ev;
431 req = tevent_req_create(mem_ctx, &state,
432 struct tstream_tls_readv_state);
433 if (req == NULL) {
434 return NULL;
437 state->stream = stream;
438 state->ret = 0;
440 if (tlss->error != 0) {
441 tevent_req_error(req, tlss->error);
442 return tevent_req_post(req, ev);
446 * we make a copy of the vector so we can change the structure
448 state->vector = talloc_array(state, struct iovec, count);
449 if (tevent_req_nomem(state->vector, req)) {
450 return tevent_req_post(req, ev);
452 memcpy(state->vector, vector, sizeof(struct iovec) * count);
453 state->count = count;
455 tstream_tls_readv_crypt_next(req);
456 if (!tevent_req_is_in_progress(req)) {
457 return tevent_req_post(req, ev);
460 return req;
463 static void tstream_tls_readv_crypt_next(struct tevent_req *req)
465 struct tstream_tls_readv_state *state =
466 tevent_req_data(req,
467 struct tstream_tls_readv_state);
468 struct tstream_tls *tlss =
469 tstream_context_data(state->stream,
470 struct tstream_tls);
473 * copy the pending buffer first
475 while (tlss->read.left > 0 && state->count > 0) {
476 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
477 size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
479 memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
481 base += len;
482 state->vector[0].iov_base = (char *) base;
483 state->vector[0].iov_len -= len;
485 tlss->read.ofs += len;
486 tlss->read.left -= len;
488 if (state->vector[0].iov_len == 0) {
489 state->vector += 1;
490 state->count -= 1;
493 state->ret += len;
496 if (state->count == 0) {
497 tevent_req_done(req);
498 return;
501 tlss->read.req = req;
502 tstream_tls_retry_read(state->stream);
505 static void tstream_tls_retry_read(struct tstream_context *stream)
507 struct tstream_tls *tlss =
508 tstream_context_data(stream,
509 struct tstream_tls);
510 struct tevent_req *req = tlss->read.req;
511 int ret;
513 if (tlss->error != 0) {
514 tevent_req_error(req, tlss->error);
515 return;
518 tlss->read.left = 0;
519 tlss->read.ofs = 0;
521 ret = gnutls_record_recv(tlss->tls_session,
522 tlss->read.buffer,
523 sizeof(tlss->read.buffer));
524 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
525 return;
528 tlss->read.req = NULL;
530 if (gnutls_error_is_fatal(ret) != 0) {
531 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
532 tlss->error = EIO;
533 tevent_req_error(req, tlss->error);
534 return;
537 if (ret == 0) {
538 tlss->error = EPIPE;
539 tevent_req_error(req, tlss->error);
540 return;
543 tlss->read.left = ret;
544 tstream_tls_readv_crypt_next(req);
547 static int tstream_tls_readv_recv(struct tevent_req *req,
548 int *perrno)
550 struct tstream_tls_readv_state *state =
551 tevent_req_data(req,
552 struct tstream_tls_readv_state);
553 struct tstream_tls *tlss =
554 tstream_context_data(state->stream,
555 struct tstream_tls);
556 int ret;
558 tlss->read.req = NULL;
560 ret = tsocket_simple_int_recv(req, perrno);
561 if (ret == 0) {
562 ret = state->ret;
565 tevent_req_received(req);
566 return ret;
569 struct tstream_tls_writev_state {
570 struct tstream_context *stream;
572 struct iovec *vector;
573 int count;
575 int ret;
578 static void tstream_tls_writev_crypt_next(struct tevent_req *req);
580 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)
586 struct tstream_tls *tlss =
587 tstream_context_data(stream,
588 struct tstream_tls);
589 struct tevent_req *req;
590 struct tstream_tls_writev_state *state;
592 tlss->write.req = NULL;
594 if (tlss->current_ev != ev) {
595 SMB_ASSERT(tlss->push.subreq == NULL);
596 SMB_ASSERT(tlss->pull.subreq == NULL);
599 tlss->current_ev = ev;
601 req = tevent_req_create(mem_ctx, &state,
602 struct tstream_tls_writev_state);
603 if (req == NULL) {
604 return NULL;
607 state->stream = stream;
608 state->ret = 0;
610 if (tlss->error != 0) {
611 tevent_req_error(req, tlss->error);
612 return tevent_req_post(req, ev);
616 * we make a copy of the vector so we can change the structure
618 state->vector = talloc_array(state, struct iovec, count);
619 if (tevent_req_nomem(state->vector, req)) {
620 return tevent_req_post(req, ev);
622 memcpy(state->vector, vector, sizeof(struct iovec) * count);
623 state->count = count;
625 tstream_tls_writev_crypt_next(req);
626 if (!tevent_req_is_in_progress(req)) {
627 return tevent_req_post(req, ev);
630 return req;
633 static void tstream_tls_writev_crypt_next(struct tevent_req *req)
635 struct tstream_tls_writev_state *state =
636 tevent_req_data(req,
637 struct tstream_tls_writev_state);
638 struct tstream_tls *tlss =
639 tstream_context_data(state->stream,
640 struct tstream_tls);
642 tlss->write.left = sizeof(tlss->write.buffer);
643 tlss->write.ofs = 0;
646 * first fill our buffer
648 while (tlss->write.left > 0 && state->count > 0) {
649 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
650 size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
652 memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
654 base += len;
655 state->vector[0].iov_base = (char *) base;
656 state->vector[0].iov_len -= len;
658 tlss->write.ofs += len;
659 tlss->write.left -= len;
661 if (state->vector[0].iov_len == 0) {
662 state->vector += 1;
663 state->count -= 1;
666 state->ret += len;
669 if (tlss->write.ofs == 0) {
670 tevent_req_done(req);
671 return;
674 tlss->write.left = tlss->write.ofs;
675 tlss->write.ofs = 0;
677 tlss->write.req = req;
678 tstream_tls_retry_write(state->stream);
681 static void tstream_tls_retry_write(struct tstream_context *stream)
683 struct tstream_tls *tlss =
684 tstream_context_data(stream,
685 struct tstream_tls);
686 struct tevent_req *req = tlss->write.req;
687 int ret;
689 if (tlss->error != 0) {
690 tevent_req_error(req, tlss->error);
691 return;
694 ret = gnutls_record_send(tlss->tls_session,
695 tlss->write.buffer + tlss->write.ofs,
696 tlss->write.left);
697 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
698 return;
701 tlss->write.req = NULL;
703 if (gnutls_error_is_fatal(ret) != 0) {
704 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
705 tlss->error = EIO;
706 tevent_req_error(req, tlss->error);
707 return;
710 if (ret == 0) {
711 tlss->error = EPIPE;
712 tevent_req_error(req, tlss->error);
713 return;
716 tlss->write.ofs += ret;
717 tlss->write.left -= ret;
719 if (tlss->write.left > 0) {
720 tlss->write.req = req;
721 tstream_tls_retry_write(stream);
722 return;
725 tstream_tls_writev_crypt_next(req);
728 static int tstream_tls_writev_recv(struct tevent_req *req,
729 int *perrno)
731 struct tstream_tls_writev_state *state =
732 tevent_req_data(req,
733 struct tstream_tls_writev_state);
734 struct tstream_tls *tlss =
735 tstream_context_data(state->stream,
736 struct tstream_tls);
737 int ret;
739 tlss->write.req = NULL;
741 ret = tsocket_simple_int_recv(req, perrno);
742 if (ret == 0) {
743 ret = state->ret;
746 tevent_req_received(req);
747 return ret;
750 struct tstream_tls_disconnect_state {
751 uint8_t _dummy;
754 static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
755 struct tevent_context *ev,
756 struct tstream_context *stream)
758 struct tstream_tls *tlss =
759 tstream_context_data(stream,
760 struct tstream_tls);
761 struct tevent_req *req;
762 struct tstream_tls_disconnect_state *state;
764 tlss->disconnect.req = NULL;
766 if (tlss->current_ev != ev) {
767 SMB_ASSERT(tlss->push.subreq == NULL);
768 SMB_ASSERT(tlss->pull.subreq == NULL);
771 tlss->current_ev = ev;
773 req = tevent_req_create(mem_ctx, &state,
774 struct tstream_tls_disconnect_state);
775 if (req == NULL) {
776 return NULL;
779 if (tlss->error != 0) {
780 tevent_req_error(req, tlss->error);
781 return tevent_req_post(req, ev);
784 tlss->disconnect.req = req;
785 tstream_tls_retry_disconnect(stream);
786 if (!tevent_req_is_in_progress(req)) {
787 return tevent_req_post(req, ev);
790 return req;
793 static void tstream_tls_retry_disconnect(struct tstream_context *stream)
795 struct tstream_tls *tlss =
796 tstream_context_data(stream,
797 struct tstream_tls);
798 struct tevent_req *req = tlss->disconnect.req;
799 int ret;
801 if (tlss->error != 0) {
802 tevent_req_error(req, tlss->error);
803 return;
806 ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
807 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
808 return;
811 tlss->disconnect.req = NULL;
813 if (gnutls_error_is_fatal(ret) != 0) {
814 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
815 tlss->error = EIO;
816 tevent_req_error(req, tlss->error);
817 return;
820 if (ret != GNUTLS_E_SUCCESS) {
821 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
822 tlss->error = EIO;
823 tevent_req_error(req, tlss->error);
824 return;
827 if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
828 tlss->waiting_flush.mgmt_req = req;
829 return;
832 tevent_req_done(req);
835 static int tstream_tls_disconnect_recv(struct tevent_req *req,
836 int *perrno)
838 int ret;
840 ret = tsocket_simple_int_recv(req, perrno);
842 tevent_req_received(req);
843 return ret;
846 static const struct tstream_context_ops tstream_tls_ops = {
847 .name = "tls",
849 .pending_bytes = tstream_tls_pending_bytes,
851 .readv_send = tstream_tls_readv_send,
852 .readv_recv = tstream_tls_readv_recv,
854 .writev_send = tstream_tls_writev_send,
855 .writev_recv = tstream_tls_writev_recv,
857 .disconnect_send = tstream_tls_disconnect_send,
858 .disconnect_recv = tstream_tls_disconnect_recv,
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;
870 struct tstream_tls_params {
871 struct tstream_tls_params_internal *internal;
874 static int tstream_tls_params_internal_destructor(struct tstream_tls_params_internal *tlsp)
876 if (tlsp->x509_cred) {
877 gnutls_certificate_free_credentials(tlsp->x509_cred);
878 tlsp->x509_cred = NULL;
880 if (tlsp->dh_params) {
881 gnutls_dh_params_deinit(tlsp->dh_params);
882 tlsp->dh_params = NULL;
885 return 0;
888 bool tstream_tls_params_enabled(struct tstream_tls_params *tls_params)
890 struct tstream_tls_params_internal *tlsp = tls_params->internal;
892 return tlsp->tls_enabled;
895 static NTSTATUS tstream_tls_setup_channel_bindings(struct tstream_tls *tlss)
897 gnutls_datum_t cb = { .size = 0 };
898 int ret;
900 #ifdef HAVE_GNUTLS_CB_TLS_SERVER_END_POINT
901 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 if (ret != GNUTLS_E_SUCCESS) {
910 return gnutls_error_to_ntstatus(ret,
911 NT_STATUS_CRYPTO_SYSTEM_INVALID);
914 if (cb.size != 0) {
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:'
921 const char endpoint_prefix[] = "tls-server-end-point:";
922 size_t prefix_size = strlen(endpoint_prefix);
923 size_t size = prefix_size + cb.size;
925 tlss->channel_bindings = data_blob_talloc_named(tlss, NULL, size,
926 "tls_channel_bindings");
927 if (tlss->channel_bindings.data == NULL) {
928 gnutls_free(cb.data);
929 return NT_STATUS_NO_MEMORY;
931 memcpy(tlss->channel_bindings.data, endpoint_prefix, prefix_size);
932 memcpy(tlss->channel_bindings.data + prefix_size, cb.data, cb.size);
933 gnutls_free(cb.data);
936 return NT_STATUS_OK;
939 const DATA_BLOB *tstream_tls_channel_bindings(struct tstream_context *tls_tstream)
941 struct tstream_tls *tlss =
942 talloc_get_type(_tstream_context_data(tls_tstream),
943 struct tstream_tls);
945 if (tlss == NULL) {
946 return NULL;
949 return &tlss->channel_bindings;
952 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)
962 struct tstream_tls_params *__tlsp = NULL;
963 struct tstream_tls_params_internal *tlsp = NULL;
964 bool got_ca = false;
965 size_t i;
966 int ret;
968 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
969 if (__tlsp == NULL) {
970 return NT_STATUS_NO_MEMORY;
973 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
974 if (tlsp == NULL) {
975 TALLOC_FREE(__tlsp);
976 return NT_STATUS_NO_MEMORY;
978 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
979 __tlsp->internal = tlsp;
981 tlsp->verify_peer = verify_peer;
982 if (peer_name != NULL) {
983 tlsp->peer_name = talloc_strdup(tlsp, peer_name);
984 if (tlsp->peer_name == NULL) {
985 TALLOC_FREE(__tlsp);
986 return NT_STATUS_NO_MEMORY;
988 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
989 DEBUG(0,("TLS failed to missing peer_name - "
990 "with 'tls verify peer = %s'\n",
991 tls_verify_peer_string(tlsp->verify_peer)));
992 TALLOC_FREE(__tlsp);
993 return NT_STATUS_INVALID_PARAMETER_MIX;
996 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
997 if (ret != GNUTLS_E_SUCCESS) {
998 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
999 TALLOC_FREE(__tlsp);
1000 return NT_STATUS_NO_MEMORY;
1003 if (system_cas) {
1004 ret = gnutls_certificate_set_x509_system_trust(tlsp->x509_cred);
1005 if (ret < 0) {
1006 DBG_ERR("gnutls_certificate_set_x509_system_trust() - %s\n",
1007 gnutls_strerror(ret));
1008 TALLOC_FREE(__tlsp);
1009 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1011 if (ret > 0) {
1012 got_ca = true;
1016 for (i = 0; ca_dirs != NULL && ca_dirs[i] != NULL; i++) {
1017 const char *ca_dir = ca_dirs[i];
1019 if (!directory_exist(ca_dir)) {
1020 continue;
1023 ret = gnutls_certificate_set_x509_trust_dir(tlsp->x509_cred,
1024 ca_dir,
1025 GNUTLS_X509_FMT_PEM);
1026 if (ret < 0) {
1027 DBG_ERR("gnutls_certificate_set_x509_trust_dir(%s) - %s\n",
1028 ca_dir, gnutls_strerror(ret));
1029 TALLOC_FREE(__tlsp);
1030 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1032 if (ret > 0) {
1033 got_ca = true;
1037 if (ca_file && *ca_file && file_exist(ca_file)) {
1038 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1039 ca_file,
1040 GNUTLS_X509_FMT_PEM);
1041 if (ret < 0) {
1042 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1043 ca_file, gnutls_strerror(ret)));
1044 TALLOC_FREE(__tlsp);
1045 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1047 if (ret > 0) {
1048 got_ca = true;
1052 if (!got_ca && tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
1053 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 TALLOC_FREE(__tlsp);
1059 return NT_STATUS_INVALID_PARAMETER_MIX;
1062 if (crl_file && *crl_file && file_exist(crl_file)) {
1063 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1064 crl_file,
1065 GNUTLS_X509_FMT_PEM);
1066 if (ret < 0) {
1067 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1068 crl_file, gnutls_strerror(ret)));
1069 TALLOC_FREE(__tlsp);
1070 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1072 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE) {
1073 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 TALLOC_FREE(__tlsp);
1078 return NT_STATUS_INVALID_PARAMETER_MIX;
1081 tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
1082 if (tlsp->tls_priority == NULL) {
1083 TALLOC_FREE(__tlsp);
1084 return NT_STATUS_NO_MEMORY;
1087 tlsp->tls_enabled = true;
1089 *_tlsp = __tlsp;
1090 return NT_STATUS_OK;
1093 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)
1098 TALLOC_CTX *frame = talloc_stackframe();
1099 bool system_cas = false;
1100 const char * const *ca_dirs = NULL;
1101 const char *ptr = NULL;
1102 char *ca_file = NULL;
1103 char *crl_file = NULL;
1104 const char *tls_priority = NULL;
1105 enum tls_verify_peer_state verify_peer =
1106 TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE;
1107 NTSTATUS status;
1109 system_cas = lpcfg_tls_trust_system_cas(lp_ctx);
1110 ca_dirs = lpcfg_tls_ca_directories(lp_ctx);
1112 ptr = lpcfg__tls_cafile(lp_ctx);
1113 if (ptr != NULL) {
1114 ca_file = lpcfg_tls_cafile(frame, lp_ctx);
1115 if (ca_file == NULL) {
1116 TALLOC_FREE(frame);
1117 return NT_STATUS_NO_MEMORY;
1121 ptr = lpcfg__tls_crlfile(lp_ctx);
1122 if (ptr != NULL) {
1123 crl_file = lpcfg_tls_crlfile(frame, lp_ctx);
1124 if (crl_file == NULL) {
1125 TALLOC_FREE(frame);
1126 return NT_STATUS_NO_MEMORY;
1130 tls_priority = lpcfg_tls_priority(lp_ctx);
1131 verify_peer = lpcfg_tls_verify_peer(lp_ctx);
1133 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 TALLOC_FREE(frame);
1143 return status;
1146 static NTSTATUS tstream_tls_prepare_gnutls(struct tstream_tls_params *_tlsp,
1147 struct tstream_tls *tlss)
1149 struct tstream_tls_params_internal *tlsp = NULL;
1150 int ret;
1151 unsigned int flags;
1152 const char *hostname = NULL;
1154 if (tlss->is_server) {
1155 flags = GNUTLS_SERVER;
1156 } else {
1157 flags = GNUTLS_CLIENT;
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.
1165 flags |= GNUTLS_NO_TICKETS;
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!
1173 * See 'man gnutls_credentials_set' and
1174 * 'man gnutls_certificate_set_dh_params'.
1176 * Note: here we use talloc_reference() in a way
1177 * that does not expose it to the caller.
1179 tlsp = talloc_reference(tlss, _tlsp->internal);
1180 if (tlsp == NULL) {
1181 return NT_STATUS_NO_MEMORY;
1184 tlss->verify_peer = tlsp->verify_peer;
1185 if (tlsp->peer_name != NULL) {
1186 bool ip = is_ipaddress(tlsp->peer_name);
1188 tlss->peer_name = talloc_strdup(tlss, tlsp->peer_name);
1189 if (tlss->peer_name == NULL) {
1190 return NT_STATUS_NO_MEMORY;
1193 if (!ip) {
1194 hostname = tlss->peer_name;
1197 if (tlss->verify_peer < TLS_VERIFY_PEER_CA_AND_NAME) {
1198 hostname = NULL;
1202 if (tlss->current_ev != NULL) {
1203 tlss->retry_im = tevent_create_immediate(tlss);
1204 if (tlss->retry_im == NULL) {
1205 return NT_STATUS_NO_MEMORY;
1209 ret = gnutls_init(&tlss->tls_session, flags);
1210 if (ret != GNUTLS_E_SUCCESS) {
1211 return gnutls_error_to_ntstatus(ret,
1212 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1215 ret = gnutls_set_default_priority(tlss->tls_session);
1216 if (ret != GNUTLS_E_SUCCESS) {
1217 return gnutls_error_to_ntstatus(ret,
1218 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1221 if (strlen(tlsp->tls_priority) > 0) {
1222 const char *error_pos = NULL;
1224 ret = gnutls_priority_set_direct(tlss->tls_session,
1225 tlsp->tls_priority,
1226 &error_pos);
1227 if (ret != GNUTLS_E_SUCCESS) {
1228 return gnutls_error_to_ntstatus(ret,
1229 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1233 ret = gnutls_credentials_set(tlss->tls_session,
1234 GNUTLS_CRD_CERTIFICATE,
1235 tlsp->x509_cred);
1236 if (ret != GNUTLS_E_SUCCESS) {
1237 return gnutls_error_to_ntstatus(ret,
1238 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1241 if (hostname != NULL) {
1242 ret = gnutls_server_name_set(tlss->tls_session,
1243 GNUTLS_NAME_DNS,
1244 hostname,
1245 strlen(hostname));
1246 if (ret != GNUTLS_E_SUCCESS) {
1247 return gnutls_error_to_ntstatus(ret,
1248 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1252 if (tlss->is_server) {
1253 gnutls_certificate_server_set_request(tlss->tls_session,
1254 GNUTLS_CERT_REQUEST);
1255 gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
1258 return NT_STATUS_OK;
1261 static NTSTATUS tstream_tls_verify_peer(struct tstream_tls *tlss)
1263 unsigned int status = UINT32_MAX;
1264 bool ip = true;
1265 const char *hostname = NULL;
1266 int ret;
1268 if (tlss->verify_peer == TLS_VERIFY_PEER_NO_CHECK) {
1269 return NT_STATUS_OK;
1272 if (tlss->peer_name != NULL) {
1273 ip = is_ipaddress(tlss->peer_name);
1276 if (!ip) {
1277 hostname = tlss->peer_name;
1280 if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
1281 hostname = NULL;
1284 if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
1285 if (hostname == NULL) {
1286 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 return NT_STATUS_IMAGE_CERT_REVOKED;
1295 ret = gnutls_certificate_verify_peers3(tlss->tls_session,
1296 hostname,
1297 &status);
1298 if (ret != GNUTLS_E_SUCCESS) {
1299 return gnutls_error_to_ntstatus(ret,
1300 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1303 if (status != 0) {
1304 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 return NT_STATUS_IMAGE_CERT_REVOKED;
1328 return NT_STATUS_OK;
1331 struct tstream_tls_connect_state {
1332 struct tstream_context *tls_stream;
1335 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)
1341 struct tevent_req *req;
1342 struct tstream_tls_connect_state *state;
1343 struct tstream_tls *tlss;
1344 NTSTATUS status;
1346 req = tevent_req_create(mem_ctx, &state,
1347 struct tstream_tls_connect_state);
1348 if (req == NULL) {
1349 return NULL;
1352 state->tls_stream = tstream_context_create(state,
1353 &tstream_tls_ops,
1354 &tlss,
1355 struct tstream_tls,
1356 location);
1357 if (tevent_req_nomem(state->tls_stream, req)) {
1358 return tevent_req_post(req, ev);
1360 ZERO_STRUCTP(tlss);
1361 talloc_set_destructor(tlss, tstream_tls_destructor);
1362 tlss->plain_stream = plain_stream;
1363 tlss->is_server = false;
1364 tlss->current_ev = ev;
1366 status = tstream_tls_prepare_gnutls(_tls_params, tlss);
1367 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1368 tevent_req_oom(req);
1369 return tevent_req_post(req, ev);
1371 if (!NT_STATUS_IS_OK(status)) {
1372 tevent_req_error(req, EINVAL);
1373 return tevent_req_post(req, ev);
1376 gnutls_transport_set_ptr(tlss->tls_session,
1377 (gnutls_transport_ptr_t)state->tls_stream);
1378 gnutls_transport_set_pull_function(tlss->tls_session,
1379 (gnutls_pull_func)tstream_tls_pull_function);
1380 gnutls_transport_set_push_function(tlss->tls_session,
1381 (gnutls_push_func)tstream_tls_push_function);
1383 tlss->handshake.req = req;
1384 tstream_tls_retry_handshake(state->tls_stream);
1385 if (!tevent_req_is_in_progress(req)) {
1386 return tevent_req_post(req, ev);
1389 return req;
1392 int tstream_tls_connect_recv(struct tevent_req *req,
1393 int *perrno,
1394 TALLOC_CTX *mem_ctx,
1395 struct tstream_context **tls_stream)
1397 struct tstream_tls_connect_state *state =
1398 tevent_req_data(req,
1399 struct tstream_tls_connect_state);
1401 if (tevent_req_is_unix_error(req, perrno)) {
1402 tevent_req_received(req);
1403 return -1;
1406 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1407 tevent_req_received(req);
1408 return 0;
1412 initialise global tls state
1414 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)
1425 struct tstream_tls_params *__tlsp = NULL;
1426 struct tstream_tls_params_internal *tlsp = NULL;
1427 int ret;
1428 struct stat st;
1430 if (!enabled || key_file == NULL || *key_file == 0) {
1431 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1432 if (__tlsp == NULL) {
1433 return NT_STATUS_NO_MEMORY;
1436 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1437 if (tlsp == NULL) {
1438 TALLOC_FREE(__tlsp);
1439 return NT_STATUS_NO_MEMORY;
1442 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1443 __tlsp->internal = tlsp;
1444 tlsp->tls_enabled = false;
1446 *_tlsp = __tlsp;
1447 return NT_STATUS_OK;
1450 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1451 if (__tlsp == NULL) {
1452 return NT_STATUS_NO_MEMORY;
1455 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1456 if (tlsp == NULL) {
1457 TALLOC_FREE(__tlsp);
1458 return NT_STATUS_NO_MEMORY;
1461 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1462 __tlsp->internal = tlsp;
1464 if (!file_exist(ca_file)) {
1465 tls_cert_generate(tlsp, dns_host_name,
1466 key_file, cert_file, ca_file);
1469 if (file_exist(key_file) &&
1470 !file_check_permissions(key_file, geteuid(), 0600, &st))
1472 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 TALLOC_FREE(__tlsp);
1481 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1484 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
1485 if (ret != GNUTLS_E_SUCCESS) {
1486 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1487 TALLOC_FREE(__tlsp);
1488 return NT_STATUS_NO_MEMORY;
1491 if (ca_file && *ca_file) {
1492 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1493 ca_file,
1494 GNUTLS_X509_FMT_PEM);
1495 if (ret < 0) {
1496 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1497 ca_file, gnutls_strerror(ret)));
1498 TALLOC_FREE(__tlsp);
1499 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1503 if (crl_file && *crl_file) {
1504 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1505 crl_file,
1506 GNUTLS_X509_FMT_PEM);
1507 if (ret < 0) {
1508 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1509 crl_file, gnutls_strerror(ret)));
1510 TALLOC_FREE(__tlsp);
1511 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1515 ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
1516 cert_file, key_file,
1517 GNUTLS_X509_FMT_PEM);
1518 if (ret != GNUTLS_E_SUCCESS) {
1519 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1520 cert_file, key_file, gnutls_strerror(ret)));
1521 TALLOC_FREE(__tlsp);
1522 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1525 ret = gnutls_dh_params_init(&tlsp->dh_params);
1526 if (ret != GNUTLS_E_SUCCESS) {
1527 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1528 TALLOC_FREE(__tlsp);
1529 return NT_STATUS_NO_MEMORY;
1532 if (dhp_file && *dhp_file) {
1533 gnutls_datum_t dhparms;
1534 size_t size;
1536 dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
1538 if (!dhparms.data) {
1539 DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1540 dhp_file, errno, strerror(errno)));
1541 TALLOC_FREE(__tlsp);
1542 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1544 dhparms.size = size;
1546 ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
1547 &dhparms,
1548 GNUTLS_X509_FMT_PEM);
1549 if (ret != GNUTLS_E_SUCCESS) {
1550 DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1551 dhp_file, gnutls_strerror(ret)));
1552 TALLOC_FREE(__tlsp);
1553 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1555 } else {
1556 ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
1557 if (ret != GNUTLS_E_SUCCESS) {
1558 DEBUG(0,("TLS failed to generate dh_params - %s\n",
1559 gnutls_strerror(ret)));
1560 TALLOC_FREE(__tlsp);
1561 return NT_STATUS_INTERNAL_ERROR;
1565 gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
1567 tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
1568 if (tlsp->tls_priority == NULL) {
1569 TALLOC_FREE(__tlsp);
1570 return NT_STATUS_NO_MEMORY;
1573 tlsp->tls_enabled = true;
1575 *_tlsp = __tlsp;
1576 return NT_STATUS_OK;
1579 struct tstream_tls_accept_state {
1580 struct tstream_context *tls_stream;
1583 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)
1589 struct tevent_req *req;
1590 struct tstream_tls_accept_state *state;
1591 struct tstream_tls *tlss;
1592 NTSTATUS status;
1594 req = tevent_req_create(mem_ctx, &state,
1595 struct tstream_tls_accept_state);
1596 if (req == NULL) {
1597 return NULL;
1600 state->tls_stream = tstream_context_create(state,
1601 &tstream_tls_ops,
1602 &tlss,
1603 struct tstream_tls,
1604 location);
1605 if (tevent_req_nomem(state->tls_stream, req)) {
1606 return tevent_req_post(req, ev);
1608 ZERO_STRUCTP(tlss);
1609 talloc_set_destructor(tlss, tstream_tls_destructor);
1610 tlss->plain_stream = plain_stream;
1611 tlss->is_server = true;
1612 tlss->current_ev = ev;
1614 status = tstream_tls_prepare_gnutls(_tlsp, tlss);
1615 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1616 tevent_req_oom(req);
1617 return tevent_req_post(req, ev);
1619 if (!NT_STATUS_IS_OK(status)) {
1620 tevent_req_error(req, EINVAL);
1621 return tevent_req_post(req, ev);
1624 gnutls_transport_set_ptr(tlss->tls_session,
1625 (gnutls_transport_ptr_t)state->tls_stream);
1626 gnutls_transport_set_pull_function(tlss->tls_session,
1627 (gnutls_pull_func)tstream_tls_pull_function);
1628 gnutls_transport_set_push_function(tlss->tls_session,
1629 (gnutls_push_func)tstream_tls_push_function);
1631 tlss->handshake.req = req;
1632 tstream_tls_retry_handshake(state->tls_stream);
1633 if (!tevent_req_is_in_progress(req)) {
1634 return tevent_req_post(req, ev);
1637 return req;
1640 static void tstream_tls_retry_handshake(struct tstream_context *stream)
1642 struct tstream_tls *tlss =
1643 tstream_context_data(stream,
1644 struct tstream_tls);
1645 struct tevent_req *req = tlss->handshake.req;
1646 NTSTATUS status;
1647 int ret;
1649 if (tlss->error != 0) {
1650 tevent_req_error(req, tlss->error);
1651 return;
1654 ret = gnutls_handshake(tlss->tls_session);
1655 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
1656 return;
1659 tlss->handshake.req = NULL;
1661 if (gnutls_error_is_fatal(ret) != 0) {
1662 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1663 tlss->error = EIO;
1664 tevent_req_error(req, tlss->error);
1665 return;
1668 if (ret != GNUTLS_E_SUCCESS) {
1669 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1670 tlss->error = EIO;
1671 tevent_req_error(req, tlss->error);
1672 return;
1675 status = tstream_tls_verify_peer(tlss);
1676 if (NT_STATUS_EQUAL(status, NT_STATUS_IMAGE_CERT_REVOKED)) {
1677 tlss->error = EINVAL;
1678 tevent_req_error(req, tlss->error);
1679 return;
1681 if (!NT_STATUS_IS_OK(status)) {
1682 tlss->error = EIO;
1683 tevent_req_error(req, tlss->error);
1684 return;
1687 status = tstream_tls_setup_channel_bindings(tlss);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 tlss->error = EIO;
1690 tevent_req_error(req, tlss->error);
1691 return;
1694 if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
1695 tlss->waiting_flush.mgmt_req = req;
1696 return;
1699 tevent_req_done(req);
1702 int tstream_tls_accept_recv(struct tevent_req *req,
1703 int *perrno,
1704 TALLOC_CTX *mem_ctx,
1705 struct tstream_context **tls_stream)
1707 struct tstream_tls_accept_state *state =
1708 tevent_req_data(req,
1709 struct tstream_tls_accept_state);
1711 if (tevent_req_is_unix_error(req, perrno)) {
1712 tevent_req_received(req);
1713 return -1;
1716 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1717 tevent_req_received(req);
1718 return 0;
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);
1732 const DATA_BLOB *tstream_tls_sync_channel_bindings(struct tstream_tls_sync *tlsss)
1734 return &tlsss->tlss->channel_bindings;
1737 static ssize_t tstream_tls_sync_push_function(gnutls_transport_ptr_t ptr,
1738 const void *buf, size_t size)
1740 struct tstream_tls_sync *tlsss =
1741 talloc_get_type_abort(ptr,
1742 struct tstream_tls_sync);
1744 return tlsss->io_send_fn(tlsss->io_private, buf, size);
1747 static ssize_t tstream_tls_sync_pull_function(gnutls_transport_ptr_t ptr,
1748 void *buf, size_t size)
1750 struct tstream_tls_sync *tlsss =
1751 talloc_get_type_abort(ptr,
1752 struct tstream_tls_sync);
1754 return tlsss->io_recv_fn(tlsss->io_private, buf, size);
1757 ssize_t tstream_tls_sync_read(struct tstream_tls_sync *tlsss,
1758 void *buf, size_t len)
1760 int ret;
1762 ret = gnutls_record_recv(tlsss->tlss->tls_session, buf, len);
1763 if (ret == GNUTLS_E_INTERRUPTED) {
1764 errno = EINTR;
1765 return -1;
1767 if (ret == GNUTLS_E_AGAIN) {
1768 errno = EAGAIN;
1769 return -1;
1772 if (ret < 0) {
1773 DBG_WARNING("TLS gnutls_record_recv(%zu) - %s\n",
1774 (size_t)len, gnutls_strerror(ret));
1775 errno = EIO;
1776 return -1;
1779 return ret;
1782 ssize_t tstream_tls_sync_write(struct tstream_tls_sync *tlsss,
1783 const void *buf, size_t len)
1785 int ret;
1787 ret = gnutls_record_send(tlsss->tlss->tls_session, buf, len);
1788 if (ret == GNUTLS_E_INTERRUPTED) {
1789 errno = EINTR;
1790 return -1;
1792 if (ret == GNUTLS_E_AGAIN) {
1793 errno = EAGAIN;
1794 return -1;
1797 if (ret < 0) {
1798 DBG_WARNING("TLS gnutls_record_send(%zu) - %s\n",
1799 (size_t)len, gnutls_strerror(ret));
1800 errno = EIO;
1801 return -1;
1804 return ret;
1807 size_t tstream_tls_sync_pending(struct tstream_tls_sync *tlsss)
1809 return gnutls_record_check_pending(tlsss->tlss->tls_session);
1812 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)
1823 struct tstream_tls_sync *tlsss = NULL;
1824 struct tstream_tls *tlss = NULL;
1825 NTSTATUS status;
1826 int ret;
1828 tlsss = talloc_zero(mem_ctx, struct tstream_tls_sync);
1829 if (tlsss == NULL) {
1830 return NT_STATUS_NO_MEMORY;
1833 tlsss->io_private = io_private;
1834 tlsss->io_send_fn = io_send_fn;
1835 tlsss->io_recv_fn = io_recv_fn;
1837 tlss = talloc_zero(tlsss, struct tstream_tls);
1838 if (tlss == NULL) {
1839 TALLOC_FREE(tlsss);
1840 return NT_STATUS_NO_MEMORY;
1842 talloc_set_destructor(tlss, tstream_tls_destructor);
1843 tlss->is_server = false;
1845 tlsss->tlss = tlss;
1847 status = tstream_tls_prepare_gnutls(_tls_params, tlss);
1848 if (!NT_STATUS_IS_OK(status)) {
1849 TALLOC_FREE(tlsss);
1850 return status;
1853 gnutls_transport_set_ptr(tlss->tls_session,
1854 (gnutls_transport_ptr_t)tlsss);
1855 gnutls_transport_set_pull_function(tlss->tls_session,
1856 (gnutls_pull_func)tstream_tls_sync_pull_function);
1857 gnutls_transport_set_push_function(tlss->tls_session,
1858 (gnutls_push_func)tstream_tls_sync_push_function);
1860 do {
1862 * The caller should have the socket blocking
1863 * and do the timeout handling in the
1864 * io_send/recv_fn
1866 ret = gnutls_handshake(tlss->tls_session);
1867 } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
1869 if (gnutls_error_is_fatal(ret) != 0) {
1870 TALLOC_FREE(tlsss);
1871 return gnutls_error_to_ntstatus(ret,
1872 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1875 if (ret != GNUTLS_E_SUCCESS) {
1876 TALLOC_FREE(tlsss);
1877 return gnutls_error_to_ntstatus(ret,
1878 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1881 status = tstream_tls_verify_peer(tlss);
1882 if (!NT_STATUS_IS_OK(status)) {
1883 TALLOC_FREE(tlsss);
1884 return status;
1887 status = tstream_tls_setup_channel_bindings(tlss);
1888 if (!NT_STATUS_IS_OK(status)) {
1889 TALLOC_FREE(tlsss);
1890 return status;
1893 *_tlsss = tlsss;
1894 return NT_STATUS_OK;