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 "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>
33 #include "lib/crypto/gnutls_helpers.h"
37 const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer)
39 switch (verify_peer) {
40 case TLS_VERIFY_PEER_NO_CHECK:
41 return TLS_VERIFY_PEER_NO_CHECK_STRING;
43 case TLS_VERIFY_PEER_CA_ONLY:
44 return TLS_VERIFY_PEER_CA_ONLY_STRING;
46 case TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE:
47 return TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING;
49 case TLS_VERIFY_PEER_CA_AND_NAME:
50 return TLS_VERIFY_PEER_CA_AND_NAME_STRING;
52 case TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE:
53 return TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING;
56 return "unknown tls_verify_peer_state";
59 static const struct tstream_context_ops tstream_tls_ops;
62 struct tstream_context *plain_stream;
65 gnutls_session_t tls_session;
69 enum tls_verify_peer_state verify_peer;
70 const char *peer_name;
72 struct tevent_context *current_ev;
74 struct tevent_immediate *retry_im;
77 struct tevent_req *mgmt_req;
84 struct tevent_req *subreq;
90 struct tevent_req *subreq;
94 struct tevent_req *req;
100 uint8_t buffer[1024];
101 struct tevent_req *req;
107 uint8_t buffer[1024];
108 struct tevent_req *req;
112 struct tevent_req *req;
116 static void tstream_tls_retry_handshake(struct tstream_context *stream);
117 static void tstream_tls_retry_read(struct tstream_context *stream);
118 static void tstream_tls_retry_write(struct tstream_context *stream);
119 static void tstream_tls_retry_disconnect(struct tstream_context *stream);
120 static void tstream_tls_retry_trigger(struct tevent_context *ctx,
121 struct tevent_immediate *im,
124 static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
127 struct tstream_tls *tlss =
128 tstream_context_data(stream,
131 if (tlss->push.subreq == NULL && tlss->pull.subreq == NULL) {
132 if (tlss->waiting_flush.mgmt_req != NULL) {
133 struct tevent_req *req = tlss->waiting_flush.mgmt_req;
135 tlss->waiting_flush.mgmt_req = NULL;
137 tevent_req_done(req);
142 if (tlss->disconnect.req) {
143 tstream_tls_retry_disconnect(stream);
147 if (tlss->handshake.req) {
148 tstream_tls_retry_handshake(stream);
152 if (tlss->write.req && tlss->read.req && !deferred) {
153 tevent_schedule_immediate(tlss->retry_im, tlss->current_ev,
154 tstream_tls_retry_trigger,
158 if (tlss->write.req) {
159 tstream_tls_retry_write(stream);
163 if (tlss->read.req) {
164 tstream_tls_retry_read(stream);
169 static void tstream_tls_retry_trigger(struct tevent_context *ctx,
170 struct tevent_immediate *im,
173 struct tstream_context *stream =
174 talloc_get_type_abort(private_data,
175 struct tstream_context);
177 tstream_tls_retry(stream, true);
180 static void tstream_tls_push_done(struct tevent_req *subreq);
182 static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
183 const void *buf, size_t size)
185 struct tstream_context *stream =
186 talloc_get_type_abort(ptr,
187 struct tstream_context);
188 struct tstream_tls *tlss =
189 tstream_context_data(stream,
191 struct tevent_req *subreq = NULL;
195 if (tlss->error != 0) {
200 if (tlss->push.subreq) {
205 len = MIN(size, UINT16_MAX - tlss->push.ofs);
212 nbuf = talloc_realloc(tlss, tlss->push.buf,
213 uint8_t, tlss->push.ofs + len);
215 if (tlss->push.buf) {
222 tlss->push.buf = nbuf;
224 memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
225 tlss->push.ofs += len;
227 tlss->push.iov.iov_base = (char *)tlss->push.buf;
228 tlss->push.iov.iov_len = tlss->push.ofs;
230 subreq = tstream_writev_send(tlss,
234 if (subreq == NULL) {
238 tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
240 tlss->push.subreq = subreq;
244 static void tstream_tls_push_done(struct tevent_req *subreq)
246 struct tstream_context *stream =
247 tevent_req_callback_data(subreq,
248 struct tstream_context);
249 struct tstream_tls *tlss =
250 tstream_context_data(stream,
255 tlss->push.subreq = NULL;
256 ZERO_STRUCT(tlss->push.iov);
257 TALLOC_FREE(tlss->push.buf);
260 ret = tstream_writev_recv(subreq, &sys_errno);
263 tlss->error = sys_errno;
264 tstream_tls_retry(stream, false);
268 tstream_tls_retry(stream, false);
271 static void tstream_tls_pull_done(struct tevent_req *subreq);
273 static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
274 void *buf, size_t size)
276 struct tstream_context *stream =
277 talloc_get_type_abort(ptr,
278 struct tstream_context);
279 struct tstream_tls *tlss =
280 tstream_context_data(stream,
282 struct tevent_req *subreq;
285 if (tlss->error != 0) {
290 if (tlss->pull.subreq) {
295 if (tlss->pull.iov.iov_base) {
299 b = (uint8_t *)tlss->pull.iov.iov_base;
301 n = MIN(tlss->pull.iov.iov_len, size);
304 tlss->pull.iov.iov_len -= n;
306 tlss->pull.iov.iov_base = (char *)b;
307 if (tlss->pull.iov.iov_len == 0) {
308 tlss->pull.iov.iov_base = NULL;
309 TALLOC_FREE(tlss->pull.buf);
319 len = MIN(size, UINT16_MAX);
321 tlss->pull.buf = talloc_array(tlss, uint8_t, len);
322 if (tlss->pull.buf == NULL) {
326 tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
327 tlss->pull.iov.iov_len = len;
329 subreq = tstream_readv_send(tlss,
333 if (subreq == NULL) {
337 tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
339 tlss->pull.subreq = subreq;
344 static void tstream_tls_pull_done(struct tevent_req *subreq)
346 struct tstream_context *stream =
347 tevent_req_callback_data(subreq,
348 struct tstream_context);
349 struct tstream_tls *tlss =
350 tstream_context_data(stream,
355 tlss->pull.subreq = NULL;
357 ret = tstream_readv_recv(subreq, &sys_errno);
360 tlss->error = sys_errno;
361 tstream_tls_retry(stream, false);
365 tstream_tls_retry(stream, false);
368 static int tstream_tls_destructor(struct tstream_tls *tlss)
370 if (tlss->tls_session) {
371 gnutls_deinit(tlss->tls_session);
372 tlss->tls_session = NULL;
378 static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
380 struct tstream_tls *tlss =
381 tstream_context_data(stream,
385 if (tlss->error != 0) {
390 ret = gnutls_record_check_pending(tlss->tls_session);
391 ret += tlss->read.left;
396 struct tstream_tls_readv_state {
397 struct tstream_context *stream;
399 struct iovec *vector;
405 static void tstream_tls_readv_crypt_next(struct tevent_req *req);
407 static struct tevent_req *tstream_tls_readv_send(TALLOC_CTX *mem_ctx,
408 struct tevent_context *ev,
409 struct tstream_context *stream,
410 struct iovec *vector,
413 struct tstream_tls *tlss =
414 tstream_context_data(stream,
416 struct tevent_req *req;
417 struct tstream_tls_readv_state *state;
419 tlss->read.req = NULL;
421 if (tlss->current_ev != ev) {
422 SMB_ASSERT(tlss->push.subreq == NULL);
423 SMB_ASSERT(tlss->pull.subreq == NULL);
426 tlss->current_ev = ev;
428 req = tevent_req_create(mem_ctx, &state,
429 struct tstream_tls_readv_state);
434 state->stream = stream;
437 if (tlss->error != 0) {
438 tevent_req_error(req, tlss->error);
439 return tevent_req_post(req, ev);
443 * we make a copy of the vector so we can change the structure
445 state->vector = talloc_array(state, struct iovec, count);
446 if (tevent_req_nomem(state->vector, req)) {
447 return tevent_req_post(req, ev);
449 memcpy(state->vector, vector, sizeof(struct iovec) * count);
450 state->count = count;
452 tstream_tls_readv_crypt_next(req);
453 if (!tevent_req_is_in_progress(req)) {
454 return tevent_req_post(req, ev);
460 static void tstream_tls_readv_crypt_next(struct tevent_req *req)
462 struct tstream_tls_readv_state *state =
464 struct tstream_tls_readv_state);
465 struct tstream_tls *tlss =
466 tstream_context_data(state->stream,
470 * copy the pending buffer first
472 while (tlss->read.left > 0 && state->count > 0) {
473 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
474 size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
476 memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
479 state->vector[0].iov_base = (char *) base;
480 state->vector[0].iov_len -= len;
482 tlss->read.ofs += len;
483 tlss->read.left -= len;
485 if (state->vector[0].iov_len == 0) {
493 if (state->count == 0) {
494 tevent_req_done(req);
498 tlss->read.req = req;
499 tstream_tls_retry_read(state->stream);
502 static void tstream_tls_retry_read(struct tstream_context *stream)
504 struct tstream_tls *tlss =
505 tstream_context_data(stream,
507 struct tevent_req *req = tlss->read.req;
510 if (tlss->error != 0) {
511 tevent_req_error(req, tlss->error);
518 ret = gnutls_record_recv(tlss->tls_session,
520 sizeof(tlss->read.buffer));
521 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
525 tlss->read.req = NULL;
527 if (gnutls_error_is_fatal(ret) != 0) {
528 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
530 tevent_req_error(req, tlss->error);
536 tevent_req_error(req, tlss->error);
540 tlss->read.left = ret;
541 tstream_tls_readv_crypt_next(req);
544 static int tstream_tls_readv_recv(struct tevent_req *req,
547 struct tstream_tls_readv_state *state =
549 struct tstream_tls_readv_state);
550 struct tstream_tls *tlss =
551 tstream_context_data(state->stream,
555 tlss->read.req = NULL;
557 ret = tsocket_simple_int_recv(req, perrno);
562 tevent_req_received(req);
566 struct tstream_tls_writev_state {
567 struct tstream_context *stream;
569 struct iovec *vector;
575 static void tstream_tls_writev_crypt_next(struct tevent_req *req);
577 static struct tevent_req *tstream_tls_writev_send(TALLOC_CTX *mem_ctx,
578 struct tevent_context *ev,
579 struct tstream_context *stream,
580 const struct iovec *vector,
583 struct tstream_tls *tlss =
584 tstream_context_data(stream,
586 struct tevent_req *req;
587 struct tstream_tls_writev_state *state;
589 tlss->write.req = NULL;
591 if (tlss->current_ev != ev) {
592 SMB_ASSERT(tlss->push.subreq == NULL);
593 SMB_ASSERT(tlss->pull.subreq == NULL);
596 tlss->current_ev = ev;
598 req = tevent_req_create(mem_ctx, &state,
599 struct tstream_tls_writev_state);
604 state->stream = stream;
607 if (tlss->error != 0) {
608 tevent_req_error(req, tlss->error);
609 return tevent_req_post(req, ev);
613 * we make a copy of the vector so we can change the structure
615 state->vector = talloc_array(state, struct iovec, count);
616 if (tevent_req_nomem(state->vector, req)) {
617 return tevent_req_post(req, ev);
619 memcpy(state->vector, vector, sizeof(struct iovec) * count);
620 state->count = count;
622 tstream_tls_writev_crypt_next(req);
623 if (!tevent_req_is_in_progress(req)) {
624 return tevent_req_post(req, ev);
630 static void tstream_tls_writev_crypt_next(struct tevent_req *req)
632 struct tstream_tls_writev_state *state =
634 struct tstream_tls_writev_state);
635 struct tstream_tls *tlss =
636 tstream_context_data(state->stream,
639 tlss->write.left = sizeof(tlss->write.buffer);
643 * first fill our buffer
645 while (tlss->write.left > 0 && state->count > 0) {
646 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
647 size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
649 memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
652 state->vector[0].iov_base = (char *) base;
653 state->vector[0].iov_len -= len;
655 tlss->write.ofs += len;
656 tlss->write.left -= len;
658 if (state->vector[0].iov_len == 0) {
666 if (tlss->write.ofs == 0) {
667 tevent_req_done(req);
671 tlss->write.left = tlss->write.ofs;
674 tlss->write.req = req;
675 tstream_tls_retry_write(state->stream);
678 static void tstream_tls_retry_write(struct tstream_context *stream)
680 struct tstream_tls *tlss =
681 tstream_context_data(stream,
683 struct tevent_req *req = tlss->write.req;
686 if (tlss->error != 0) {
687 tevent_req_error(req, tlss->error);
691 ret = gnutls_record_send(tlss->tls_session,
692 tlss->write.buffer + tlss->write.ofs,
694 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
698 tlss->write.req = NULL;
700 if (gnutls_error_is_fatal(ret) != 0) {
701 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
703 tevent_req_error(req, tlss->error);
709 tevent_req_error(req, tlss->error);
713 tlss->write.ofs += ret;
714 tlss->write.left -= ret;
716 if (tlss->write.left > 0) {
717 tlss->write.req = req;
718 tstream_tls_retry_write(stream);
722 tstream_tls_writev_crypt_next(req);
725 static int tstream_tls_writev_recv(struct tevent_req *req,
728 struct tstream_tls_writev_state *state =
730 struct tstream_tls_writev_state);
731 struct tstream_tls *tlss =
732 tstream_context_data(state->stream,
736 tlss->write.req = NULL;
738 ret = tsocket_simple_int_recv(req, perrno);
743 tevent_req_received(req);
747 struct tstream_tls_disconnect_state {
751 static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
752 struct tevent_context *ev,
753 struct tstream_context *stream)
755 struct tstream_tls *tlss =
756 tstream_context_data(stream,
758 struct tevent_req *req;
759 struct tstream_tls_disconnect_state *state;
761 tlss->disconnect.req = NULL;
763 if (tlss->current_ev != ev) {
764 SMB_ASSERT(tlss->push.subreq == NULL);
765 SMB_ASSERT(tlss->pull.subreq == NULL);
768 tlss->current_ev = ev;
770 req = tevent_req_create(mem_ctx, &state,
771 struct tstream_tls_disconnect_state);
776 if (tlss->error != 0) {
777 tevent_req_error(req, tlss->error);
778 return tevent_req_post(req, ev);
781 tlss->disconnect.req = req;
782 tstream_tls_retry_disconnect(stream);
783 if (!tevent_req_is_in_progress(req)) {
784 return tevent_req_post(req, ev);
790 static void tstream_tls_retry_disconnect(struct tstream_context *stream)
792 struct tstream_tls *tlss =
793 tstream_context_data(stream,
795 struct tevent_req *req = tlss->disconnect.req;
798 if (tlss->error != 0) {
799 tevent_req_error(req, tlss->error);
803 ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
804 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
808 tlss->disconnect.req = NULL;
810 if (gnutls_error_is_fatal(ret) != 0) {
811 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
813 tevent_req_error(req, tlss->error);
817 if (ret != GNUTLS_E_SUCCESS) {
818 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
820 tevent_req_error(req, tlss->error);
824 if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
825 tlss->waiting_flush.mgmt_req = req;
829 tevent_req_done(req);
832 static int tstream_tls_disconnect_recv(struct tevent_req *req,
837 ret = tsocket_simple_int_recv(req, perrno);
839 tevent_req_received(req);
843 static const struct tstream_context_ops tstream_tls_ops = {
846 .pending_bytes = tstream_tls_pending_bytes,
848 .readv_send = tstream_tls_readv_send,
849 .readv_recv = tstream_tls_readv_recv,
851 .writev_send = tstream_tls_writev_send,
852 .writev_recv = tstream_tls_writev_recv,
854 .disconnect_send = tstream_tls_disconnect_send,
855 .disconnect_recv = tstream_tls_disconnect_recv,
858 struct tstream_tls_params_internal {
859 gnutls_certificate_credentials_t x509_cred;
860 gnutls_dh_params_t dh_params;
861 const char *tls_priority;
863 enum tls_verify_peer_state verify_peer;
864 const char *peer_name;
867 struct tstream_tls_params {
868 struct tstream_tls_params_internal *internal;
871 static int tstream_tls_params_internal_destructor(struct tstream_tls_params_internal *tlsp)
873 if (tlsp->x509_cred) {
874 gnutls_certificate_free_credentials(tlsp->x509_cred);
875 tlsp->x509_cred = NULL;
877 if (tlsp->dh_params) {
878 gnutls_dh_params_deinit(tlsp->dh_params);
879 tlsp->dh_params = NULL;
885 bool tstream_tls_params_enabled(struct tstream_tls_params *tls_params)
887 struct tstream_tls_params_internal *tlsp = tls_params->internal;
889 return tlsp->tls_enabled;
892 NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
894 const char *crl_file,
895 const char *tls_priority,
896 enum tls_verify_peer_state verify_peer,
897 const char *peer_name,
898 struct tstream_tls_params **_tlsp)
900 struct tstream_tls_params *__tlsp = NULL;
901 struct tstream_tls_params_internal *tlsp = NULL;
904 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
905 if (__tlsp == NULL) {
906 return NT_STATUS_NO_MEMORY;
909 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
912 return NT_STATUS_NO_MEMORY;
914 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
915 __tlsp->internal = tlsp;
917 tlsp->verify_peer = verify_peer;
918 if (peer_name != NULL) {
919 tlsp->peer_name = talloc_strdup(tlsp, peer_name);
920 if (tlsp->peer_name == NULL) {
922 return NT_STATUS_NO_MEMORY;
924 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
925 DEBUG(0,("TLS failed to missing peer_name - "
926 "with 'tls verify peer = %s'\n",
927 tls_verify_peer_string(tlsp->verify_peer)));
929 return NT_STATUS_INVALID_PARAMETER_MIX;
932 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
933 if (ret != GNUTLS_E_SUCCESS) {
934 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
936 return NT_STATUS_NO_MEMORY;
939 if (ca_file && *ca_file && file_exist(ca_file)) {
940 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
942 GNUTLS_X509_FMT_PEM);
944 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
945 ca_file, gnutls_strerror(ret)));
947 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
949 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
950 DEBUG(0,("TLS failed to missing cafile %s - "
951 "with 'tls verify peer = %s'\n",
953 tls_verify_peer_string(tlsp->verify_peer)));
955 return NT_STATUS_INVALID_PARAMETER_MIX;
958 if (crl_file && *crl_file && file_exist(crl_file)) {
959 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
961 GNUTLS_X509_FMT_PEM);
963 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
964 crl_file, gnutls_strerror(ret)));
966 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
968 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE) {
969 DEBUG(0,("TLS failed to missing crlfile %s - "
970 "with 'tls verify peer = %s'\n",
972 tls_verify_peer_string(tlsp->verify_peer)));
974 return NT_STATUS_INVALID_PARAMETER_MIX;
977 tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
978 if (tlsp->tls_priority == NULL) {
980 return NT_STATUS_NO_MEMORY;
983 tlsp->tls_enabled = true;
989 static NTSTATUS tstream_tls_prepare_gnutls(struct tstream_tls_params *_tlsp,
990 struct tstream_tls *tlss)
992 struct tstream_tls_params_internal *tlsp = NULL;
995 const char *hostname = NULL;
997 if (tlss->is_server) {
998 flags = GNUTLS_SERVER;
1000 flags = GNUTLS_CLIENT;
1002 * tls_tstream can't properly handle 'New Session Ticket'
1003 * messages sent 'after' the client sends the 'Finished'
1004 * message. GNUTLS_NO_TICKETS was introduced in GnuTLS 3.5.6.
1005 * This flag is to indicate the session Flag session should not
1006 * use resumption with session tickets.
1008 flags |= GNUTLS_NO_TICKETS;
1012 * Note we need to make sure x509_cred and dh_params
1013 * from tstream_tls_params_internal stay alive for
1014 * the whole lifetime of this session!
1016 * See 'man gnutls_credentials_set' and
1017 * 'man gnutls_certificate_set_dh_params'.
1019 * Note: here we use talloc_reference() in a way
1020 * that does not expose it to the caller.
1022 tlsp = talloc_reference(tlss, _tlsp->internal);
1024 return NT_STATUS_NO_MEMORY;
1027 tlss->verify_peer = tlsp->verify_peer;
1028 if (tlsp->peer_name != NULL) {
1029 bool ip = is_ipaddress(tlsp->peer_name);
1031 tlss->peer_name = talloc_strdup(tlss, tlsp->peer_name);
1032 if (tlss->peer_name == NULL) {
1033 return NT_STATUS_NO_MEMORY;
1037 hostname = tlss->peer_name;
1040 if (tlss->verify_peer < TLS_VERIFY_PEER_CA_AND_NAME) {
1045 if (tlss->current_ev != NULL) {
1046 tlss->retry_im = tevent_create_immediate(tlss);
1047 if (tlss->retry_im == NULL) {
1048 return NT_STATUS_NO_MEMORY;
1052 ret = gnutls_init(&tlss->tls_session, flags);
1053 if (ret != GNUTLS_E_SUCCESS) {
1054 return gnutls_error_to_ntstatus(ret,
1055 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1058 ret = gnutls_set_default_priority(tlss->tls_session);
1059 if (ret != GNUTLS_E_SUCCESS) {
1060 return gnutls_error_to_ntstatus(ret,
1061 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1064 if (strlen(tlsp->tls_priority) > 0) {
1065 const char *error_pos = NULL;
1067 ret = gnutls_priority_set_direct(tlss->tls_session,
1070 if (ret != GNUTLS_E_SUCCESS) {
1071 return gnutls_error_to_ntstatus(ret,
1072 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1076 ret = gnutls_credentials_set(tlss->tls_session,
1077 GNUTLS_CRD_CERTIFICATE,
1079 if (ret != GNUTLS_E_SUCCESS) {
1080 return gnutls_error_to_ntstatus(ret,
1081 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1084 if (hostname != NULL) {
1085 ret = gnutls_server_name_set(tlss->tls_session,
1089 if (ret != GNUTLS_E_SUCCESS) {
1090 return gnutls_error_to_ntstatus(ret,
1091 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1095 if (tlss->is_server) {
1096 gnutls_certificate_server_set_request(tlss->tls_session,
1097 GNUTLS_CERT_REQUEST);
1098 gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
1101 return NT_STATUS_OK;
1104 static NTSTATUS tstream_tls_verify_peer(struct tstream_tls *tlss)
1106 unsigned int status = UINT32_MAX;
1108 const char *hostname = NULL;
1111 if (tlss->verify_peer == TLS_VERIFY_PEER_NO_CHECK) {
1112 return NT_STATUS_OK;
1115 if (tlss->peer_name != NULL) {
1116 ip = is_ipaddress(tlss->peer_name);
1120 hostname = tlss->peer_name;
1123 if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
1127 if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
1128 if (hostname == NULL) {
1129 DEBUG(1,("TLS %s - no hostname available for "
1130 "verify_peer[%s] and peer_name[%s]\n",
1132 tls_verify_peer_string(tlss->verify_peer),
1134 return NT_STATUS_IMAGE_CERT_REVOKED;
1138 ret = gnutls_certificate_verify_peers3(tlss->tls_session,
1141 if (ret != GNUTLS_E_SUCCESS) {
1142 return gnutls_error_to_ntstatus(ret,
1143 NT_STATUS_CRYPTO_SYSTEM_INVALID);
1147 DEBUG(1,("TLS %s - check failed for "
1148 "verify_peer[%s] and peer_name[%s] "
1149 "status 0x%x (%s%s%s%s%s%s%s%s)\n",
1151 tls_verify_peer_string(tlss->verify_peer),
1154 status & GNUTLS_CERT_INVALID ? "invalid " : "",
1155 status & GNUTLS_CERT_REVOKED ? "revoked " : "",
1156 status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
1157 "signer_not_found " : "",
1158 status & GNUTLS_CERT_SIGNER_NOT_CA ?
1159 "signer_not_ca " : "",
1160 status & GNUTLS_CERT_INSECURE_ALGORITHM ?
1161 "insecure_algorithm " : "",
1162 status & GNUTLS_CERT_NOT_ACTIVATED ?
1163 "not_activated " : "",
1164 status & GNUTLS_CERT_EXPIRED ?
1166 status & GNUTLS_CERT_UNEXPECTED_OWNER ?
1167 "unexpected_owner " : ""));
1168 return NT_STATUS_IMAGE_CERT_REVOKED;
1171 return NT_STATUS_OK;
1174 struct tstream_tls_connect_state {
1175 struct tstream_context *tls_stream;
1178 struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
1179 struct tevent_context *ev,
1180 struct tstream_context *plain_stream,
1181 struct tstream_tls_params *_tls_params,
1182 const char *location)
1184 struct tevent_req *req;
1185 struct tstream_tls_connect_state *state;
1186 struct tstream_tls *tlss;
1189 req = tevent_req_create(mem_ctx, &state,
1190 struct tstream_tls_connect_state);
1195 state->tls_stream = tstream_context_create(state,
1200 if (tevent_req_nomem(state->tls_stream, req)) {
1201 return tevent_req_post(req, ev);
1204 talloc_set_destructor(tlss, tstream_tls_destructor);
1205 tlss->plain_stream = plain_stream;
1206 tlss->is_server = false;
1207 tlss->current_ev = ev;
1209 status = tstream_tls_prepare_gnutls(_tls_params, tlss);
1210 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1211 tevent_req_oom(req);
1212 return tevent_req_post(req, ev);
1214 if (!NT_STATUS_IS_OK(status)) {
1215 tevent_req_error(req, EINVAL);
1216 return tevent_req_post(req, ev);
1219 gnutls_transport_set_ptr(tlss->tls_session,
1220 (gnutls_transport_ptr_t)state->tls_stream);
1221 gnutls_transport_set_pull_function(tlss->tls_session,
1222 (gnutls_pull_func)tstream_tls_pull_function);
1223 gnutls_transport_set_push_function(tlss->tls_session,
1224 (gnutls_push_func)tstream_tls_push_function);
1226 tlss->handshake.req = req;
1227 tstream_tls_retry_handshake(state->tls_stream);
1228 if (!tevent_req_is_in_progress(req)) {
1229 return tevent_req_post(req, ev);
1235 int tstream_tls_connect_recv(struct tevent_req *req,
1237 TALLOC_CTX *mem_ctx,
1238 struct tstream_context **tls_stream)
1240 struct tstream_tls_connect_state *state =
1241 tevent_req_data(req,
1242 struct tstream_tls_connect_state);
1244 if (tevent_req_is_unix_error(req, perrno)) {
1245 tevent_req_received(req);
1249 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1250 tevent_req_received(req);
1255 initialise global tls state
1257 NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
1258 const char *dns_host_name,
1260 const char *key_file,
1261 const char *cert_file,
1262 const char *ca_file,
1263 const char *crl_file,
1264 const char *dhp_file,
1265 const char *tls_priority,
1266 struct tstream_tls_params **_tlsp)
1268 struct tstream_tls_params *__tlsp = NULL;
1269 struct tstream_tls_params_internal *tlsp = NULL;
1273 if (!enabled || key_file == NULL || *key_file == 0) {
1274 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1275 if (__tlsp == NULL) {
1276 return NT_STATUS_NO_MEMORY;
1279 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1281 TALLOC_FREE(__tlsp);
1282 return NT_STATUS_NO_MEMORY;
1285 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1286 __tlsp->internal = tlsp;
1287 tlsp->tls_enabled = false;
1290 return NT_STATUS_OK;
1293 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1294 if (__tlsp == NULL) {
1295 return NT_STATUS_NO_MEMORY;
1298 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1300 TALLOC_FREE(__tlsp);
1301 return NT_STATUS_NO_MEMORY;
1304 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1305 __tlsp->internal = tlsp;
1307 if (!file_exist(ca_file)) {
1308 tls_cert_generate(tlsp, dns_host_name,
1309 key_file, cert_file, ca_file);
1312 if (file_exist(key_file) &&
1313 !file_check_permissions(key_file, geteuid(), 0600, &st))
1315 DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
1316 "owner uid %u should be %u, mode 0%o should be 0%o\n"
1317 "This is known as CVE-2013-4476.\n"
1318 "Removing all tls .pem files will cause an "
1319 "auto-regeneration with the correct permissions.\n",
1321 (unsigned int)st.st_uid, geteuid(),
1322 (unsigned int)(st.st_mode & 0777), 0600));
1323 TALLOC_FREE(__tlsp);
1324 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1327 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
1328 if (ret != GNUTLS_E_SUCCESS) {
1329 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1330 TALLOC_FREE(__tlsp);
1331 return NT_STATUS_NO_MEMORY;
1334 if (ca_file && *ca_file) {
1335 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1337 GNUTLS_X509_FMT_PEM);
1339 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1340 ca_file, gnutls_strerror(ret)));
1341 TALLOC_FREE(__tlsp);
1342 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1346 if (crl_file && *crl_file) {
1347 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1349 GNUTLS_X509_FMT_PEM);
1351 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1352 crl_file, gnutls_strerror(ret)));
1353 TALLOC_FREE(__tlsp);
1354 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1358 ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
1359 cert_file, key_file,
1360 GNUTLS_X509_FMT_PEM);
1361 if (ret != GNUTLS_E_SUCCESS) {
1362 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1363 cert_file, key_file, gnutls_strerror(ret)));
1364 TALLOC_FREE(__tlsp);
1365 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1368 ret = gnutls_dh_params_init(&tlsp->dh_params);
1369 if (ret != GNUTLS_E_SUCCESS) {
1370 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1371 TALLOC_FREE(__tlsp);
1372 return NT_STATUS_NO_MEMORY;
1375 if (dhp_file && *dhp_file) {
1376 gnutls_datum_t dhparms;
1379 dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
1381 if (!dhparms.data) {
1382 DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1383 dhp_file, errno, strerror(errno)));
1384 TALLOC_FREE(__tlsp);
1385 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1387 dhparms.size = size;
1389 ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
1391 GNUTLS_X509_FMT_PEM);
1392 if (ret != GNUTLS_E_SUCCESS) {
1393 DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1394 dhp_file, gnutls_strerror(ret)));
1395 TALLOC_FREE(__tlsp);
1396 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1399 ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
1400 if (ret != GNUTLS_E_SUCCESS) {
1401 DEBUG(0,("TLS failed to generate dh_params - %s\n",
1402 gnutls_strerror(ret)));
1403 TALLOC_FREE(__tlsp);
1404 return NT_STATUS_INTERNAL_ERROR;
1408 gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
1410 tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
1411 if (tlsp->tls_priority == NULL) {
1412 TALLOC_FREE(__tlsp);
1413 return NT_STATUS_NO_MEMORY;
1416 tlsp->tls_enabled = true;
1419 return NT_STATUS_OK;
1422 struct tstream_tls_accept_state {
1423 struct tstream_context *tls_stream;
1426 struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
1427 struct tevent_context *ev,
1428 struct tstream_context *plain_stream,
1429 struct tstream_tls_params *_tlsp,
1430 const char *location)
1432 struct tevent_req *req;
1433 struct tstream_tls_accept_state *state;
1434 struct tstream_tls *tlss;
1437 req = tevent_req_create(mem_ctx, &state,
1438 struct tstream_tls_accept_state);
1443 state->tls_stream = tstream_context_create(state,
1448 if (tevent_req_nomem(state->tls_stream, req)) {
1449 return tevent_req_post(req, ev);
1452 talloc_set_destructor(tlss, tstream_tls_destructor);
1453 tlss->plain_stream = plain_stream;
1454 tlss->is_server = true;
1455 tlss->current_ev = ev;
1457 status = tstream_tls_prepare_gnutls(_tlsp, tlss);
1458 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1459 tevent_req_oom(req);
1460 return tevent_req_post(req, ev);
1462 if (!NT_STATUS_IS_OK(status)) {
1463 tevent_req_error(req, EINVAL);
1464 return tevent_req_post(req, ev);
1467 gnutls_transport_set_ptr(tlss->tls_session,
1468 (gnutls_transport_ptr_t)state->tls_stream);
1469 gnutls_transport_set_pull_function(tlss->tls_session,
1470 (gnutls_pull_func)tstream_tls_pull_function);
1471 gnutls_transport_set_push_function(tlss->tls_session,
1472 (gnutls_push_func)tstream_tls_push_function);
1474 tlss->handshake.req = req;
1475 tstream_tls_retry_handshake(state->tls_stream);
1476 if (!tevent_req_is_in_progress(req)) {
1477 return tevent_req_post(req, ev);
1483 static void tstream_tls_retry_handshake(struct tstream_context *stream)
1485 struct tstream_tls *tlss =
1486 tstream_context_data(stream,
1487 struct tstream_tls);
1488 struct tevent_req *req = tlss->handshake.req;
1492 if (tlss->error != 0) {
1493 tevent_req_error(req, tlss->error);
1497 ret = gnutls_handshake(tlss->tls_session);
1498 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
1502 tlss->handshake.req = NULL;
1504 if (gnutls_error_is_fatal(ret) != 0) {
1505 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1507 tevent_req_error(req, tlss->error);
1511 if (ret != GNUTLS_E_SUCCESS) {
1512 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1514 tevent_req_error(req, tlss->error);
1518 status = tstream_tls_verify_peer(tlss);
1519 if (NT_STATUS_EQUAL(status, NT_STATUS_IMAGE_CERT_REVOKED)) {
1520 tlss->error = EINVAL;
1521 tevent_req_error(req, tlss->error);
1524 if (!NT_STATUS_IS_OK(status)) {
1526 tevent_req_error(req, tlss->error);
1530 if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
1531 tlss->waiting_flush.mgmt_req = req;
1535 tevent_req_done(req);
1538 int tstream_tls_accept_recv(struct tevent_req *req,
1540 TALLOC_CTX *mem_ctx,
1541 struct tstream_context **tls_stream)
1543 struct tstream_tls_accept_state *state =
1544 tevent_req_data(req,
1545 struct tstream_tls_accept_state);
1547 if (tevent_req_is_unix_error(req, perrno)) {
1548 tevent_req_received(req);
1552 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1553 tevent_req_received(req);