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>
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
;
61 struct tstream_context
*plain_stream
;
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
;
77 struct tevent_req
*subreq
;
78 struct tevent_immediate
*im
;
84 struct tevent_req
*subreq
;
88 struct tevent_req
*req
;
95 struct tevent_req
*req
;
101 uint8_t buffer
[1024];
102 struct tevent_req
*req
;
106 struct tevent_req
*req
;
110 static void tstream_tls_retry_handshake(struct tstream_context
*stream
);
111 static void tstream_tls_retry_read(struct tstream_context
*stream
);
112 static void tstream_tls_retry_write(struct tstream_context
*stream
);
113 static void tstream_tls_retry_disconnect(struct tstream_context
*stream
);
114 static void tstream_tls_retry_trigger(struct tevent_context
*ctx
,
115 struct tevent_immediate
*im
,
118 static void tstream_tls_retry(struct tstream_context
*stream
, bool deferred
)
121 struct tstream_tls
*tlss
=
122 tstream_context_data(stream
,
125 if (tlss
->disconnect
.req
) {
126 tstream_tls_retry_disconnect(stream
);
130 if (tlss
->handshake
.req
) {
131 tstream_tls_retry_handshake(stream
);
135 if (tlss
->write
.req
&& tlss
->read
.req
&& !deferred
) {
136 tevent_schedule_immediate(tlss
->retry_im
, tlss
->current_ev
,
137 tstream_tls_retry_trigger
,
141 if (tlss
->write
.req
) {
142 tstream_tls_retry_write(stream
);
146 if (tlss
->read
.req
) {
147 tstream_tls_retry_read(stream
);
152 static void tstream_tls_retry_trigger(struct tevent_context
*ctx
,
153 struct tevent_immediate
*im
,
156 struct tstream_context
*stream
=
157 talloc_get_type_abort(private_data
,
158 struct tstream_context
);
160 tstream_tls_retry(stream
, true);
163 static void tstream_tls_push_trigger_write(struct tevent_context
*ev
,
164 struct tevent_immediate
*im
,
167 static ssize_t
tstream_tls_push_function(gnutls_transport_ptr_t ptr
,
168 const void *buf
, size_t size
)
170 struct tstream_context
*stream
=
171 talloc_get_type_abort(ptr
,
172 struct tstream_context
);
173 struct tstream_tls
*tlss
=
174 tstream_context_data(stream
,
179 if (tlss
->error
!= 0) {
184 if (tlss
->push
.subreq
) {
189 len
= MIN(size
, UINT16_MAX
- tlss
->push
.ofs
);
196 nbuf
= talloc_realloc(tlss
, tlss
->push
.buf
,
197 uint8_t, tlss
->push
.ofs
+ len
);
199 if (tlss
->push
.buf
) {
206 tlss
->push
.buf
= nbuf
;
208 memcpy(tlss
->push
.buf
+ tlss
->push
.ofs
, buf
, len
);
210 if (tlss
->push
.im
== NULL
) {
211 tlss
->push
.im
= tevent_create_immediate(tlss
);
212 if (tlss
->push
.im
== NULL
) {
218 if (tlss
->push
.ofs
== 0) {
220 * We'll do start the tstream_writev
221 * in the next event cycle.
223 * This way we can batch all push requests,
224 * if they fit into a UINT16_MAX buffer.
226 * This is important as gnutls_handshake()
227 * had a bug in some versions e.g. 2.4.1
228 * and others (See bug #7218) and it doesn't
231 tevent_schedule_immediate(tlss
->push
.im
,
233 tstream_tls_push_trigger_write
,
237 tlss
->push
.ofs
+= len
;
241 static void tstream_tls_push_done(struct tevent_req
*subreq
);
243 static void tstream_tls_push_trigger_write(struct tevent_context
*ev
,
244 struct tevent_immediate
*im
,
247 struct tstream_context
*stream
=
248 talloc_get_type_abort(private_data
,
249 struct tstream_context
);
250 struct tstream_tls
*tlss
=
251 tstream_context_data(stream
,
253 struct tevent_req
*subreq
;
255 if (tlss
->push
.subreq
) {
260 tlss
->push
.iov
.iov_base
= (char *)tlss
->push
.buf
;
261 tlss
->push
.iov
.iov_len
= tlss
->push
.ofs
;
263 subreq
= tstream_writev_send(tlss
,
267 if (subreq
== NULL
) {
268 tlss
->error
= ENOMEM
;
269 tstream_tls_retry(stream
, false);
272 tevent_req_set_callback(subreq
, tstream_tls_push_done
, stream
);
274 tlss
->push
.subreq
= subreq
;
277 static void tstream_tls_push_done(struct tevent_req
*subreq
)
279 struct tstream_context
*stream
=
280 tevent_req_callback_data(subreq
,
281 struct tstream_context
);
282 struct tstream_tls
*tlss
=
283 tstream_context_data(stream
,
288 tlss
->push
.subreq
= NULL
;
289 ZERO_STRUCT(tlss
->push
.iov
);
290 TALLOC_FREE(tlss
->push
.buf
);
293 ret
= tstream_writev_recv(subreq
, &sys_errno
);
296 tlss
->error
= sys_errno
;
297 tstream_tls_retry(stream
, false);
301 tstream_tls_retry(stream
, false);
304 static void tstream_tls_pull_done(struct tevent_req
*subreq
);
306 static ssize_t
tstream_tls_pull_function(gnutls_transport_ptr_t ptr
,
307 void *buf
, size_t size
)
309 struct tstream_context
*stream
=
310 talloc_get_type_abort(ptr
,
311 struct tstream_context
);
312 struct tstream_tls
*tlss
=
313 tstream_context_data(stream
,
315 struct tevent_req
*subreq
;
318 if (tlss
->error
!= 0) {
323 if (tlss
->pull
.subreq
) {
328 if (tlss
->pull
.iov
.iov_base
) {
332 b
= (uint8_t *)tlss
->pull
.iov
.iov_base
;
334 n
= MIN(tlss
->pull
.iov
.iov_len
, size
);
337 tlss
->pull
.iov
.iov_len
-= n
;
339 tlss
->pull
.iov
.iov_base
= (char *)b
;
340 if (tlss
->pull
.iov
.iov_len
== 0) {
341 tlss
->pull
.iov
.iov_base
= NULL
;
342 TALLOC_FREE(tlss
->pull
.buf
);
352 len
= MIN(size
, UINT16_MAX
);
354 tlss
->pull
.buf
= talloc_array(tlss
, uint8_t, len
);
355 if (tlss
->pull
.buf
== NULL
) {
359 tlss
->pull
.iov
.iov_base
= (char *)tlss
->pull
.buf
;
360 tlss
->pull
.iov
.iov_len
= len
;
362 subreq
= tstream_readv_send(tlss
,
366 if (subreq
== NULL
) {
370 tevent_req_set_callback(subreq
, tstream_tls_pull_done
, stream
);
372 tlss
->pull
.subreq
= subreq
;
377 static void tstream_tls_pull_done(struct tevent_req
*subreq
)
379 struct tstream_context
*stream
=
380 tevent_req_callback_data(subreq
,
381 struct tstream_context
);
382 struct tstream_tls
*tlss
=
383 tstream_context_data(stream
,
388 tlss
->pull
.subreq
= NULL
;
390 ret
= tstream_readv_recv(subreq
, &sys_errno
);
393 tlss
->error
= sys_errno
;
394 tstream_tls_retry(stream
, false);
398 tstream_tls_retry(stream
, false);
401 static int tstream_tls_destructor(struct tstream_tls
*tlss
)
403 if (tlss
->tls_session
) {
404 gnutls_deinit(tlss
->tls_session
);
405 tlss
->tls_session
= NULL
;
411 static ssize_t
tstream_tls_pending_bytes(struct tstream_context
*stream
)
413 struct tstream_tls
*tlss
=
414 tstream_context_data(stream
,
418 if (tlss
->error
!= 0) {
423 ret
= gnutls_record_check_pending(tlss
->tls_session
);
424 ret
+= tlss
->read
.left
;
429 struct tstream_tls_readv_state
{
430 struct tstream_context
*stream
;
432 struct iovec
*vector
;
438 static void tstream_tls_readv_crypt_next(struct tevent_req
*req
);
440 static struct tevent_req
*tstream_tls_readv_send(TALLOC_CTX
*mem_ctx
,
441 struct tevent_context
*ev
,
442 struct tstream_context
*stream
,
443 struct iovec
*vector
,
446 struct tstream_tls
*tlss
=
447 tstream_context_data(stream
,
449 struct tevent_req
*req
;
450 struct tstream_tls_readv_state
*state
;
452 tlss
->read
.req
= NULL
;
453 tlss
->current_ev
= ev
;
455 req
= tevent_req_create(mem_ctx
, &state
,
456 struct tstream_tls_readv_state
);
461 state
->stream
= stream
;
464 if (tlss
->error
!= 0) {
465 tevent_req_error(req
, tlss
->error
);
466 return tevent_req_post(req
, ev
);
470 * we make a copy of the vector so we can change the structure
472 state
->vector
= talloc_array(state
, struct iovec
, count
);
473 if (tevent_req_nomem(state
->vector
, req
)) {
474 return tevent_req_post(req
, ev
);
476 memcpy(state
->vector
, vector
, sizeof(struct iovec
) * count
);
477 state
->count
= count
;
479 tstream_tls_readv_crypt_next(req
);
480 if (!tevent_req_is_in_progress(req
)) {
481 return tevent_req_post(req
, ev
);
487 static void tstream_tls_readv_crypt_next(struct tevent_req
*req
)
489 struct tstream_tls_readv_state
*state
=
491 struct tstream_tls_readv_state
);
492 struct tstream_tls
*tlss
=
493 tstream_context_data(state
->stream
,
497 * copy the pending buffer first
499 while (tlss
->read
.left
> 0 && state
->count
> 0) {
500 uint8_t *base
= (uint8_t *)state
->vector
[0].iov_base
;
501 size_t len
= MIN(tlss
->read
.left
, state
->vector
[0].iov_len
);
503 memcpy(base
, tlss
->read
.buffer
+ tlss
->read
.ofs
, len
);
506 state
->vector
[0].iov_base
= (char *) base
;
507 state
->vector
[0].iov_len
-= len
;
509 tlss
->read
.ofs
+= len
;
510 tlss
->read
.left
-= len
;
512 if (state
->vector
[0].iov_len
== 0) {
520 if (state
->count
== 0) {
521 tevent_req_done(req
);
525 tlss
->read
.req
= req
;
526 tstream_tls_retry_read(state
->stream
);
529 static void tstream_tls_retry_read(struct tstream_context
*stream
)
531 struct tstream_tls
*tlss
=
532 tstream_context_data(stream
,
534 struct tevent_req
*req
= tlss
->read
.req
;
537 if (tlss
->error
!= 0) {
538 tevent_req_error(req
, tlss
->error
);
545 ret
= gnutls_record_recv(tlss
->tls_session
,
547 sizeof(tlss
->read
.buffer
));
548 if (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
) {
552 tlss
->read
.req
= NULL
;
554 if (gnutls_error_is_fatal(ret
) != 0) {
555 DEBUG(1,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
557 tevent_req_error(req
, tlss
->error
);
563 tevent_req_error(req
, tlss
->error
);
567 tlss
->read
.left
= ret
;
568 tstream_tls_readv_crypt_next(req
);
571 static int tstream_tls_readv_recv(struct tevent_req
*req
,
574 struct tstream_tls_readv_state
*state
=
576 struct tstream_tls_readv_state
);
577 struct tstream_tls
*tlss
=
578 tstream_context_data(state
->stream
,
582 tlss
->read
.req
= NULL
;
584 ret
= tsocket_simple_int_recv(req
, perrno
);
589 tevent_req_received(req
);
593 struct tstream_tls_writev_state
{
594 struct tstream_context
*stream
;
596 struct iovec
*vector
;
602 static void tstream_tls_writev_crypt_next(struct tevent_req
*req
);
604 static struct tevent_req
*tstream_tls_writev_send(TALLOC_CTX
*mem_ctx
,
605 struct tevent_context
*ev
,
606 struct tstream_context
*stream
,
607 const struct iovec
*vector
,
610 struct tstream_tls
*tlss
=
611 tstream_context_data(stream
,
613 struct tevent_req
*req
;
614 struct tstream_tls_writev_state
*state
;
616 tlss
->write
.req
= NULL
;
617 tlss
->current_ev
= ev
;
619 req
= tevent_req_create(mem_ctx
, &state
,
620 struct tstream_tls_writev_state
);
625 state
->stream
= stream
;
628 if (tlss
->error
!= 0) {
629 tevent_req_error(req
, tlss
->error
);
630 return tevent_req_post(req
, ev
);
634 * we make a copy of the vector so we can change the structure
636 state
->vector
= talloc_array(state
, struct iovec
, count
);
637 if (tevent_req_nomem(state
->vector
, req
)) {
638 return tevent_req_post(req
, ev
);
640 memcpy(state
->vector
, vector
, sizeof(struct iovec
) * count
);
641 state
->count
= count
;
643 tstream_tls_writev_crypt_next(req
);
644 if (!tevent_req_is_in_progress(req
)) {
645 return tevent_req_post(req
, ev
);
651 static void tstream_tls_writev_crypt_next(struct tevent_req
*req
)
653 struct tstream_tls_writev_state
*state
=
655 struct tstream_tls_writev_state
);
656 struct tstream_tls
*tlss
=
657 tstream_context_data(state
->stream
,
660 tlss
->write
.left
= sizeof(tlss
->write
.buffer
);
664 * first fill our buffer
666 while (tlss
->write
.left
> 0 && state
->count
> 0) {
667 uint8_t *base
= (uint8_t *)state
->vector
[0].iov_base
;
668 size_t len
= MIN(tlss
->write
.left
, state
->vector
[0].iov_len
);
670 memcpy(tlss
->write
.buffer
+ tlss
->write
.ofs
, base
, len
);
673 state
->vector
[0].iov_base
= (char *) base
;
674 state
->vector
[0].iov_len
-= len
;
676 tlss
->write
.ofs
+= len
;
677 tlss
->write
.left
-= len
;
679 if (state
->vector
[0].iov_len
== 0) {
687 if (tlss
->write
.ofs
== 0) {
688 tevent_req_done(req
);
692 tlss
->write
.left
= tlss
->write
.ofs
;
695 tlss
->write
.req
= req
;
696 tstream_tls_retry_write(state
->stream
);
699 static void tstream_tls_retry_write(struct tstream_context
*stream
)
701 struct tstream_tls
*tlss
=
702 tstream_context_data(stream
,
704 struct tevent_req
*req
= tlss
->write
.req
;
707 if (tlss
->error
!= 0) {
708 tevent_req_error(req
, tlss
->error
);
712 ret
= gnutls_record_send(tlss
->tls_session
,
713 tlss
->write
.buffer
+ tlss
->write
.ofs
,
715 if (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
) {
719 tlss
->write
.req
= NULL
;
721 if (gnutls_error_is_fatal(ret
) != 0) {
722 DEBUG(1,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
724 tevent_req_error(req
, tlss
->error
);
730 tevent_req_error(req
, tlss
->error
);
734 tlss
->write
.ofs
+= ret
;
735 tlss
->write
.left
-= ret
;
737 if (tlss
->write
.left
> 0) {
738 tlss
->write
.req
= req
;
739 tstream_tls_retry_write(stream
);
743 tstream_tls_writev_crypt_next(req
);
746 static int tstream_tls_writev_recv(struct tevent_req
*req
,
749 struct tstream_tls_writev_state
*state
=
751 struct tstream_tls_writev_state
);
752 struct tstream_tls
*tlss
=
753 tstream_context_data(state
->stream
,
757 tlss
->write
.req
= NULL
;
759 ret
= tsocket_simple_int_recv(req
, perrno
);
764 tevent_req_received(req
);
768 struct tstream_tls_disconnect_state
{
772 static struct tevent_req
*tstream_tls_disconnect_send(TALLOC_CTX
*mem_ctx
,
773 struct tevent_context
*ev
,
774 struct tstream_context
*stream
)
776 struct tstream_tls
*tlss
=
777 tstream_context_data(stream
,
779 struct tevent_req
*req
;
780 struct tstream_tls_disconnect_state
*state
;
782 tlss
->disconnect
.req
= NULL
;
783 tlss
->current_ev
= ev
;
785 req
= tevent_req_create(mem_ctx
, &state
,
786 struct tstream_tls_disconnect_state
);
791 if (tlss
->error
!= 0) {
792 tevent_req_error(req
, tlss
->error
);
793 return tevent_req_post(req
, ev
);
796 tlss
->disconnect
.req
= req
;
797 tstream_tls_retry_disconnect(stream
);
798 if (!tevent_req_is_in_progress(req
)) {
799 return tevent_req_post(req
, ev
);
805 static void tstream_tls_retry_disconnect(struct tstream_context
*stream
)
807 struct tstream_tls
*tlss
=
808 tstream_context_data(stream
,
810 struct tevent_req
*req
= tlss
->disconnect
.req
;
813 if (tlss
->error
!= 0) {
814 tevent_req_error(req
, tlss
->error
);
818 ret
= gnutls_bye(tlss
->tls_session
, GNUTLS_SHUT_WR
);
819 if (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
) {
823 tlss
->disconnect
.req
= NULL
;
825 if (gnutls_error_is_fatal(ret
) != 0) {
826 DEBUG(1,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
828 tevent_req_error(req
, tlss
->error
);
832 if (ret
!= GNUTLS_E_SUCCESS
) {
833 DEBUG(1,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
835 tevent_req_error(req
, tlss
->error
);
839 tevent_req_done(req
);
842 static int tstream_tls_disconnect_recv(struct tevent_req
*req
,
847 ret
= tsocket_simple_int_recv(req
, perrno
);
849 tevent_req_received(req
);
853 static const struct tstream_context_ops tstream_tls_ops
= {
856 .pending_bytes
= tstream_tls_pending_bytes
,
858 .readv_send
= tstream_tls_readv_send
,
859 .readv_recv
= tstream_tls_readv_recv
,
861 .writev_send
= tstream_tls_writev_send
,
862 .writev_recv
= tstream_tls_writev_recv
,
864 .disconnect_send
= tstream_tls_disconnect_send
,
865 .disconnect_recv
= tstream_tls_disconnect_recv
,
868 struct tstream_tls_params_internal
{
869 gnutls_certificate_credentials_t x509_cred
;
870 gnutls_dh_params_t dh_params
;
871 const char *tls_priority
;
873 enum tls_verify_peer_state verify_peer
;
874 const char *peer_name
;
877 struct tstream_tls_params
{
878 struct tstream_tls_params_internal
*internal
;
881 static int tstream_tls_params_internal_destructor(struct tstream_tls_params_internal
*tlsp
)
883 if (tlsp
->x509_cred
) {
884 gnutls_certificate_free_credentials(tlsp
->x509_cred
);
885 tlsp
->x509_cred
= NULL
;
887 if (tlsp
->dh_params
) {
888 gnutls_dh_params_deinit(tlsp
->dh_params
);
889 tlsp
->dh_params
= NULL
;
895 bool tstream_tls_params_enabled(struct tstream_tls_params
*tls_params
)
897 struct tstream_tls_params_internal
*tlsp
= tls_params
->internal
;
899 return tlsp
->tls_enabled
;
902 NTSTATUS
tstream_tls_params_client(TALLOC_CTX
*mem_ctx
,
904 const char *crl_file
,
905 const char *tls_priority
,
906 enum tls_verify_peer_state verify_peer
,
907 const char *peer_name
,
908 struct tstream_tls_params
**_tlsp
)
910 struct tstream_tls_params
*__tlsp
= NULL
;
911 struct tstream_tls_params_internal
*tlsp
= NULL
;
914 __tlsp
= talloc_zero(mem_ctx
, struct tstream_tls_params
);
915 if (__tlsp
== NULL
) {
916 return NT_STATUS_NO_MEMORY
;
919 tlsp
= talloc_zero(__tlsp
, struct tstream_tls_params_internal
);
922 return NT_STATUS_NO_MEMORY
;
924 talloc_set_destructor(tlsp
, tstream_tls_params_internal_destructor
);
925 __tlsp
->internal
= tlsp
;
927 tlsp
->verify_peer
= verify_peer
;
928 if (peer_name
!= NULL
) {
929 tlsp
->peer_name
= talloc_strdup(tlsp
, peer_name
);
930 if (tlsp
->peer_name
== NULL
) {
932 return NT_STATUS_NO_MEMORY
;
934 } else if (tlsp
->verify_peer
>= TLS_VERIFY_PEER_CA_AND_NAME
) {
935 DEBUG(0,("TLS failed to missing peer_name - "
936 "with 'tls verify peer = %s'\n",
937 tls_verify_peer_string(tlsp
->verify_peer
)));
939 return NT_STATUS_INVALID_PARAMETER_MIX
;
942 ret
= gnutls_certificate_allocate_credentials(&tlsp
->x509_cred
);
943 if (ret
!= GNUTLS_E_SUCCESS
) {
944 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
946 return NT_STATUS_NO_MEMORY
;
949 if (ca_file
&& *ca_file
&& file_exist(ca_file
)) {
950 ret
= gnutls_certificate_set_x509_trust_file(tlsp
->x509_cred
,
952 GNUTLS_X509_FMT_PEM
);
954 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
955 ca_file
, gnutls_strerror(ret
)));
957 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
959 } else if (tlsp
->verify_peer
>= TLS_VERIFY_PEER_CA_ONLY
) {
960 DEBUG(0,("TLS failed to missing cafile %s - "
961 "with 'tls verify peer = %s'\n",
963 tls_verify_peer_string(tlsp
->verify_peer
)));
965 return NT_STATUS_INVALID_PARAMETER_MIX
;
968 if (crl_file
&& *crl_file
&& file_exist(crl_file
)) {
969 ret
= gnutls_certificate_set_x509_crl_file(tlsp
->x509_cred
,
971 GNUTLS_X509_FMT_PEM
);
973 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
974 crl_file
, gnutls_strerror(ret
)));
976 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
978 } else if (tlsp
->verify_peer
>= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE
) {
979 DEBUG(0,("TLS failed to missing crlfile %s - "
980 "with 'tls verify peer = %s'\n",
982 tls_verify_peer_string(tlsp
->verify_peer
)));
984 return NT_STATUS_INVALID_PARAMETER_MIX
;
987 tlsp
->tls_priority
= talloc_strdup(tlsp
, tls_priority
);
988 if (tlsp
->tls_priority
== NULL
) {
990 return NT_STATUS_NO_MEMORY
;
993 tlsp
->tls_enabled
= true;
999 struct tstream_tls_connect_state
{
1000 struct tstream_context
*tls_stream
;
1003 struct tevent_req
*_tstream_tls_connect_send(TALLOC_CTX
*mem_ctx
,
1004 struct tevent_context
*ev
,
1005 struct tstream_context
*plain_stream
,
1006 struct tstream_tls_params
*_tls_params
,
1007 const char *location
)
1009 struct tevent_req
*req
;
1010 struct tstream_tls_connect_state
*state
;
1011 const char *error_pos
;
1012 struct tstream_tls
*tlss
;
1013 struct tstream_tls_params_internal
*tls_params
= NULL
;
1015 unsigned int flags
= GNUTLS_CLIENT
;
1017 req
= tevent_req_create(mem_ctx
, &state
,
1018 struct tstream_tls_connect_state
);
1023 state
->tls_stream
= tstream_context_create(state
,
1028 if (tevent_req_nomem(state
->tls_stream
, req
)) {
1029 return tevent_req_post(req
, ev
);
1032 talloc_set_destructor(tlss
, tstream_tls_destructor
);
1035 * Note we need to make sure x509_cred and dh_params
1036 * from tstream_tls_params_internal stay alive for
1037 * the whole lifetime of this session!
1039 * See 'man gnutls_credentials_set' and
1040 * 'man gnutls_certificate_set_dh_params'.
1042 * Note: here we use talloc_reference() in a way
1043 * that does not expose it to the caller.
1046 tls_params
= talloc_reference(tlss
, _tls_params
->internal
);
1047 if (tevent_req_nomem(tls_params
, req
)) {
1048 return tevent_req_post(req
, ev
);
1051 tlss
->plain_stream
= plain_stream
;
1052 tlss
->verify_peer
= tls_params
->verify_peer
;
1053 if (tls_params
->peer_name
!= NULL
) {
1054 tlss
->peer_name
= talloc_strdup(tlss
, tls_params
->peer_name
);
1055 if (tevent_req_nomem(tlss
->peer_name
, req
)) {
1056 return tevent_req_post(req
, ev
);
1060 tlss
->current_ev
= ev
;
1061 tlss
->retry_im
= tevent_create_immediate(tlss
);
1062 if (tevent_req_nomem(tlss
->retry_im
, req
)) {
1063 return tevent_req_post(req
, ev
);
1066 #ifdef GNUTLS_NO_TICKETS
1068 * tls_tstream can't properly handle 'New Session Ticket' messages
1069 * sent 'after' the client sends the 'Finished' message.
1070 * GNUTLS_NO_TICKETS was introduced in GnuTLS 3.5.6. This flag is to
1071 * indicate the session Flag session should not use resumption with
1074 flags
|= GNUTLS_NO_TICKETS
;
1077 ret
= gnutls_init(&tlss
->tls_session
, flags
);
1078 if (ret
!= GNUTLS_E_SUCCESS
) {
1079 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1080 tevent_req_error(req
, EINVAL
);
1081 return tevent_req_post(req
, ev
);
1084 ret
= gnutls_set_default_priority(tlss
->tls_session
);
1085 if (ret
!= GNUTLS_E_SUCCESS
) {
1086 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1087 __location__
, gnutls_strerror(ret
));
1088 tevent_req_error(req
, EINVAL
);
1089 return tevent_req_post(req
, ev
);
1092 if (strlen(tls_params
->tls_priority
) > 0) {
1093 ret
= gnutls_priority_set_direct(tlss
->tls_session
,
1094 tls_params
->tls_priority
,
1096 if (ret
!= GNUTLS_E_SUCCESS
) {
1097 DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1098 __location__
, gnutls_strerror(ret
), error_pos
));
1099 tevent_req_error(req
, EINVAL
);
1100 return tevent_req_post(req
, ev
);
1104 ret
= gnutls_credentials_set(tlss
->tls_session
,
1105 GNUTLS_CRD_CERTIFICATE
,
1106 tls_params
->x509_cred
);
1107 if (ret
!= GNUTLS_E_SUCCESS
) {
1108 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1109 tevent_req_error(req
, EINVAL
);
1110 return tevent_req_post(req
, ev
);
1113 gnutls_transport_set_ptr(tlss
->tls_session
,
1114 (gnutls_transport_ptr_t
)state
->tls_stream
);
1115 gnutls_transport_set_pull_function(tlss
->tls_session
,
1116 (gnutls_pull_func
)tstream_tls_pull_function
);
1117 gnutls_transport_set_push_function(tlss
->tls_session
,
1118 (gnutls_push_func
)tstream_tls_push_function
);
1120 tlss
->handshake
.req
= req
;
1121 tstream_tls_retry_handshake(state
->tls_stream
);
1122 if (!tevent_req_is_in_progress(req
)) {
1123 return tevent_req_post(req
, ev
);
1129 int tstream_tls_connect_recv(struct tevent_req
*req
,
1131 TALLOC_CTX
*mem_ctx
,
1132 struct tstream_context
**tls_stream
)
1134 struct tstream_tls_connect_state
*state
=
1135 tevent_req_data(req
,
1136 struct tstream_tls_connect_state
);
1138 if (tevent_req_is_unix_error(req
, perrno
)) {
1139 tevent_req_received(req
);
1143 *tls_stream
= talloc_move(mem_ctx
, &state
->tls_stream
);
1144 tevent_req_received(req
);
1149 initialise global tls state
1151 NTSTATUS
tstream_tls_params_server(TALLOC_CTX
*mem_ctx
,
1152 const char *dns_host_name
,
1154 const char *key_file
,
1155 const char *cert_file
,
1156 const char *ca_file
,
1157 const char *crl_file
,
1158 const char *dhp_file
,
1159 const char *tls_priority
,
1160 struct tstream_tls_params
**_tlsp
)
1162 struct tstream_tls_params
*__tlsp
= NULL
;
1163 struct tstream_tls_params_internal
*tlsp
= NULL
;
1167 if (!enabled
|| key_file
== NULL
|| *key_file
== 0) {
1168 __tlsp
= talloc_zero(mem_ctx
, struct tstream_tls_params
);
1169 if (__tlsp
== NULL
) {
1170 return NT_STATUS_NO_MEMORY
;
1173 tlsp
= talloc_zero(__tlsp
, struct tstream_tls_params_internal
);
1175 TALLOC_FREE(__tlsp
);
1176 return NT_STATUS_NO_MEMORY
;
1179 talloc_set_destructor(tlsp
, tstream_tls_params_internal_destructor
);
1180 __tlsp
->internal
= tlsp
;
1181 tlsp
->tls_enabled
= false;
1184 return NT_STATUS_OK
;
1187 __tlsp
= talloc_zero(mem_ctx
, struct tstream_tls_params
);
1188 if (__tlsp
== NULL
) {
1189 return NT_STATUS_NO_MEMORY
;
1192 tlsp
= talloc_zero(__tlsp
, struct tstream_tls_params_internal
);
1194 TALLOC_FREE(__tlsp
);
1195 return NT_STATUS_NO_MEMORY
;
1198 talloc_set_destructor(tlsp
, tstream_tls_params_internal_destructor
);
1199 __tlsp
->internal
= tlsp
;
1201 if (!file_exist(ca_file
)) {
1202 tls_cert_generate(tlsp
, dns_host_name
,
1203 key_file
, cert_file
, ca_file
);
1206 if (file_exist(key_file
) &&
1207 !file_check_permissions(key_file
, geteuid(), 0600, &st
))
1209 DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
1210 "owner uid %u should be %u, mode 0%o should be 0%o\n"
1211 "This is known as CVE-2013-4476.\n"
1212 "Removing all tls .pem files will cause an "
1213 "auto-regeneration with the correct permissions.\n",
1215 (unsigned int)st
.st_uid
, geteuid(),
1216 (unsigned int)(st
.st_mode
& 0777), 0600));
1217 TALLOC_FREE(__tlsp
);
1218 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1221 ret
= gnutls_certificate_allocate_credentials(&tlsp
->x509_cred
);
1222 if (ret
!= GNUTLS_E_SUCCESS
) {
1223 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1224 TALLOC_FREE(__tlsp
);
1225 return NT_STATUS_NO_MEMORY
;
1228 if (ca_file
&& *ca_file
) {
1229 ret
= gnutls_certificate_set_x509_trust_file(tlsp
->x509_cred
,
1231 GNUTLS_X509_FMT_PEM
);
1233 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1234 ca_file
, gnutls_strerror(ret
)));
1235 TALLOC_FREE(__tlsp
);
1236 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1240 if (crl_file
&& *crl_file
) {
1241 ret
= gnutls_certificate_set_x509_crl_file(tlsp
->x509_cred
,
1243 GNUTLS_X509_FMT_PEM
);
1245 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1246 crl_file
, gnutls_strerror(ret
)));
1247 TALLOC_FREE(__tlsp
);
1248 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1252 ret
= gnutls_certificate_set_x509_key_file(tlsp
->x509_cred
,
1253 cert_file
, key_file
,
1254 GNUTLS_X509_FMT_PEM
);
1255 if (ret
!= GNUTLS_E_SUCCESS
) {
1256 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1257 cert_file
, key_file
, gnutls_strerror(ret
)));
1258 TALLOC_FREE(__tlsp
);
1259 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1262 ret
= gnutls_dh_params_init(&tlsp
->dh_params
);
1263 if (ret
!= GNUTLS_E_SUCCESS
) {
1264 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1265 TALLOC_FREE(__tlsp
);
1266 return NT_STATUS_NO_MEMORY
;
1269 if (dhp_file
&& *dhp_file
) {
1270 gnutls_datum_t dhparms
;
1273 dhparms
.data
= (uint8_t *)file_load(dhp_file
, &size
, 0, tlsp
);
1275 if (!dhparms
.data
) {
1276 DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1277 dhp_file
, errno
, strerror(errno
)));
1278 TALLOC_FREE(__tlsp
);
1279 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1281 dhparms
.size
= size
;
1283 ret
= gnutls_dh_params_import_pkcs3(tlsp
->dh_params
,
1285 GNUTLS_X509_FMT_PEM
);
1286 if (ret
!= GNUTLS_E_SUCCESS
) {
1287 DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1288 dhp_file
, gnutls_strerror(ret
)));
1289 TALLOC_FREE(__tlsp
);
1290 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1293 ret
= gnutls_dh_params_generate2(tlsp
->dh_params
, DH_BITS
);
1294 if (ret
!= GNUTLS_E_SUCCESS
) {
1295 DEBUG(0,("TLS failed to generate dh_params - %s\n",
1296 gnutls_strerror(ret
)));
1297 TALLOC_FREE(__tlsp
);
1298 return NT_STATUS_INTERNAL_ERROR
;
1302 gnutls_certificate_set_dh_params(tlsp
->x509_cred
, tlsp
->dh_params
);
1304 tlsp
->tls_priority
= talloc_strdup(tlsp
, tls_priority
);
1305 if (tlsp
->tls_priority
== NULL
) {
1306 TALLOC_FREE(__tlsp
);
1307 return NT_STATUS_NO_MEMORY
;
1310 tlsp
->tls_enabled
= true;
1313 return NT_STATUS_OK
;
1316 struct tstream_tls_accept_state
{
1317 struct tstream_context
*tls_stream
;
1320 struct tevent_req
*_tstream_tls_accept_send(TALLOC_CTX
*mem_ctx
,
1321 struct tevent_context
*ev
,
1322 struct tstream_context
*plain_stream
,
1323 struct tstream_tls_params
*_tlsp
,
1324 const char *location
)
1326 struct tevent_req
*req
;
1327 struct tstream_tls_accept_state
*state
;
1328 struct tstream_tls
*tlss
;
1329 const char *error_pos
;
1330 struct tstream_tls_params_internal
*tlsp
= NULL
;
1333 req
= tevent_req_create(mem_ctx
, &state
,
1334 struct tstream_tls_accept_state
);
1339 state
->tls_stream
= tstream_context_create(state
,
1344 if (tevent_req_nomem(state
->tls_stream
, req
)) {
1345 return tevent_req_post(req
, ev
);
1348 talloc_set_destructor(tlss
, tstream_tls_destructor
);
1351 * Note we need to make sure x509_cred and dh_params
1352 * from tstream_tls_params_internal stay alive for
1353 * the whole lifetime of this session!
1355 * See 'man gnutls_credentials_set' and
1356 * 'man gnutls_certificate_set_dh_params'.
1358 * Note: here we use talloc_reference() in a way
1359 * that does not expose it to the caller.
1361 tlsp
= talloc_reference(tlss
, _tlsp
->internal
);
1362 if (tevent_req_nomem(tlsp
, req
)) {
1363 return tevent_req_post(req
, ev
);
1366 tlss
->plain_stream
= plain_stream
;
1368 tlss
->current_ev
= ev
;
1369 tlss
->retry_im
= tevent_create_immediate(tlss
);
1370 if (tevent_req_nomem(tlss
->retry_im
, req
)) {
1371 return tevent_req_post(req
, ev
);
1374 ret
= gnutls_init(&tlss
->tls_session
, GNUTLS_SERVER
);
1375 if (ret
!= GNUTLS_E_SUCCESS
) {
1376 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1377 tevent_req_error(req
, EINVAL
);
1378 return tevent_req_post(req
, ev
);
1381 ret
= gnutls_set_default_priority(tlss
->tls_session
);
1382 if (ret
!= GNUTLS_E_SUCCESS
) {
1383 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1384 __location__
, gnutls_strerror(ret
));
1385 tevent_req_error(req
, EINVAL
);
1386 return tevent_req_post(req
, ev
);
1389 if (strlen(tlsp
->tls_priority
) > 0) {
1390 ret
= gnutls_priority_set_direct(tlss
->tls_session
,
1393 if (ret
!= GNUTLS_E_SUCCESS
) {
1394 DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1395 __location__
, gnutls_strerror(ret
), error_pos
));
1396 tevent_req_error(req
, EINVAL
);
1397 return tevent_req_post(req
, ev
);
1401 ret
= gnutls_credentials_set(tlss
->tls_session
, GNUTLS_CRD_CERTIFICATE
,
1403 if (ret
!= GNUTLS_E_SUCCESS
) {
1404 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1405 tevent_req_error(req
, EINVAL
);
1406 return tevent_req_post(req
, ev
);
1409 gnutls_certificate_server_set_request(tlss
->tls_session
,
1410 GNUTLS_CERT_REQUEST
);
1411 gnutls_dh_set_prime_bits(tlss
->tls_session
, DH_BITS
);
1413 gnutls_transport_set_ptr(tlss
->tls_session
,
1414 (gnutls_transport_ptr_t
)state
->tls_stream
);
1415 gnutls_transport_set_pull_function(tlss
->tls_session
,
1416 (gnutls_pull_func
)tstream_tls_pull_function
);
1417 gnutls_transport_set_push_function(tlss
->tls_session
,
1418 (gnutls_push_func
)tstream_tls_push_function
);
1420 tlss
->handshake
.req
= req
;
1421 tstream_tls_retry_handshake(state
->tls_stream
);
1422 if (!tevent_req_is_in_progress(req
)) {
1423 return tevent_req_post(req
, ev
);
1429 static void tstream_tls_retry_handshake(struct tstream_context
*stream
)
1431 struct tstream_tls
*tlss
=
1432 tstream_context_data(stream
,
1433 struct tstream_tls
);
1434 struct tevent_req
*req
= tlss
->handshake
.req
;
1437 if (tlss
->error
!= 0) {
1438 tevent_req_error(req
, tlss
->error
);
1442 ret
= gnutls_handshake(tlss
->tls_session
);
1443 if (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
) {
1447 tlss
->handshake
.req
= NULL
;
1449 if (gnutls_error_is_fatal(ret
) != 0) {
1450 DEBUG(1,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1452 tevent_req_error(req
, tlss
->error
);
1456 if (ret
!= GNUTLS_E_SUCCESS
) {
1457 DEBUG(1,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1459 tevent_req_error(req
, tlss
->error
);
1463 if (tlss
->verify_peer
>= TLS_VERIFY_PEER_CA_ONLY
) {
1464 unsigned int status
= UINT32_MAX
;
1466 const char *hostname
= NULL
;
1468 if (tlss
->peer_name
!= NULL
) {
1469 ip
= is_ipaddress(tlss
->peer_name
);
1473 hostname
= tlss
->peer_name
;
1476 if (tlss
->verify_peer
== TLS_VERIFY_PEER_CA_ONLY
) {
1480 if (tlss
->verify_peer
>= TLS_VERIFY_PEER_CA_AND_NAME
) {
1481 if (hostname
== NULL
) {
1482 DEBUG(1,("TLS %s - no hostname available for "
1483 "verify_peer[%s] and peer_name[%s]\n",
1485 tls_verify_peer_string(tlss
->verify_peer
),
1487 tlss
->error
= EINVAL
;
1488 tevent_req_error(req
, tlss
->error
);
1493 ret
= gnutls_certificate_verify_peers3(tlss
->tls_session
,
1496 if (ret
!= GNUTLS_E_SUCCESS
) {
1497 DEBUG(1,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1499 tevent_req_error(req
, tlss
->error
);
1504 DEBUG(1,("TLS %s - check failed for "
1505 "verify_peer[%s] and peer_name[%s] "
1506 "status 0x%x (%s%s%s%s%s%s%s%s)\n",
1508 tls_verify_peer_string(tlss
->verify_peer
),
1511 status
& GNUTLS_CERT_INVALID
? "invalid " : "",
1512 status
& GNUTLS_CERT_REVOKED
? "revoked " : "",
1513 status
& GNUTLS_CERT_SIGNER_NOT_FOUND
?
1514 "signer_not_found " : "",
1515 status
& GNUTLS_CERT_SIGNER_NOT_CA
?
1516 "signer_not_ca " : "",
1517 status
& GNUTLS_CERT_INSECURE_ALGORITHM
?
1518 "insecure_algorithm " : "",
1519 status
& GNUTLS_CERT_NOT_ACTIVATED
?
1520 "not_activated " : "",
1521 status
& GNUTLS_CERT_EXPIRED
?
1523 status
& GNUTLS_CERT_UNEXPECTED_OWNER
?
1524 "unexpected_owner " : ""));
1525 tlss
->error
= EINVAL
;
1526 tevent_req_error(req
, tlss
->error
);
1531 tevent_req_done(req
);
1534 int tstream_tls_accept_recv(struct tevent_req
*req
,
1536 TALLOC_CTX
*mem_ctx
,
1537 struct tstream_context
**tls_stream
)
1539 struct tstream_tls_accept_state
*state
=
1540 tevent_req_data(req
,
1541 struct tstream_tls_accept_state
);
1543 if (tevent_req_is_unix_error(req
, perrno
)) {
1544 tevent_req_received(req
);
1548 *tls_stream
= talloc_move(mem_ctx
, &state
->tls_stream
);
1549 tevent_req_received(req
);