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/>.
21 #include "system/network.h"
22 #include "system/filesys.h"
23 #include "system/time.h"
24 #include "../util/tevent_unix.h"
25 #include "../lib/tsocket/tsocket.h"
26 #include "../lib/tsocket/tsocket_internal.h"
27 #include "../lib/util/util_net.h"
28 #include "lib/tls/tls.h"
30 #include <gnutls/gnutls.h>
31 #include <gnutls/x509.h>
35 const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer)
37 switch (verify_peer) {
38 case TLS_VERIFY_PEER_NO_CHECK:
39 return TLS_VERIFY_PEER_NO_CHECK_STRING;
41 case TLS_VERIFY_PEER_CA_ONLY:
42 return TLS_VERIFY_PEER_CA_ONLY_STRING;
44 case TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE:
45 return TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING;
47 case TLS_VERIFY_PEER_CA_AND_NAME:
48 return TLS_VERIFY_PEER_CA_AND_NAME_STRING;
50 case TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE:
51 return TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING;
54 return "unknown tls_verify_peer_state";
57 static const struct tstream_context_ops tstream_tls_ops;
60 struct tstream_context *plain_stream;
63 gnutls_session_t tls_session;
65 enum tls_verify_peer_state verify_peer;
66 const char *peer_name;
68 struct tevent_context *current_ev;
70 struct tevent_immediate *retry_im;
76 struct tevent_req *subreq;
77 struct tevent_immediate *im;
83 struct tevent_req *subreq;
87 struct tevent_req *req;
94 struct tevent_req *req;
100 uint8_t buffer[1024];
101 struct tevent_req *req;
105 struct tevent_req *req;
109 static void tstream_tls_retry_handshake(struct tstream_context *stream);
110 static void tstream_tls_retry_read(struct tstream_context *stream);
111 static void tstream_tls_retry_write(struct tstream_context *stream);
112 static void tstream_tls_retry_disconnect(struct tstream_context *stream);
113 static void tstream_tls_retry_trigger(struct tevent_context *ctx,
114 struct tevent_immediate *im,
117 static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
120 struct tstream_tls *tlss =
121 tstream_context_data(stream,
124 if (tlss->disconnect.req) {
125 tstream_tls_retry_disconnect(stream);
129 if (tlss->handshake.req) {
130 tstream_tls_retry_handshake(stream);
134 if (tlss->write.req && tlss->read.req && !deferred) {
135 tevent_schedule_immediate(tlss->retry_im, tlss->current_ev,
136 tstream_tls_retry_trigger,
140 if (tlss->write.req) {
141 tstream_tls_retry_write(stream);
145 if (tlss->read.req) {
146 tstream_tls_retry_read(stream);
151 static void tstream_tls_retry_trigger(struct tevent_context *ctx,
152 struct tevent_immediate *im,
155 struct tstream_context *stream =
156 talloc_get_type_abort(private_data,
157 struct tstream_context);
159 tstream_tls_retry(stream, true);
162 static void tstream_tls_push_trigger_write(struct tevent_context *ev,
163 struct tevent_immediate *im,
166 static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
167 const void *buf, size_t size)
169 struct tstream_context *stream =
170 talloc_get_type_abort(ptr,
171 struct tstream_context);
172 struct tstream_tls *tlss =
173 tstream_context_data(stream,
178 if (tlss->error != 0) {
183 if (tlss->push.subreq) {
188 len = MIN(size, UINT16_MAX - tlss->push.ofs);
195 nbuf = talloc_realloc(tlss, tlss->push.buf,
196 uint8_t, tlss->push.ofs + len);
198 if (tlss->push.buf) {
205 tlss->push.buf = nbuf;
207 memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
209 if (tlss->push.im == NULL) {
210 tlss->push.im = tevent_create_immediate(tlss);
211 if (tlss->push.im == NULL) {
217 if (tlss->push.ofs == 0) {
219 * We'll do start the tstream_writev
220 * in the next event cycle.
222 * This way we can batch all push requests,
223 * if they fit into a UINT16_MAX buffer.
225 * This is important as gnutls_handshake()
226 * had a bug in some versions e.g. 2.4.1
227 * and others (See bug #7218) and it doesn't
230 tevent_schedule_immediate(tlss->push.im,
232 tstream_tls_push_trigger_write,
236 tlss->push.ofs += len;
240 static void tstream_tls_push_done(struct tevent_req *subreq);
242 static void tstream_tls_push_trigger_write(struct tevent_context *ev,
243 struct tevent_immediate *im,
246 struct tstream_context *stream =
247 talloc_get_type_abort(private_data,
248 struct tstream_context);
249 struct tstream_tls *tlss =
250 tstream_context_data(stream,
252 struct tevent_req *subreq;
254 if (tlss->push.subreq) {
259 tlss->push.iov.iov_base = (char *)tlss->push.buf;
260 tlss->push.iov.iov_len = tlss->push.ofs;
262 subreq = tstream_writev_send(tlss,
266 if (subreq == NULL) {
267 tlss->error = ENOMEM;
268 tstream_tls_retry(stream, false);
271 tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
273 tlss->push.subreq = subreq;
276 static void tstream_tls_push_done(struct tevent_req *subreq)
278 struct tstream_context *stream =
279 tevent_req_callback_data(subreq,
280 struct tstream_context);
281 struct tstream_tls *tlss =
282 tstream_context_data(stream,
287 tlss->push.subreq = NULL;
288 ZERO_STRUCT(tlss->push.iov);
289 TALLOC_FREE(tlss->push.buf);
292 ret = tstream_writev_recv(subreq, &sys_errno);
295 tlss->error = sys_errno;
296 tstream_tls_retry(stream, false);
300 tstream_tls_retry(stream, false);
303 static void tstream_tls_pull_done(struct tevent_req *subreq);
305 static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
306 void *buf, size_t size)
308 struct tstream_context *stream =
309 talloc_get_type_abort(ptr,
310 struct tstream_context);
311 struct tstream_tls *tlss =
312 tstream_context_data(stream,
314 struct tevent_req *subreq;
317 if (tlss->error != 0) {
322 if (tlss->pull.subreq) {
327 if (tlss->pull.iov.iov_base) {
331 b = (uint8_t *)tlss->pull.iov.iov_base;
333 n = MIN(tlss->pull.iov.iov_len, size);
336 tlss->pull.iov.iov_len -= n;
338 tlss->pull.iov.iov_base = (char *)b;
339 if (tlss->pull.iov.iov_len == 0) {
340 tlss->pull.iov.iov_base = NULL;
341 TALLOC_FREE(tlss->pull.buf);
351 len = MIN(size, UINT16_MAX);
353 tlss->pull.buf = talloc_array(tlss, uint8_t, len);
354 if (tlss->pull.buf == NULL) {
358 tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
359 tlss->pull.iov.iov_len = len;
361 subreq = tstream_readv_send(tlss,
365 if (subreq == NULL) {
369 tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
371 tlss->pull.subreq = subreq;
376 static void tstream_tls_pull_done(struct tevent_req *subreq)
378 struct tstream_context *stream =
379 tevent_req_callback_data(subreq,
380 struct tstream_context);
381 struct tstream_tls *tlss =
382 tstream_context_data(stream,
387 tlss->pull.subreq = NULL;
389 ret = tstream_readv_recv(subreq, &sys_errno);
392 tlss->error = sys_errno;
393 tstream_tls_retry(stream, false);
397 tstream_tls_retry(stream, false);
400 static int tstream_tls_destructor(struct tstream_tls *tlss)
402 if (tlss->tls_session) {
403 gnutls_deinit(tlss->tls_session);
404 tlss->tls_session = NULL;
410 static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
412 struct tstream_tls *tlss =
413 tstream_context_data(stream,
417 if (tlss->error != 0) {
422 ret = gnutls_record_check_pending(tlss->tls_session);
423 ret += tlss->read.left;
428 struct tstream_tls_readv_state {
429 struct tstream_context *stream;
431 struct iovec *vector;
437 static void tstream_tls_readv_crypt_next(struct tevent_req *req);
439 static struct tevent_req *tstream_tls_readv_send(TALLOC_CTX *mem_ctx,
440 struct tevent_context *ev,
441 struct tstream_context *stream,
442 struct iovec *vector,
445 struct tstream_tls *tlss =
446 tstream_context_data(stream,
448 struct tevent_req *req;
449 struct tstream_tls_readv_state *state;
451 tlss->read.req = NULL;
452 tlss->current_ev = ev;
454 req = tevent_req_create(mem_ctx, &state,
455 struct tstream_tls_readv_state);
460 state->stream = stream;
463 if (tlss->error != 0) {
464 tevent_req_error(req, tlss->error);
465 return tevent_req_post(req, ev);
469 * we make a copy of the vector so we can change the structure
471 state->vector = talloc_array(state, struct iovec, count);
472 if (tevent_req_nomem(state->vector, req)) {
473 return tevent_req_post(req, ev);
475 memcpy(state->vector, vector, sizeof(struct iovec) * count);
476 state->count = count;
478 tstream_tls_readv_crypt_next(req);
479 if (!tevent_req_is_in_progress(req)) {
480 return tevent_req_post(req, ev);
486 static void tstream_tls_readv_crypt_next(struct tevent_req *req)
488 struct tstream_tls_readv_state *state =
490 struct tstream_tls_readv_state);
491 struct tstream_tls *tlss =
492 tstream_context_data(state->stream,
496 * copy the pending buffer first
498 while (tlss->read.left > 0 && state->count > 0) {
499 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
500 size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
502 memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
505 state->vector[0].iov_base = (char *) base;
506 state->vector[0].iov_len -= len;
508 tlss->read.ofs += len;
509 tlss->read.left -= len;
511 if (state->vector[0].iov_len == 0) {
519 if (state->count == 0) {
520 tevent_req_done(req);
524 tlss->read.req = req;
525 tstream_tls_retry_read(state->stream);
528 static void tstream_tls_retry_read(struct tstream_context *stream)
530 struct tstream_tls *tlss =
531 tstream_context_data(stream,
533 struct tevent_req *req = tlss->read.req;
536 if (tlss->error != 0) {
537 tevent_req_error(req, tlss->error);
544 ret = gnutls_record_recv(tlss->tls_session,
546 sizeof(tlss->read.buffer));
547 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
551 tlss->read.req = NULL;
553 if (gnutls_error_is_fatal(ret) != 0) {
554 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
556 tevent_req_error(req, tlss->error);
562 tevent_req_error(req, tlss->error);
566 tlss->read.left = ret;
567 tstream_tls_readv_crypt_next(req);
570 static int tstream_tls_readv_recv(struct tevent_req *req,
573 struct tstream_tls_readv_state *state =
575 struct tstream_tls_readv_state);
576 struct tstream_tls *tlss =
577 tstream_context_data(state->stream,
581 tlss->read.req = NULL;
583 ret = tsocket_simple_int_recv(req, perrno);
588 tevent_req_received(req);
592 struct tstream_tls_writev_state {
593 struct tstream_context *stream;
595 struct iovec *vector;
601 static void tstream_tls_writev_crypt_next(struct tevent_req *req);
603 static struct tevent_req *tstream_tls_writev_send(TALLOC_CTX *mem_ctx,
604 struct tevent_context *ev,
605 struct tstream_context *stream,
606 const struct iovec *vector,
609 struct tstream_tls *tlss =
610 tstream_context_data(stream,
612 struct tevent_req *req;
613 struct tstream_tls_writev_state *state;
615 tlss->write.req = NULL;
616 tlss->current_ev = ev;
618 req = tevent_req_create(mem_ctx, &state,
619 struct tstream_tls_writev_state);
624 state->stream = stream;
627 if (tlss->error != 0) {
628 tevent_req_error(req, tlss->error);
629 return tevent_req_post(req, ev);
633 * we make a copy of the vector so we can change the structure
635 state->vector = talloc_array(state, struct iovec, count);
636 if (tevent_req_nomem(state->vector, req)) {
637 return tevent_req_post(req, ev);
639 memcpy(state->vector, vector, sizeof(struct iovec) * count);
640 state->count = count;
642 tstream_tls_writev_crypt_next(req);
643 if (!tevent_req_is_in_progress(req)) {
644 return tevent_req_post(req, ev);
650 static void tstream_tls_writev_crypt_next(struct tevent_req *req)
652 struct tstream_tls_writev_state *state =
654 struct tstream_tls_writev_state);
655 struct tstream_tls *tlss =
656 tstream_context_data(state->stream,
659 tlss->write.left = sizeof(tlss->write.buffer);
663 * first fill our buffer
665 while (tlss->write.left > 0 && state->count > 0) {
666 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
667 size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
669 memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
672 state->vector[0].iov_base = (char *) base;
673 state->vector[0].iov_len -= len;
675 tlss->write.ofs += len;
676 tlss->write.left -= len;
678 if (state->vector[0].iov_len == 0) {
686 if (tlss->write.ofs == 0) {
687 tevent_req_done(req);
691 tlss->write.left = tlss->write.ofs;
694 tlss->write.req = req;
695 tstream_tls_retry_write(state->stream);
698 static void tstream_tls_retry_write(struct tstream_context *stream)
700 struct tstream_tls *tlss =
701 tstream_context_data(stream,
703 struct tevent_req *req = tlss->write.req;
706 if (tlss->error != 0) {
707 tevent_req_error(req, tlss->error);
711 ret = gnutls_record_send(tlss->tls_session,
712 tlss->write.buffer + tlss->write.ofs,
714 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
718 tlss->write.req = NULL;
720 if (gnutls_error_is_fatal(ret) != 0) {
721 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
723 tevent_req_error(req, tlss->error);
729 tevent_req_error(req, tlss->error);
733 tlss->write.ofs += ret;
734 tlss->write.left -= ret;
736 if (tlss->write.left > 0) {
737 tlss->write.req = req;
738 tstream_tls_retry_write(stream);
742 tstream_tls_writev_crypt_next(req);
745 static int tstream_tls_writev_recv(struct tevent_req *req,
748 struct tstream_tls_writev_state *state =
750 struct tstream_tls_writev_state);
751 struct tstream_tls *tlss =
752 tstream_context_data(state->stream,
756 tlss->write.req = NULL;
758 ret = tsocket_simple_int_recv(req, perrno);
763 tevent_req_received(req);
767 struct tstream_tls_disconnect_state {
771 static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
772 struct tevent_context *ev,
773 struct tstream_context *stream)
775 struct tstream_tls *tlss =
776 tstream_context_data(stream,
778 struct tevent_req *req;
779 struct tstream_tls_disconnect_state *state;
781 tlss->disconnect.req = NULL;
782 tlss->current_ev = ev;
784 req = tevent_req_create(mem_ctx, &state,
785 struct tstream_tls_disconnect_state);
790 if (tlss->error != 0) {
791 tevent_req_error(req, tlss->error);
792 return tevent_req_post(req, ev);
795 tlss->disconnect.req = req;
796 tstream_tls_retry_disconnect(stream);
797 if (!tevent_req_is_in_progress(req)) {
798 return tevent_req_post(req, ev);
804 static void tstream_tls_retry_disconnect(struct tstream_context *stream)
806 struct tstream_tls *tlss =
807 tstream_context_data(stream,
809 struct tevent_req *req = tlss->disconnect.req;
812 if (tlss->error != 0) {
813 tevent_req_error(req, tlss->error);
817 ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
818 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
822 tlss->disconnect.req = NULL;
824 if (gnutls_error_is_fatal(ret) != 0) {
825 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
827 tevent_req_error(req, tlss->error);
831 if (ret != GNUTLS_E_SUCCESS) {
832 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
834 tevent_req_error(req, tlss->error);
838 tevent_req_done(req);
841 static int tstream_tls_disconnect_recv(struct tevent_req *req,
846 ret = tsocket_simple_int_recv(req, perrno);
848 tevent_req_received(req);
852 static const struct tstream_context_ops tstream_tls_ops = {
855 .pending_bytes = tstream_tls_pending_bytes,
857 .readv_send = tstream_tls_readv_send,
858 .readv_recv = tstream_tls_readv_recv,
860 .writev_send = tstream_tls_writev_send,
861 .writev_recv = tstream_tls_writev_recv,
863 .disconnect_send = tstream_tls_disconnect_send,
864 .disconnect_recv = tstream_tls_disconnect_recv,
867 struct tstream_tls_params {
868 gnutls_certificate_credentials_t x509_cred;
869 gnutls_dh_params_t dh_params;
870 const char *tls_priority;
872 enum tls_verify_peer_state verify_peer;
873 const char *peer_name;
876 static int tstream_tls_params_destructor(struct tstream_tls_params *tlsp)
878 if (tlsp->x509_cred) {
879 gnutls_certificate_free_credentials(tlsp->x509_cred);
880 tlsp->x509_cred = NULL;
882 if (tlsp->dh_params) {
883 gnutls_dh_params_deinit(tlsp->dh_params);
884 tlsp->dh_params = NULL;
890 bool tstream_tls_params_enabled(struct tstream_tls_params *tlsp)
892 return tlsp->tls_enabled;
895 NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
897 const char *crl_file,
898 const char *tls_priority,
899 enum tls_verify_peer_state verify_peer,
900 const char *peer_name,
901 struct tstream_tls_params **_tlsp)
903 struct tstream_tls_params *tlsp;
906 tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
907 NT_STATUS_HAVE_NO_MEMORY(tlsp);
909 talloc_set_destructor(tlsp, tstream_tls_params_destructor);
911 tlsp->verify_peer = verify_peer;
912 if (peer_name != NULL) {
913 tlsp->peer_name = talloc_strdup(tlsp, peer_name);
914 if (tlsp->peer_name == NULL) {
916 return NT_STATUS_NO_MEMORY;
918 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
919 DEBUG(0,("TLS failed to missing peer_name - "
920 "with 'tls verify peer = %s'\n",
921 tls_verify_peer_string(tlsp->verify_peer)));
923 return NT_STATUS_INVALID_PARAMETER_MIX;
926 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
927 if (ret != GNUTLS_E_SUCCESS) {
928 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
930 return NT_STATUS_NO_MEMORY;
933 if (ca_file && *ca_file && file_exist(ca_file)) {
934 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
936 GNUTLS_X509_FMT_PEM);
938 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
939 ca_file, gnutls_strerror(ret)));
941 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
943 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
944 DEBUG(0,("TLS failed to missing cafile %s - "
945 "with 'tls verify peer = %s'\n",
947 tls_verify_peer_string(tlsp->verify_peer)));
949 return NT_STATUS_INVALID_PARAMETER_MIX;
952 if (crl_file && *crl_file && file_exist(crl_file)) {
953 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
955 GNUTLS_X509_FMT_PEM);
957 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
958 crl_file, gnutls_strerror(ret)));
960 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
962 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE) {
963 DEBUG(0,("TLS failed to missing crlfile %s - "
964 "with 'tls verify peer = %s'\n",
966 tls_verify_peer_string(tlsp->verify_peer)));
968 return NT_STATUS_INVALID_PARAMETER_MIX;
971 tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
972 if (tlsp->tls_priority == NULL) {
974 return NT_STATUS_NO_MEMORY;
977 tlsp->tls_enabled = true;
983 struct tstream_tls_connect_state {
984 struct tstream_context *tls_stream;
987 struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
988 struct tevent_context *ev,
989 struct tstream_context *plain_stream,
990 struct tstream_tls_params *tls_params,
991 const char *location)
993 struct tevent_req *req;
994 struct tstream_tls_connect_state *state;
995 const char *error_pos;
996 struct tstream_tls *tlss;
999 req = tevent_req_create(mem_ctx, &state,
1000 struct tstream_tls_connect_state);
1005 state->tls_stream = tstream_context_create(state,
1010 if (tevent_req_nomem(state->tls_stream, req)) {
1011 return tevent_req_post(req, ev);
1014 talloc_set_destructor(tlss, tstream_tls_destructor);
1016 tlss->plain_stream = plain_stream;
1017 tlss->verify_peer = tls_params->verify_peer;
1018 if (tls_params->peer_name != NULL) {
1019 tlss->peer_name = talloc_strdup(tlss, tls_params->peer_name);
1020 if (tevent_req_nomem(tlss->peer_name, req)) {
1021 return tevent_req_post(req, ev);
1025 tlss->current_ev = ev;
1026 tlss->retry_im = tevent_create_immediate(tlss);
1027 if (tevent_req_nomem(tlss->retry_im, req)) {
1028 return tevent_req_post(req, ev);
1031 ret = gnutls_init(&tlss->tls_session, GNUTLS_CLIENT);
1032 if (ret != GNUTLS_E_SUCCESS) {
1033 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1034 tevent_req_error(req, EINVAL);
1035 return tevent_req_post(req, ev);
1038 ret = gnutls_set_default_priority(tlss->tls_session);
1039 if (ret != GNUTLS_E_SUCCESS) {
1040 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1041 __location__, gnutls_strerror(ret));
1042 tevent_req_error(req, EINVAL);
1043 return tevent_req_post(req, ev);
1046 if (strlen(tls_params->tls_priority) > 0) {
1047 ret = gnutls_priority_set_direct(tlss->tls_session,
1048 tls_params->tls_priority,
1050 if (ret != GNUTLS_E_SUCCESS) {
1051 DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1052 __location__, gnutls_strerror(ret), error_pos));
1053 tevent_req_error(req, EINVAL);
1054 return tevent_req_post(req, ev);
1058 ret = gnutls_credentials_set(tlss->tls_session,
1059 GNUTLS_CRD_CERTIFICATE,
1060 tls_params->x509_cred);
1061 if (ret != GNUTLS_E_SUCCESS) {
1062 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1063 tevent_req_error(req, EINVAL);
1064 return tevent_req_post(req, ev);
1067 gnutls_transport_set_ptr(tlss->tls_session,
1068 (gnutls_transport_ptr_t)state->tls_stream);
1069 gnutls_transport_set_pull_function(tlss->tls_session,
1070 (gnutls_pull_func)tstream_tls_pull_function);
1071 gnutls_transport_set_push_function(tlss->tls_session,
1072 (gnutls_push_func)tstream_tls_push_function);
1074 tlss->handshake.req = req;
1075 tstream_tls_retry_handshake(state->tls_stream);
1076 if (!tevent_req_is_in_progress(req)) {
1077 return tevent_req_post(req, ev);
1083 int tstream_tls_connect_recv(struct tevent_req *req,
1085 TALLOC_CTX *mem_ctx,
1086 struct tstream_context **tls_stream)
1088 struct tstream_tls_connect_state *state =
1089 tevent_req_data(req,
1090 struct tstream_tls_connect_state);
1092 if (tevent_req_is_unix_error(req, perrno)) {
1093 tevent_req_received(req);
1097 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1098 tevent_req_received(req);
1103 initialise global tls state
1105 NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
1106 const char *dns_host_name,
1108 const char *key_file,
1109 const char *cert_file,
1110 const char *ca_file,
1111 const char *crl_file,
1112 const char *dhp_file,
1113 const char *tls_priority,
1114 struct tstream_tls_params **_tlsp)
1116 struct tstream_tls_params *tlsp;
1120 if (!enabled || key_file == NULL || *key_file == 0) {
1121 tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1122 NT_STATUS_HAVE_NO_MEMORY(tlsp);
1123 talloc_set_destructor(tlsp, tstream_tls_params_destructor);
1124 tlsp->tls_enabled = false;
1127 return NT_STATUS_OK;
1130 tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1131 NT_STATUS_HAVE_NO_MEMORY(tlsp);
1133 talloc_set_destructor(tlsp, tstream_tls_params_destructor);
1135 if (!file_exist(ca_file)) {
1136 tls_cert_generate(tlsp, dns_host_name,
1137 key_file, cert_file, ca_file);
1140 if (file_exist(key_file) &&
1141 !file_check_permissions(key_file, geteuid(), 0600, &st))
1143 DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
1144 "owner uid %u should be %u, mode 0%o should be 0%o\n"
1145 "This is known as CVE-2013-4476.\n"
1146 "Removing all tls .pem files will cause an "
1147 "auto-regeneration with the correct permissions.\n",
1149 (unsigned int)st.st_uid, geteuid(),
1150 (unsigned int)(st.st_mode & 0777), 0600));
1151 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1154 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
1155 if (ret != GNUTLS_E_SUCCESS) {
1156 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1158 return NT_STATUS_NO_MEMORY;
1161 if (ca_file && *ca_file) {
1162 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1164 GNUTLS_X509_FMT_PEM);
1166 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1167 ca_file, gnutls_strerror(ret)));
1169 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1173 if (crl_file && *crl_file) {
1174 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1176 GNUTLS_X509_FMT_PEM);
1178 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1179 crl_file, gnutls_strerror(ret)));
1181 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1185 ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
1186 cert_file, key_file,
1187 GNUTLS_X509_FMT_PEM);
1188 if (ret != GNUTLS_E_SUCCESS) {
1189 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1190 cert_file, key_file, gnutls_strerror(ret)));
1192 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1195 ret = gnutls_dh_params_init(&tlsp->dh_params);
1196 if (ret != GNUTLS_E_SUCCESS) {
1197 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1199 return NT_STATUS_NO_MEMORY;
1202 if (dhp_file && *dhp_file) {
1203 gnutls_datum_t dhparms;
1206 dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
1208 if (!dhparms.data) {
1209 DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1210 dhp_file, errno, strerror(errno)));
1212 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1214 dhparms.size = size;
1216 ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
1218 GNUTLS_X509_FMT_PEM);
1219 if (ret != GNUTLS_E_SUCCESS) {
1220 DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1221 dhp_file, gnutls_strerror(ret)));
1223 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1226 ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
1227 if (ret != GNUTLS_E_SUCCESS) {
1228 DEBUG(0,("TLS failed to generate dh_params - %s\n",
1229 gnutls_strerror(ret)));
1231 return NT_STATUS_INTERNAL_ERROR;
1235 gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
1237 tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
1238 if (tlsp->tls_priority == NULL) {
1240 return NT_STATUS_NO_MEMORY;
1243 tlsp->tls_enabled = true;
1246 return NT_STATUS_OK;
1249 struct tstream_tls_accept_state {
1250 struct tstream_context *tls_stream;
1253 struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
1254 struct tevent_context *ev,
1255 struct tstream_context *plain_stream,
1256 struct tstream_tls_params *tlsp,
1257 const char *location)
1259 struct tevent_req *req;
1260 struct tstream_tls_accept_state *state;
1261 struct tstream_tls *tlss;
1262 const char *error_pos;
1265 req = tevent_req_create(mem_ctx, &state,
1266 struct tstream_tls_accept_state);
1271 state->tls_stream = tstream_context_create(state,
1276 if (tevent_req_nomem(state->tls_stream, req)) {
1277 return tevent_req_post(req, ev);
1280 talloc_set_destructor(tlss, tstream_tls_destructor);
1282 tlss->plain_stream = plain_stream;
1284 tlss->current_ev = ev;
1285 tlss->retry_im = tevent_create_immediate(tlss);
1286 if (tevent_req_nomem(tlss->retry_im, req)) {
1287 return tevent_req_post(req, ev);
1290 ret = gnutls_init(&tlss->tls_session, GNUTLS_SERVER);
1291 if (ret != GNUTLS_E_SUCCESS) {
1292 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1293 tevent_req_error(req, EINVAL);
1294 return tevent_req_post(req, ev);
1297 ret = gnutls_set_default_priority(tlss->tls_session);
1298 if (ret != GNUTLS_E_SUCCESS) {
1299 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1300 __location__, gnutls_strerror(ret));
1301 tevent_req_error(req, EINVAL);
1302 return tevent_req_post(req, ev);
1305 if (strlen(tlsp->tls_priority) > 0) {
1306 ret = gnutls_priority_set_direct(tlss->tls_session,
1309 if (ret != GNUTLS_E_SUCCESS) {
1310 DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1311 __location__, gnutls_strerror(ret), error_pos));
1312 tevent_req_error(req, EINVAL);
1313 return tevent_req_post(req, ev);
1317 ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE,
1319 if (ret != GNUTLS_E_SUCCESS) {
1320 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1321 tevent_req_error(req, EINVAL);
1322 return tevent_req_post(req, ev);
1325 gnutls_certificate_server_set_request(tlss->tls_session,
1326 GNUTLS_CERT_REQUEST);
1327 gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
1329 gnutls_transport_set_ptr(tlss->tls_session,
1330 (gnutls_transport_ptr_t)state->tls_stream);
1331 gnutls_transport_set_pull_function(tlss->tls_session,
1332 (gnutls_pull_func)tstream_tls_pull_function);
1333 gnutls_transport_set_push_function(tlss->tls_session,
1334 (gnutls_push_func)tstream_tls_push_function);
1336 tlss->handshake.req = req;
1337 tstream_tls_retry_handshake(state->tls_stream);
1338 if (!tevent_req_is_in_progress(req)) {
1339 return tevent_req_post(req, ev);
1345 static void tstream_tls_retry_handshake(struct tstream_context *stream)
1347 struct tstream_tls *tlss =
1348 tstream_context_data(stream,
1349 struct tstream_tls);
1350 struct tevent_req *req = tlss->handshake.req;
1353 if (tlss->error != 0) {
1354 tevent_req_error(req, tlss->error);
1358 ret = gnutls_handshake(tlss->tls_session);
1359 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
1363 tlss->handshake.req = NULL;
1365 if (gnutls_error_is_fatal(ret) != 0) {
1366 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1368 tevent_req_error(req, tlss->error);
1372 if (ret != GNUTLS_E_SUCCESS) {
1373 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1375 tevent_req_error(req, tlss->error);
1379 if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
1380 unsigned int status = UINT32_MAX;
1382 const char *hostname = NULL;
1384 if (tlss->peer_name != NULL) {
1385 ip = is_ipaddress(tlss->peer_name);
1389 hostname = tlss->peer_name;
1392 if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
1396 if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
1397 if (hostname == NULL) {
1398 DEBUG(1,("TLS %s - no hostname available for "
1399 "verify_peer[%s] and peer_name[%s]\n",
1401 tls_verify_peer_string(tlss->verify_peer),
1403 tlss->error = EINVAL;
1404 tevent_req_error(req, tlss->error);
1409 ret = gnutls_certificate_verify_peers3(tlss->tls_session,
1412 if (ret != GNUTLS_E_SUCCESS) {
1413 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1415 tevent_req_error(req, tlss->error);
1420 DEBUG(1,("TLS %s - check failed for "
1421 "verify_peer[%s] and peer_name[%s] "
1422 "status 0x%x (%s%s%s%s%s%s%s%s)\n",
1424 tls_verify_peer_string(tlss->verify_peer),
1427 status & GNUTLS_CERT_INVALID ? "invalid " : "",
1428 status & GNUTLS_CERT_REVOKED ? "revoked " : "",
1429 status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
1430 "signer_not_found " : "",
1431 status & GNUTLS_CERT_SIGNER_NOT_CA ?
1432 "signer_not_ca " : "",
1433 status & GNUTLS_CERT_INSECURE_ALGORITHM ?
1434 "insecure_algorithm " : "",
1435 status & GNUTLS_CERT_NOT_ACTIVATED ?
1436 "not_activated " : "",
1437 status & GNUTLS_CERT_EXPIRED ?
1439 status & GNUTLS_CERT_UNEXPECTED_OWNER ?
1440 "unexptected_owner " : ""));
1441 tlss->error = EINVAL;
1442 tevent_req_error(req, tlss->error);
1447 tevent_req_done(req);
1450 int tstream_tls_accept_recv(struct tevent_req *req,
1452 TALLOC_CTX *mem_ctx,
1453 struct tstream_context **tls_stream)
1455 struct tstream_tls_accept_state *state =
1456 tevent_req_data(req,
1457 struct tstream_tls_accept_state);
1459 if (tevent_req_is_unix_error(req, perrno)) {
1460 tevent_req_received(req);
1464 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1465 tevent_req_received(req);