s4:lib/tls: assert that event contexts are not mixed
[samba.git] / source4 / lib / tls / tls_tstream.c
blob347c47ed48eb14bdd30c258a371e61dce461f80b
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"
31 #include <gnutls/gnutls.h>
32 #include <gnutls/x509.h>
34 #define DH_BITS 2048
36 const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer)
38 switch (verify_peer) {
39 case TLS_VERIFY_PEER_NO_CHECK:
40 return TLS_VERIFY_PEER_NO_CHECK_STRING;
42 case TLS_VERIFY_PEER_CA_ONLY:
43 return TLS_VERIFY_PEER_CA_ONLY_STRING;
45 case TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE:
46 return TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING;
48 case TLS_VERIFY_PEER_CA_AND_NAME:
49 return TLS_VERIFY_PEER_CA_AND_NAME_STRING;
51 case TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE:
52 return TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING;
55 return "unknown tls_verify_peer_state";
58 static const struct tstream_context_ops tstream_tls_ops;
60 struct tstream_tls {
61 struct tstream_context *plain_stream;
62 int error;
64 gnutls_session_t tls_session;
66 enum tls_verify_peer_state verify_peer;
67 const char *peer_name;
69 struct tevent_context *current_ev;
71 struct tevent_immediate *retry_im;
73 struct {
74 struct tevent_req *mgmt_req;
75 } waiting_flush;
77 struct {
78 uint8_t *buf;
79 off_t ofs;
80 struct iovec iov;
81 struct tevent_req *subreq;
82 } push;
84 struct {
85 uint8_t *buf;
86 struct iovec iov;
87 struct tevent_req *subreq;
88 } pull;
90 struct {
91 struct tevent_req *req;
92 } handshake;
94 struct {
95 off_t ofs;
96 size_t left;
97 uint8_t buffer[1024];
98 struct tevent_req *req;
99 } write;
101 struct {
102 off_t ofs;
103 size_t left;
104 uint8_t buffer[1024];
105 struct tevent_req *req;
106 } read;
108 struct {
109 struct tevent_req *req;
110 } disconnect;
113 static void tstream_tls_retry_handshake(struct tstream_context *stream);
114 static void tstream_tls_retry_read(struct tstream_context *stream);
115 static void tstream_tls_retry_write(struct tstream_context *stream);
116 static void tstream_tls_retry_disconnect(struct tstream_context *stream);
117 static void tstream_tls_retry_trigger(struct tevent_context *ctx,
118 struct tevent_immediate *im,
119 void *private_data);
121 static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
124 struct tstream_tls *tlss =
125 tstream_context_data(stream,
126 struct tstream_tls);
128 if (tlss->push.subreq == NULL && tlss->pull.subreq == NULL) {
129 if (tlss->waiting_flush.mgmt_req != NULL) {
130 struct tevent_req *req = tlss->waiting_flush.mgmt_req;
132 tlss->waiting_flush.mgmt_req = NULL;
134 tevent_req_done(req);
135 return;
139 if (tlss->disconnect.req) {
140 tstream_tls_retry_disconnect(stream);
141 return;
144 if (tlss->handshake.req) {
145 tstream_tls_retry_handshake(stream);
146 return;
149 if (tlss->write.req && tlss->read.req && !deferred) {
150 tevent_schedule_immediate(tlss->retry_im, tlss->current_ev,
151 tstream_tls_retry_trigger,
152 stream);
155 if (tlss->write.req) {
156 tstream_tls_retry_write(stream);
157 return;
160 if (tlss->read.req) {
161 tstream_tls_retry_read(stream);
162 return;
166 static void tstream_tls_retry_trigger(struct tevent_context *ctx,
167 struct tevent_immediate *im,
168 void *private_data)
170 struct tstream_context *stream =
171 talloc_get_type_abort(private_data,
172 struct tstream_context);
174 tstream_tls_retry(stream, true);
177 static void tstream_tls_push_done(struct tevent_req *subreq);
179 static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
180 const void *buf, size_t size)
182 struct tstream_context *stream =
183 talloc_get_type_abort(ptr,
184 struct tstream_context);
185 struct tstream_tls *tlss =
186 tstream_context_data(stream,
187 struct tstream_tls);
188 struct tevent_req *subreq = NULL;
189 uint8_t *nbuf;
190 size_t len;
192 if (tlss->error != 0) {
193 errno = tlss->error;
194 return -1;
197 if (tlss->push.subreq) {
198 errno = EAGAIN;
199 return -1;
202 len = MIN(size, UINT16_MAX - tlss->push.ofs);
204 if (len == 0) {
205 errno = EAGAIN;
206 return -1;
209 nbuf = talloc_realloc(tlss, tlss->push.buf,
210 uint8_t, tlss->push.ofs + len);
211 if (nbuf == NULL) {
212 if (tlss->push.buf) {
213 errno = EAGAIN;
214 return -1;
217 return -1;
219 tlss->push.buf = nbuf;
221 memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
222 tlss->push.ofs += len;
224 tlss->push.iov.iov_base = (char *)tlss->push.buf;
225 tlss->push.iov.iov_len = tlss->push.ofs;
227 subreq = tstream_writev_send(tlss,
228 tlss->current_ev,
229 tlss->plain_stream,
230 &tlss->push.iov, 1);
231 if (subreq == NULL) {
232 errno = ENOMEM;
233 return -1;
235 tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
237 tlss->push.subreq = subreq;
238 return len;
241 static void tstream_tls_push_done(struct tevent_req *subreq)
243 struct tstream_context *stream =
244 tevent_req_callback_data(subreq,
245 struct tstream_context);
246 struct tstream_tls *tlss =
247 tstream_context_data(stream,
248 struct tstream_tls);
249 int ret;
250 int sys_errno;
252 tlss->push.subreq = NULL;
253 ZERO_STRUCT(tlss->push.iov);
254 TALLOC_FREE(tlss->push.buf);
255 tlss->push.ofs = 0;
257 ret = tstream_writev_recv(subreq, &sys_errno);
258 TALLOC_FREE(subreq);
259 if (ret == -1) {
260 tlss->error = sys_errno;
261 tstream_tls_retry(stream, false);
262 return;
265 tstream_tls_retry(stream, false);
268 static void tstream_tls_pull_done(struct tevent_req *subreq);
270 static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
271 void *buf, size_t size)
273 struct tstream_context *stream =
274 talloc_get_type_abort(ptr,
275 struct tstream_context);
276 struct tstream_tls *tlss =
277 tstream_context_data(stream,
278 struct tstream_tls);
279 struct tevent_req *subreq;
280 size_t len;
282 if (tlss->error != 0) {
283 errno = tlss->error;
284 return -1;
287 if (tlss->pull.subreq) {
288 errno = EAGAIN;
289 return -1;
292 if (tlss->pull.iov.iov_base) {
293 uint8_t *b;
294 size_t n;
296 b = (uint8_t *)tlss->pull.iov.iov_base;
298 n = MIN(tlss->pull.iov.iov_len, size);
299 memcpy(buf, b, n);
301 tlss->pull.iov.iov_len -= n;
302 b += n;
303 tlss->pull.iov.iov_base = (char *)b;
304 if (tlss->pull.iov.iov_len == 0) {
305 tlss->pull.iov.iov_base = NULL;
306 TALLOC_FREE(tlss->pull.buf);
309 return n;
312 if (size == 0) {
313 return 0;
316 len = MIN(size, UINT16_MAX);
318 tlss->pull.buf = talloc_array(tlss, uint8_t, len);
319 if (tlss->pull.buf == NULL) {
320 return -1;
323 tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
324 tlss->pull.iov.iov_len = len;
326 subreq = tstream_readv_send(tlss,
327 tlss->current_ev,
328 tlss->plain_stream,
329 &tlss->pull.iov, 1);
330 if (subreq == NULL) {
331 errno = ENOMEM;
332 return -1;
334 tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
336 tlss->pull.subreq = subreq;
337 errno = EAGAIN;
338 return -1;
341 static void tstream_tls_pull_done(struct tevent_req *subreq)
343 struct tstream_context *stream =
344 tevent_req_callback_data(subreq,
345 struct tstream_context);
346 struct tstream_tls *tlss =
347 tstream_context_data(stream,
348 struct tstream_tls);
349 int ret;
350 int sys_errno;
352 tlss->pull.subreq = NULL;
354 ret = tstream_readv_recv(subreq, &sys_errno);
355 TALLOC_FREE(subreq);
356 if (ret == -1) {
357 tlss->error = sys_errno;
358 tstream_tls_retry(stream, false);
359 return;
362 tstream_tls_retry(stream, false);
365 static int tstream_tls_destructor(struct tstream_tls *tlss)
367 if (tlss->tls_session) {
368 gnutls_deinit(tlss->tls_session);
369 tlss->tls_session = NULL;
372 return 0;
375 static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
377 struct tstream_tls *tlss =
378 tstream_context_data(stream,
379 struct tstream_tls);
380 size_t ret;
382 if (tlss->error != 0) {
383 errno = tlss->error;
384 return -1;
387 ret = gnutls_record_check_pending(tlss->tls_session);
388 ret += tlss->read.left;
390 return ret;
393 struct tstream_tls_readv_state {
394 struct tstream_context *stream;
396 struct iovec *vector;
397 int count;
399 int ret;
402 static void tstream_tls_readv_crypt_next(struct tevent_req *req);
404 static struct tevent_req *tstream_tls_readv_send(TALLOC_CTX *mem_ctx,
405 struct tevent_context *ev,
406 struct tstream_context *stream,
407 struct iovec *vector,
408 size_t count)
410 struct tstream_tls *tlss =
411 tstream_context_data(stream,
412 struct tstream_tls);
413 struct tevent_req *req;
414 struct tstream_tls_readv_state *state;
416 tlss->read.req = NULL;
418 if (tlss->current_ev != ev) {
419 SMB_ASSERT(tlss->push.subreq == NULL);
420 SMB_ASSERT(tlss->pull.subreq == NULL);
423 tlss->current_ev = ev;
425 req = tevent_req_create(mem_ctx, &state,
426 struct tstream_tls_readv_state);
427 if (req == NULL) {
428 return NULL;
431 state->stream = stream;
432 state->ret = 0;
434 if (tlss->error != 0) {
435 tevent_req_error(req, tlss->error);
436 return tevent_req_post(req, ev);
440 * we make a copy of the vector so we can change the structure
442 state->vector = talloc_array(state, struct iovec, count);
443 if (tevent_req_nomem(state->vector, req)) {
444 return tevent_req_post(req, ev);
446 memcpy(state->vector, vector, sizeof(struct iovec) * count);
447 state->count = count;
449 tstream_tls_readv_crypt_next(req);
450 if (!tevent_req_is_in_progress(req)) {
451 return tevent_req_post(req, ev);
454 return req;
457 static void tstream_tls_readv_crypt_next(struct tevent_req *req)
459 struct tstream_tls_readv_state *state =
460 tevent_req_data(req,
461 struct tstream_tls_readv_state);
462 struct tstream_tls *tlss =
463 tstream_context_data(state->stream,
464 struct tstream_tls);
467 * copy the pending buffer first
469 while (tlss->read.left > 0 && state->count > 0) {
470 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
471 size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
473 memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
475 base += len;
476 state->vector[0].iov_base = (char *) base;
477 state->vector[0].iov_len -= len;
479 tlss->read.ofs += len;
480 tlss->read.left -= len;
482 if (state->vector[0].iov_len == 0) {
483 state->vector += 1;
484 state->count -= 1;
487 state->ret += len;
490 if (state->count == 0) {
491 tevent_req_done(req);
492 return;
495 tlss->read.req = req;
496 tstream_tls_retry_read(state->stream);
499 static void tstream_tls_retry_read(struct tstream_context *stream)
501 struct tstream_tls *tlss =
502 tstream_context_data(stream,
503 struct tstream_tls);
504 struct tevent_req *req = tlss->read.req;
505 int ret;
507 if (tlss->error != 0) {
508 tevent_req_error(req, tlss->error);
509 return;
512 tlss->read.left = 0;
513 tlss->read.ofs = 0;
515 ret = gnutls_record_recv(tlss->tls_session,
516 tlss->read.buffer,
517 sizeof(tlss->read.buffer));
518 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
519 return;
522 tlss->read.req = NULL;
524 if (gnutls_error_is_fatal(ret) != 0) {
525 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
526 tlss->error = EIO;
527 tevent_req_error(req, tlss->error);
528 return;
531 if (ret == 0) {
532 tlss->error = EPIPE;
533 tevent_req_error(req, tlss->error);
534 return;
537 tlss->read.left = ret;
538 tstream_tls_readv_crypt_next(req);
541 static int tstream_tls_readv_recv(struct tevent_req *req,
542 int *perrno)
544 struct tstream_tls_readv_state *state =
545 tevent_req_data(req,
546 struct tstream_tls_readv_state);
547 struct tstream_tls *tlss =
548 tstream_context_data(state->stream,
549 struct tstream_tls);
550 int ret;
552 tlss->read.req = NULL;
554 ret = tsocket_simple_int_recv(req, perrno);
555 if (ret == 0) {
556 ret = state->ret;
559 tevent_req_received(req);
560 return ret;
563 struct tstream_tls_writev_state {
564 struct tstream_context *stream;
566 struct iovec *vector;
567 int count;
569 int ret;
572 static void tstream_tls_writev_crypt_next(struct tevent_req *req);
574 static struct tevent_req *tstream_tls_writev_send(TALLOC_CTX *mem_ctx,
575 struct tevent_context *ev,
576 struct tstream_context *stream,
577 const struct iovec *vector,
578 size_t count)
580 struct tstream_tls *tlss =
581 tstream_context_data(stream,
582 struct tstream_tls);
583 struct tevent_req *req;
584 struct tstream_tls_writev_state *state;
586 tlss->write.req = NULL;
588 if (tlss->current_ev != ev) {
589 SMB_ASSERT(tlss->push.subreq == NULL);
590 SMB_ASSERT(tlss->pull.subreq == NULL);
593 tlss->current_ev = ev;
595 req = tevent_req_create(mem_ctx, &state,
596 struct tstream_tls_writev_state);
597 if (req == NULL) {
598 return NULL;
601 state->stream = stream;
602 state->ret = 0;
604 if (tlss->error != 0) {
605 tevent_req_error(req, tlss->error);
606 return tevent_req_post(req, ev);
610 * we make a copy of the vector so we can change the structure
612 state->vector = talloc_array(state, struct iovec, count);
613 if (tevent_req_nomem(state->vector, req)) {
614 return tevent_req_post(req, ev);
616 memcpy(state->vector, vector, sizeof(struct iovec) * count);
617 state->count = count;
619 tstream_tls_writev_crypt_next(req);
620 if (!tevent_req_is_in_progress(req)) {
621 return tevent_req_post(req, ev);
624 return req;
627 static void tstream_tls_writev_crypt_next(struct tevent_req *req)
629 struct tstream_tls_writev_state *state =
630 tevent_req_data(req,
631 struct tstream_tls_writev_state);
632 struct tstream_tls *tlss =
633 tstream_context_data(state->stream,
634 struct tstream_tls);
636 tlss->write.left = sizeof(tlss->write.buffer);
637 tlss->write.ofs = 0;
640 * first fill our buffer
642 while (tlss->write.left > 0 && state->count > 0) {
643 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
644 size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
646 memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
648 base += len;
649 state->vector[0].iov_base = (char *) base;
650 state->vector[0].iov_len -= len;
652 tlss->write.ofs += len;
653 tlss->write.left -= len;
655 if (state->vector[0].iov_len == 0) {
656 state->vector += 1;
657 state->count -= 1;
660 state->ret += len;
663 if (tlss->write.ofs == 0) {
664 tevent_req_done(req);
665 return;
668 tlss->write.left = tlss->write.ofs;
669 tlss->write.ofs = 0;
671 tlss->write.req = req;
672 tstream_tls_retry_write(state->stream);
675 static void tstream_tls_retry_write(struct tstream_context *stream)
677 struct tstream_tls *tlss =
678 tstream_context_data(stream,
679 struct tstream_tls);
680 struct tevent_req *req = tlss->write.req;
681 int ret;
683 if (tlss->error != 0) {
684 tevent_req_error(req, tlss->error);
685 return;
688 ret = gnutls_record_send(tlss->tls_session,
689 tlss->write.buffer + tlss->write.ofs,
690 tlss->write.left);
691 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
692 return;
695 tlss->write.req = NULL;
697 if (gnutls_error_is_fatal(ret) != 0) {
698 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
699 tlss->error = EIO;
700 tevent_req_error(req, tlss->error);
701 return;
704 if (ret == 0) {
705 tlss->error = EPIPE;
706 tevent_req_error(req, tlss->error);
707 return;
710 tlss->write.ofs += ret;
711 tlss->write.left -= ret;
713 if (tlss->write.left > 0) {
714 tlss->write.req = req;
715 tstream_tls_retry_write(stream);
716 return;
719 tstream_tls_writev_crypt_next(req);
722 static int tstream_tls_writev_recv(struct tevent_req *req,
723 int *perrno)
725 struct tstream_tls_writev_state *state =
726 tevent_req_data(req,
727 struct tstream_tls_writev_state);
728 struct tstream_tls *tlss =
729 tstream_context_data(state->stream,
730 struct tstream_tls);
731 int ret;
733 tlss->write.req = NULL;
735 ret = tsocket_simple_int_recv(req, perrno);
736 if (ret == 0) {
737 ret = state->ret;
740 tevent_req_received(req);
741 return ret;
744 struct tstream_tls_disconnect_state {
745 uint8_t _dummy;
748 static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
749 struct tevent_context *ev,
750 struct tstream_context *stream)
752 struct tstream_tls *tlss =
753 tstream_context_data(stream,
754 struct tstream_tls);
755 struct tevent_req *req;
756 struct tstream_tls_disconnect_state *state;
758 tlss->disconnect.req = NULL;
760 if (tlss->current_ev != ev) {
761 SMB_ASSERT(tlss->push.subreq == NULL);
762 SMB_ASSERT(tlss->pull.subreq == NULL);
765 tlss->current_ev = ev;
767 req = tevent_req_create(mem_ctx, &state,
768 struct tstream_tls_disconnect_state);
769 if (req == NULL) {
770 return NULL;
773 if (tlss->error != 0) {
774 tevent_req_error(req, tlss->error);
775 return tevent_req_post(req, ev);
778 tlss->disconnect.req = req;
779 tstream_tls_retry_disconnect(stream);
780 if (!tevent_req_is_in_progress(req)) {
781 return tevent_req_post(req, ev);
784 return req;
787 static void tstream_tls_retry_disconnect(struct tstream_context *stream)
789 struct tstream_tls *tlss =
790 tstream_context_data(stream,
791 struct tstream_tls);
792 struct tevent_req *req = tlss->disconnect.req;
793 int ret;
795 if (tlss->error != 0) {
796 tevent_req_error(req, tlss->error);
797 return;
800 ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
801 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
802 return;
805 tlss->disconnect.req = NULL;
807 if (gnutls_error_is_fatal(ret) != 0) {
808 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
809 tlss->error = EIO;
810 tevent_req_error(req, tlss->error);
811 return;
814 if (ret != GNUTLS_E_SUCCESS) {
815 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
816 tlss->error = EIO;
817 tevent_req_error(req, tlss->error);
818 return;
821 if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
822 tlss->waiting_flush.mgmt_req = req;
823 return;
826 tevent_req_done(req);
829 static int tstream_tls_disconnect_recv(struct tevent_req *req,
830 int *perrno)
832 int ret;
834 ret = tsocket_simple_int_recv(req, perrno);
836 tevent_req_received(req);
837 return ret;
840 static const struct tstream_context_ops tstream_tls_ops = {
841 .name = "tls",
843 .pending_bytes = tstream_tls_pending_bytes,
845 .readv_send = tstream_tls_readv_send,
846 .readv_recv = tstream_tls_readv_recv,
848 .writev_send = tstream_tls_writev_send,
849 .writev_recv = tstream_tls_writev_recv,
851 .disconnect_send = tstream_tls_disconnect_send,
852 .disconnect_recv = tstream_tls_disconnect_recv,
855 struct tstream_tls_params_internal {
856 gnutls_certificate_credentials_t x509_cred;
857 gnutls_dh_params_t dh_params;
858 const char *tls_priority;
859 bool tls_enabled;
860 enum tls_verify_peer_state verify_peer;
861 const char *peer_name;
864 struct tstream_tls_params {
865 struct tstream_tls_params_internal *internal;
868 static int tstream_tls_params_internal_destructor(struct tstream_tls_params_internal *tlsp)
870 if (tlsp->x509_cred) {
871 gnutls_certificate_free_credentials(tlsp->x509_cred);
872 tlsp->x509_cred = NULL;
874 if (tlsp->dh_params) {
875 gnutls_dh_params_deinit(tlsp->dh_params);
876 tlsp->dh_params = NULL;
879 return 0;
882 bool tstream_tls_params_enabled(struct tstream_tls_params *tls_params)
884 struct tstream_tls_params_internal *tlsp = tls_params->internal;
886 return tlsp->tls_enabled;
889 NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
890 const char *ca_file,
891 const char *crl_file,
892 const char *tls_priority,
893 enum tls_verify_peer_state verify_peer,
894 const char *peer_name,
895 struct tstream_tls_params **_tlsp)
897 struct tstream_tls_params *__tlsp = NULL;
898 struct tstream_tls_params_internal *tlsp = NULL;
899 int ret;
901 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
902 if (__tlsp == NULL) {
903 return NT_STATUS_NO_MEMORY;
906 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
907 if (tlsp == NULL) {
908 TALLOC_FREE(__tlsp);
909 return NT_STATUS_NO_MEMORY;
911 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
912 __tlsp->internal = tlsp;
914 tlsp->verify_peer = verify_peer;
915 if (peer_name != NULL) {
916 tlsp->peer_name = talloc_strdup(tlsp, peer_name);
917 if (tlsp->peer_name == NULL) {
918 TALLOC_FREE(__tlsp);
919 return NT_STATUS_NO_MEMORY;
921 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
922 DEBUG(0,("TLS failed to missing peer_name - "
923 "with 'tls verify peer = %s'\n",
924 tls_verify_peer_string(tlsp->verify_peer)));
925 TALLOC_FREE(__tlsp);
926 return NT_STATUS_INVALID_PARAMETER_MIX;
929 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
930 if (ret != GNUTLS_E_SUCCESS) {
931 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
932 TALLOC_FREE(__tlsp);
933 return NT_STATUS_NO_MEMORY;
936 if (ca_file && *ca_file && file_exist(ca_file)) {
937 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
938 ca_file,
939 GNUTLS_X509_FMT_PEM);
940 if (ret < 0) {
941 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
942 ca_file, gnutls_strerror(ret)));
943 TALLOC_FREE(__tlsp);
944 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
946 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
947 DEBUG(0,("TLS failed to missing cafile %s - "
948 "with 'tls verify peer = %s'\n",
949 ca_file,
950 tls_verify_peer_string(tlsp->verify_peer)));
951 TALLOC_FREE(__tlsp);
952 return NT_STATUS_INVALID_PARAMETER_MIX;
955 if (crl_file && *crl_file && file_exist(crl_file)) {
956 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
957 crl_file,
958 GNUTLS_X509_FMT_PEM);
959 if (ret < 0) {
960 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
961 crl_file, gnutls_strerror(ret)));
962 TALLOC_FREE(__tlsp);
963 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
965 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE) {
966 DEBUG(0,("TLS failed to missing crlfile %s - "
967 "with 'tls verify peer = %s'\n",
968 crl_file,
969 tls_verify_peer_string(tlsp->verify_peer)));
970 TALLOC_FREE(__tlsp);
971 return NT_STATUS_INVALID_PARAMETER_MIX;
974 tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
975 if (tlsp->tls_priority == NULL) {
976 TALLOC_FREE(__tlsp);
977 return NT_STATUS_NO_MEMORY;
980 tlsp->tls_enabled = true;
982 *_tlsp = __tlsp;
983 return NT_STATUS_OK;
986 struct tstream_tls_connect_state {
987 struct tstream_context *tls_stream;
990 struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
991 struct tevent_context *ev,
992 struct tstream_context *plain_stream,
993 struct tstream_tls_params *_tls_params,
994 const char *location)
996 struct tevent_req *req;
997 struct tstream_tls_connect_state *state;
998 const char *error_pos;
999 struct tstream_tls *tlss;
1000 struct tstream_tls_params_internal *tls_params = NULL;
1001 int ret;
1002 unsigned int flags = GNUTLS_CLIENT;
1004 req = tevent_req_create(mem_ctx, &state,
1005 struct tstream_tls_connect_state);
1006 if (req == NULL) {
1007 return NULL;
1010 state->tls_stream = tstream_context_create(state,
1011 &tstream_tls_ops,
1012 &tlss,
1013 struct tstream_tls,
1014 location);
1015 if (tevent_req_nomem(state->tls_stream, req)) {
1016 return tevent_req_post(req, ev);
1018 ZERO_STRUCTP(tlss);
1019 talloc_set_destructor(tlss, tstream_tls_destructor);
1022 * Note we need to make sure x509_cred and dh_params
1023 * from tstream_tls_params_internal stay alive for
1024 * the whole lifetime of this session!
1026 * See 'man gnutls_credentials_set' and
1027 * 'man gnutls_certificate_set_dh_params'.
1029 * Note: here we use talloc_reference() in a way
1030 * that does not expose it to the caller.
1033 tls_params = talloc_reference(tlss, _tls_params->internal);
1034 if (tevent_req_nomem(tls_params, req)) {
1035 return tevent_req_post(req, ev);
1038 tlss->plain_stream = plain_stream;
1039 tlss->verify_peer = tls_params->verify_peer;
1040 if (tls_params->peer_name != NULL) {
1041 tlss->peer_name = talloc_strdup(tlss, tls_params->peer_name);
1042 if (tevent_req_nomem(tlss->peer_name, req)) {
1043 return tevent_req_post(req, ev);
1047 tlss->current_ev = ev;
1048 tlss->retry_im = tevent_create_immediate(tlss);
1049 if (tevent_req_nomem(tlss->retry_im, req)) {
1050 return tevent_req_post(req, ev);
1053 #ifdef GNUTLS_NO_TICKETS
1055 * tls_tstream can't properly handle 'New Session Ticket' messages
1056 * sent 'after' the client sends the 'Finished' message.
1057 * GNUTLS_NO_TICKETS was introduced in GnuTLS 3.5.6. This flag is to
1058 * indicate the session Flag session should not use resumption with
1059 * session tickets.
1061 flags |= GNUTLS_NO_TICKETS;
1062 #endif
1064 ret = gnutls_init(&tlss->tls_session, flags);
1065 if (ret != GNUTLS_E_SUCCESS) {
1066 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1067 tevent_req_error(req, EINVAL);
1068 return tevent_req_post(req, ev);
1071 ret = gnutls_set_default_priority(tlss->tls_session);
1072 if (ret != GNUTLS_E_SUCCESS) {
1073 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1074 __location__, gnutls_strerror(ret));
1075 tevent_req_error(req, EINVAL);
1076 return tevent_req_post(req, ev);
1079 if (strlen(tls_params->tls_priority) > 0) {
1080 ret = gnutls_priority_set_direct(tlss->tls_session,
1081 tls_params->tls_priority,
1082 &error_pos);
1083 if (ret != GNUTLS_E_SUCCESS) {
1084 DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1085 __location__, gnutls_strerror(ret), error_pos));
1086 tevent_req_error(req, EINVAL);
1087 return tevent_req_post(req, ev);
1091 ret = gnutls_credentials_set(tlss->tls_session,
1092 GNUTLS_CRD_CERTIFICATE,
1093 tls_params->x509_cred);
1094 if (ret != GNUTLS_E_SUCCESS) {
1095 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1096 tevent_req_error(req, EINVAL);
1097 return tevent_req_post(req, ev);
1100 gnutls_transport_set_ptr(tlss->tls_session,
1101 (gnutls_transport_ptr_t)state->tls_stream);
1102 gnutls_transport_set_pull_function(tlss->tls_session,
1103 (gnutls_pull_func)tstream_tls_pull_function);
1104 gnutls_transport_set_push_function(tlss->tls_session,
1105 (gnutls_push_func)tstream_tls_push_function);
1107 tlss->handshake.req = req;
1108 tstream_tls_retry_handshake(state->tls_stream);
1109 if (!tevent_req_is_in_progress(req)) {
1110 return tevent_req_post(req, ev);
1113 return req;
1116 int tstream_tls_connect_recv(struct tevent_req *req,
1117 int *perrno,
1118 TALLOC_CTX *mem_ctx,
1119 struct tstream_context **tls_stream)
1121 struct tstream_tls_connect_state *state =
1122 tevent_req_data(req,
1123 struct tstream_tls_connect_state);
1125 if (tevent_req_is_unix_error(req, perrno)) {
1126 tevent_req_received(req);
1127 return -1;
1130 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1131 tevent_req_received(req);
1132 return 0;
1136 initialise global tls state
1138 NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
1139 const char *dns_host_name,
1140 bool enabled,
1141 const char *key_file,
1142 const char *cert_file,
1143 const char *ca_file,
1144 const char *crl_file,
1145 const char *dhp_file,
1146 const char *tls_priority,
1147 struct tstream_tls_params **_tlsp)
1149 struct tstream_tls_params *__tlsp = NULL;
1150 struct tstream_tls_params_internal *tlsp = NULL;
1151 int ret;
1152 struct stat st;
1154 if (!enabled || key_file == NULL || *key_file == 0) {
1155 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1156 if (__tlsp == NULL) {
1157 return NT_STATUS_NO_MEMORY;
1160 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1161 if (tlsp == NULL) {
1162 TALLOC_FREE(__tlsp);
1163 return NT_STATUS_NO_MEMORY;
1166 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1167 __tlsp->internal = tlsp;
1168 tlsp->tls_enabled = false;
1170 *_tlsp = __tlsp;
1171 return NT_STATUS_OK;
1174 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1175 if (__tlsp == NULL) {
1176 return NT_STATUS_NO_MEMORY;
1179 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1180 if (tlsp == NULL) {
1181 TALLOC_FREE(__tlsp);
1182 return NT_STATUS_NO_MEMORY;
1185 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1186 __tlsp->internal = tlsp;
1188 if (!file_exist(ca_file)) {
1189 tls_cert_generate(tlsp, dns_host_name,
1190 key_file, cert_file, ca_file);
1193 if (file_exist(key_file) &&
1194 !file_check_permissions(key_file, geteuid(), 0600, &st))
1196 DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
1197 "owner uid %u should be %u, mode 0%o should be 0%o\n"
1198 "This is known as CVE-2013-4476.\n"
1199 "Removing all tls .pem files will cause an "
1200 "auto-regeneration with the correct permissions.\n",
1201 key_file,
1202 (unsigned int)st.st_uid, geteuid(),
1203 (unsigned int)(st.st_mode & 0777), 0600));
1204 TALLOC_FREE(__tlsp);
1205 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1208 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
1209 if (ret != GNUTLS_E_SUCCESS) {
1210 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1211 TALLOC_FREE(__tlsp);
1212 return NT_STATUS_NO_MEMORY;
1215 if (ca_file && *ca_file) {
1216 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1217 ca_file,
1218 GNUTLS_X509_FMT_PEM);
1219 if (ret < 0) {
1220 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1221 ca_file, gnutls_strerror(ret)));
1222 TALLOC_FREE(__tlsp);
1223 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1227 if (crl_file && *crl_file) {
1228 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1229 crl_file,
1230 GNUTLS_X509_FMT_PEM);
1231 if (ret < 0) {
1232 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1233 crl_file, gnutls_strerror(ret)));
1234 TALLOC_FREE(__tlsp);
1235 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1239 ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
1240 cert_file, key_file,
1241 GNUTLS_X509_FMT_PEM);
1242 if (ret != GNUTLS_E_SUCCESS) {
1243 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1244 cert_file, key_file, gnutls_strerror(ret)));
1245 TALLOC_FREE(__tlsp);
1246 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1249 ret = gnutls_dh_params_init(&tlsp->dh_params);
1250 if (ret != GNUTLS_E_SUCCESS) {
1251 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1252 TALLOC_FREE(__tlsp);
1253 return NT_STATUS_NO_MEMORY;
1256 if (dhp_file && *dhp_file) {
1257 gnutls_datum_t dhparms;
1258 size_t size;
1260 dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
1262 if (!dhparms.data) {
1263 DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1264 dhp_file, errno, strerror(errno)));
1265 TALLOC_FREE(__tlsp);
1266 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1268 dhparms.size = size;
1270 ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
1271 &dhparms,
1272 GNUTLS_X509_FMT_PEM);
1273 if (ret != GNUTLS_E_SUCCESS) {
1274 DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1275 dhp_file, gnutls_strerror(ret)));
1276 TALLOC_FREE(__tlsp);
1277 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1279 } else {
1280 ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
1281 if (ret != GNUTLS_E_SUCCESS) {
1282 DEBUG(0,("TLS failed to generate dh_params - %s\n",
1283 gnutls_strerror(ret)));
1284 TALLOC_FREE(__tlsp);
1285 return NT_STATUS_INTERNAL_ERROR;
1289 gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
1291 tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
1292 if (tlsp->tls_priority == NULL) {
1293 TALLOC_FREE(__tlsp);
1294 return NT_STATUS_NO_MEMORY;
1297 tlsp->tls_enabled = true;
1299 *_tlsp = __tlsp;
1300 return NT_STATUS_OK;
1303 struct tstream_tls_accept_state {
1304 struct tstream_context *tls_stream;
1307 struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
1308 struct tevent_context *ev,
1309 struct tstream_context *plain_stream,
1310 struct tstream_tls_params *_tlsp,
1311 const char *location)
1313 struct tevent_req *req;
1314 struct tstream_tls_accept_state *state;
1315 struct tstream_tls *tlss;
1316 const char *error_pos;
1317 struct tstream_tls_params_internal *tlsp = NULL;
1318 int ret;
1320 req = tevent_req_create(mem_ctx, &state,
1321 struct tstream_tls_accept_state);
1322 if (req == NULL) {
1323 return NULL;
1326 state->tls_stream = tstream_context_create(state,
1327 &tstream_tls_ops,
1328 &tlss,
1329 struct tstream_tls,
1330 location);
1331 if (tevent_req_nomem(state->tls_stream, req)) {
1332 return tevent_req_post(req, ev);
1334 ZERO_STRUCTP(tlss);
1335 talloc_set_destructor(tlss, tstream_tls_destructor);
1338 * Note we need to make sure x509_cred and dh_params
1339 * from tstream_tls_params_internal stay alive for
1340 * the whole lifetime of this session!
1342 * See 'man gnutls_credentials_set' and
1343 * 'man gnutls_certificate_set_dh_params'.
1345 * Note: here we use talloc_reference() in a way
1346 * that does not expose it to the caller.
1348 tlsp = talloc_reference(tlss, _tlsp->internal);
1349 if (tevent_req_nomem(tlsp, req)) {
1350 return tevent_req_post(req, ev);
1353 tlss->plain_stream = plain_stream;
1355 tlss->current_ev = ev;
1356 tlss->retry_im = tevent_create_immediate(tlss);
1357 if (tevent_req_nomem(tlss->retry_im, req)) {
1358 return tevent_req_post(req, ev);
1361 ret = gnutls_init(&tlss->tls_session, GNUTLS_SERVER);
1362 if (ret != GNUTLS_E_SUCCESS) {
1363 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1364 tevent_req_error(req, EINVAL);
1365 return tevent_req_post(req, ev);
1368 ret = gnutls_set_default_priority(tlss->tls_session);
1369 if (ret != GNUTLS_E_SUCCESS) {
1370 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1371 __location__, gnutls_strerror(ret));
1372 tevent_req_error(req, EINVAL);
1373 return tevent_req_post(req, ev);
1376 if (strlen(tlsp->tls_priority) > 0) {
1377 ret = gnutls_priority_set_direct(tlss->tls_session,
1378 tlsp->tls_priority,
1379 &error_pos);
1380 if (ret != GNUTLS_E_SUCCESS) {
1381 DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1382 __location__, gnutls_strerror(ret), error_pos));
1383 tevent_req_error(req, EINVAL);
1384 return tevent_req_post(req, ev);
1388 ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE,
1389 tlsp->x509_cred);
1390 if (ret != GNUTLS_E_SUCCESS) {
1391 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1392 tevent_req_error(req, EINVAL);
1393 return tevent_req_post(req, ev);
1396 gnutls_certificate_server_set_request(tlss->tls_session,
1397 GNUTLS_CERT_REQUEST);
1398 gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
1400 gnutls_transport_set_ptr(tlss->tls_session,
1401 (gnutls_transport_ptr_t)state->tls_stream);
1402 gnutls_transport_set_pull_function(tlss->tls_session,
1403 (gnutls_pull_func)tstream_tls_pull_function);
1404 gnutls_transport_set_push_function(tlss->tls_session,
1405 (gnutls_push_func)tstream_tls_push_function);
1407 tlss->handshake.req = req;
1408 tstream_tls_retry_handshake(state->tls_stream);
1409 if (!tevent_req_is_in_progress(req)) {
1410 return tevent_req_post(req, ev);
1413 return req;
1416 static void tstream_tls_retry_handshake(struct tstream_context *stream)
1418 struct tstream_tls *tlss =
1419 tstream_context_data(stream,
1420 struct tstream_tls);
1421 struct tevent_req *req = tlss->handshake.req;
1422 int ret;
1424 if (tlss->error != 0) {
1425 tevent_req_error(req, tlss->error);
1426 return;
1429 ret = gnutls_handshake(tlss->tls_session);
1430 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
1431 return;
1434 tlss->handshake.req = NULL;
1436 if (gnutls_error_is_fatal(ret) != 0) {
1437 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1438 tlss->error = EIO;
1439 tevent_req_error(req, tlss->error);
1440 return;
1443 if (ret != GNUTLS_E_SUCCESS) {
1444 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1445 tlss->error = EIO;
1446 tevent_req_error(req, tlss->error);
1447 return;
1450 if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
1451 unsigned int status = UINT32_MAX;
1452 bool ip = true;
1453 const char *hostname = NULL;
1455 if (tlss->peer_name != NULL) {
1456 ip = is_ipaddress(tlss->peer_name);
1459 if (!ip) {
1460 hostname = tlss->peer_name;
1463 if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
1464 hostname = NULL;
1467 if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
1468 if (hostname == NULL) {
1469 DEBUG(1,("TLS %s - no hostname available for "
1470 "verify_peer[%s] and peer_name[%s]\n",
1471 __location__,
1472 tls_verify_peer_string(tlss->verify_peer),
1473 tlss->peer_name));
1474 tlss->error = EINVAL;
1475 tevent_req_error(req, tlss->error);
1476 return;
1480 ret = gnutls_certificate_verify_peers3(tlss->tls_session,
1481 hostname,
1482 &status);
1483 if (ret != GNUTLS_E_SUCCESS) {
1484 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1485 tlss->error = EIO;
1486 tevent_req_error(req, tlss->error);
1487 return;
1490 if (status != 0) {
1491 DEBUG(1,("TLS %s - check failed for "
1492 "verify_peer[%s] and peer_name[%s] "
1493 "status 0x%x (%s%s%s%s%s%s%s%s)\n",
1494 __location__,
1495 tls_verify_peer_string(tlss->verify_peer),
1496 tlss->peer_name,
1497 status,
1498 status & GNUTLS_CERT_INVALID ? "invalid " : "",
1499 status & GNUTLS_CERT_REVOKED ? "revoked " : "",
1500 status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
1501 "signer_not_found " : "",
1502 status & GNUTLS_CERT_SIGNER_NOT_CA ?
1503 "signer_not_ca " : "",
1504 status & GNUTLS_CERT_INSECURE_ALGORITHM ?
1505 "insecure_algorithm " : "",
1506 status & GNUTLS_CERT_NOT_ACTIVATED ?
1507 "not_activated " : "",
1508 status & GNUTLS_CERT_EXPIRED ?
1509 "expired " : "",
1510 status & GNUTLS_CERT_UNEXPECTED_OWNER ?
1511 "unexpected_owner " : ""));
1512 tlss->error = EINVAL;
1513 tevent_req_error(req, tlss->error);
1514 return;
1518 if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
1519 tlss->waiting_flush.mgmt_req = req;
1520 return;
1523 tevent_req_done(req);
1526 int tstream_tls_accept_recv(struct tevent_req *req,
1527 int *perrno,
1528 TALLOC_CTX *mem_ctx,
1529 struct tstream_context **tls_stream)
1531 struct tstream_tls_accept_state *state =
1532 tevent_req_data(req,
1533 struct tstream_tls_accept_state);
1535 if (tevent_req_is_unix_error(req, perrno)) {
1536 tevent_req_received(req);
1537 return -1;
1540 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1541 tevent_req_received(req);
1542 return 0;