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_internal
{
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 struct tstream_tls_params
{
877 struct tstream_tls_params_internal
*internal
;
880 static int tstream_tls_params_internal_destructor(struct tstream_tls_params_internal
*tlsp
)
882 if (tlsp
->x509_cred
) {
883 gnutls_certificate_free_credentials(tlsp
->x509_cred
);
884 tlsp
->x509_cred
= NULL
;
886 if (tlsp
->dh_params
) {
887 gnutls_dh_params_deinit(tlsp
->dh_params
);
888 tlsp
->dh_params
= NULL
;
894 bool tstream_tls_params_enabled(struct tstream_tls_params
*tls_params
)
896 struct tstream_tls_params_internal
*tlsp
= tls_params
->internal
;
898 return tlsp
->tls_enabled
;
901 NTSTATUS
tstream_tls_params_client(TALLOC_CTX
*mem_ctx
,
903 const char *crl_file
,
904 const char *tls_priority
,
905 enum tls_verify_peer_state verify_peer
,
906 const char *peer_name
,
907 struct tstream_tls_params
**_tlsp
)
909 struct tstream_tls_params
*__tlsp
= NULL
;
910 struct tstream_tls_params_internal
*tlsp
= NULL
;
913 __tlsp
= talloc_zero(mem_ctx
, struct tstream_tls_params
);
914 if (__tlsp
== NULL
) {
915 return NT_STATUS_NO_MEMORY
;
918 tlsp
= talloc_zero(__tlsp
, struct tstream_tls_params_internal
);
921 return NT_STATUS_NO_MEMORY
;
923 talloc_set_destructor(tlsp
, tstream_tls_params_internal_destructor
);
924 __tlsp
->internal
= tlsp
;
926 tlsp
->verify_peer
= verify_peer
;
927 if (peer_name
!= NULL
) {
928 tlsp
->peer_name
= talloc_strdup(tlsp
, peer_name
);
929 if (tlsp
->peer_name
== NULL
) {
931 return NT_STATUS_NO_MEMORY
;
933 } else if (tlsp
->verify_peer
>= TLS_VERIFY_PEER_CA_AND_NAME
) {
934 DEBUG(0,("TLS failed to missing peer_name - "
935 "with 'tls verify peer = %s'\n",
936 tls_verify_peer_string(tlsp
->verify_peer
)));
938 return NT_STATUS_INVALID_PARAMETER_MIX
;
941 ret
= gnutls_certificate_allocate_credentials(&tlsp
->x509_cred
);
942 if (ret
!= GNUTLS_E_SUCCESS
) {
943 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
945 return NT_STATUS_NO_MEMORY
;
948 if (ca_file
&& *ca_file
&& file_exist(ca_file
)) {
949 ret
= gnutls_certificate_set_x509_trust_file(tlsp
->x509_cred
,
951 GNUTLS_X509_FMT_PEM
);
953 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
954 ca_file
, gnutls_strerror(ret
)));
956 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
958 } else if (tlsp
->verify_peer
>= TLS_VERIFY_PEER_CA_ONLY
) {
959 DEBUG(0,("TLS failed to missing cafile %s - "
960 "with 'tls verify peer = %s'\n",
962 tls_verify_peer_string(tlsp
->verify_peer
)));
964 return NT_STATUS_INVALID_PARAMETER_MIX
;
967 if (crl_file
&& *crl_file
&& file_exist(crl_file
)) {
968 ret
= gnutls_certificate_set_x509_crl_file(tlsp
->x509_cred
,
970 GNUTLS_X509_FMT_PEM
);
972 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
973 crl_file
, gnutls_strerror(ret
)));
975 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
977 } else if (tlsp
->verify_peer
>= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE
) {
978 DEBUG(0,("TLS failed to missing crlfile %s - "
979 "with 'tls verify peer = %s'\n",
981 tls_verify_peer_string(tlsp
->verify_peer
)));
983 return NT_STATUS_INVALID_PARAMETER_MIX
;
986 tlsp
->tls_priority
= talloc_strdup(tlsp
, tls_priority
);
987 if (tlsp
->tls_priority
== NULL
) {
989 return NT_STATUS_NO_MEMORY
;
992 tlsp
->tls_enabled
= true;
998 struct tstream_tls_connect_state
{
999 struct tstream_context
*tls_stream
;
1002 struct tevent_req
*_tstream_tls_connect_send(TALLOC_CTX
*mem_ctx
,
1003 struct tevent_context
*ev
,
1004 struct tstream_context
*plain_stream
,
1005 struct tstream_tls_params
*_tls_params
,
1006 const char *location
)
1008 struct tevent_req
*req
;
1009 struct tstream_tls_connect_state
*state
;
1010 const char *error_pos
;
1011 struct tstream_tls
*tlss
;
1012 struct tstream_tls_params_internal
*tls_params
= NULL
;
1014 unsigned int flags
= GNUTLS_CLIENT
;
1016 req
= tevent_req_create(mem_ctx
, &state
,
1017 struct tstream_tls_connect_state
);
1022 state
->tls_stream
= tstream_context_create(state
,
1027 if (tevent_req_nomem(state
->tls_stream
, req
)) {
1028 return tevent_req_post(req
, ev
);
1031 talloc_set_destructor(tlss
, tstream_tls_destructor
);
1034 * Note we need to make sure x509_cred and dh_params
1035 * from tstream_tls_params_internal stay alive for
1036 * the whole lifetime of this session!
1038 * See 'man gnutls_credentials_set' and
1039 * 'man gnutls_certificate_set_dh_params'.
1041 * Note: here we use talloc_reference() in a way
1042 * that does not expose it to the caller.
1045 tls_params
= talloc_reference(tlss
, _tls_params
->internal
);
1046 if (tevent_req_nomem(tls_params
, req
)) {
1047 return tevent_req_post(req
, ev
);
1050 tlss
->plain_stream
= plain_stream
;
1051 tlss
->verify_peer
= tls_params
->verify_peer
;
1052 if (tls_params
->peer_name
!= NULL
) {
1053 tlss
->peer_name
= talloc_strdup(tlss
, tls_params
->peer_name
);
1054 if (tevent_req_nomem(tlss
->peer_name
, req
)) {
1055 return tevent_req_post(req
, ev
);
1059 tlss
->current_ev
= ev
;
1060 tlss
->retry_im
= tevent_create_immediate(tlss
);
1061 if (tevent_req_nomem(tlss
->retry_im
, req
)) {
1062 return tevent_req_post(req
, ev
);
1065 #ifdef GNUTLS_NO_TICKETS
1067 * tls_tstream can't properly handle 'New Session Ticket' messages
1068 * sent 'after' the client sends the 'Finished' message.
1069 * GNUTLS_NO_TICKETS was introduced in GnuTLS 3.5.6. This flag is to
1070 * indicate the session Flag session should not use resumption with
1073 flags
|= GNUTLS_NO_TICKETS
;
1076 ret
= gnutls_init(&tlss
->tls_session
, flags
);
1077 if (ret
!= GNUTLS_E_SUCCESS
) {
1078 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1079 tevent_req_error(req
, EINVAL
);
1080 return tevent_req_post(req
, ev
);
1083 ret
= gnutls_set_default_priority(tlss
->tls_session
);
1084 if (ret
!= GNUTLS_E_SUCCESS
) {
1085 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1086 __location__
, gnutls_strerror(ret
));
1087 tevent_req_error(req
, EINVAL
);
1088 return tevent_req_post(req
, ev
);
1091 if (strlen(tls_params
->tls_priority
) > 0) {
1092 ret
= gnutls_priority_set_direct(tlss
->tls_session
,
1093 tls_params
->tls_priority
,
1095 if (ret
!= GNUTLS_E_SUCCESS
) {
1096 DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1097 __location__
, gnutls_strerror(ret
), error_pos
));
1098 tevent_req_error(req
, EINVAL
);
1099 return tevent_req_post(req
, ev
);
1103 ret
= gnutls_credentials_set(tlss
->tls_session
,
1104 GNUTLS_CRD_CERTIFICATE
,
1105 tls_params
->x509_cred
);
1106 if (ret
!= GNUTLS_E_SUCCESS
) {
1107 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1108 tevent_req_error(req
, EINVAL
);
1109 return tevent_req_post(req
, ev
);
1112 gnutls_transport_set_ptr(tlss
->tls_session
,
1113 (gnutls_transport_ptr_t
)state
->tls_stream
);
1114 gnutls_transport_set_pull_function(tlss
->tls_session
,
1115 (gnutls_pull_func
)tstream_tls_pull_function
);
1116 gnutls_transport_set_push_function(tlss
->tls_session
,
1117 (gnutls_push_func
)tstream_tls_push_function
);
1119 tlss
->handshake
.req
= req
;
1120 tstream_tls_retry_handshake(state
->tls_stream
);
1121 if (!tevent_req_is_in_progress(req
)) {
1122 return tevent_req_post(req
, ev
);
1128 int tstream_tls_connect_recv(struct tevent_req
*req
,
1130 TALLOC_CTX
*mem_ctx
,
1131 struct tstream_context
**tls_stream
)
1133 struct tstream_tls_connect_state
*state
=
1134 tevent_req_data(req
,
1135 struct tstream_tls_connect_state
);
1137 if (tevent_req_is_unix_error(req
, perrno
)) {
1138 tevent_req_received(req
);
1142 *tls_stream
= talloc_move(mem_ctx
, &state
->tls_stream
);
1143 tevent_req_received(req
);
1148 initialise global tls state
1150 NTSTATUS
tstream_tls_params_server(TALLOC_CTX
*mem_ctx
,
1151 const char *dns_host_name
,
1153 const char *key_file
,
1154 const char *cert_file
,
1155 const char *ca_file
,
1156 const char *crl_file
,
1157 const char *dhp_file
,
1158 const char *tls_priority
,
1159 struct tstream_tls_params
**_tlsp
)
1161 struct tstream_tls_params
*__tlsp
= NULL
;
1162 struct tstream_tls_params_internal
*tlsp
= NULL
;
1166 if (!enabled
|| key_file
== NULL
|| *key_file
== 0) {
1167 __tlsp
= talloc_zero(mem_ctx
, struct tstream_tls_params
);
1168 if (__tlsp
== NULL
) {
1169 return NT_STATUS_NO_MEMORY
;
1172 tlsp
= talloc_zero(__tlsp
, struct tstream_tls_params_internal
);
1174 TALLOC_FREE(__tlsp
);
1175 return NT_STATUS_NO_MEMORY
;
1178 talloc_set_destructor(tlsp
, tstream_tls_params_internal_destructor
);
1179 __tlsp
->internal
= tlsp
;
1180 tlsp
->tls_enabled
= false;
1183 return NT_STATUS_OK
;
1186 __tlsp
= talloc_zero(mem_ctx
, struct tstream_tls_params
);
1187 if (__tlsp
== NULL
) {
1188 return NT_STATUS_NO_MEMORY
;
1191 tlsp
= talloc_zero(__tlsp
, struct tstream_tls_params_internal
);
1193 TALLOC_FREE(__tlsp
);
1194 return NT_STATUS_NO_MEMORY
;
1197 talloc_set_destructor(tlsp
, tstream_tls_params_internal_destructor
);
1198 __tlsp
->internal
= tlsp
;
1200 if (!file_exist(ca_file
)) {
1201 tls_cert_generate(tlsp
, dns_host_name
,
1202 key_file
, cert_file
, ca_file
);
1205 if (file_exist(key_file
) &&
1206 !file_check_permissions(key_file
, geteuid(), 0600, &st
))
1208 DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
1209 "owner uid %u should be %u, mode 0%o should be 0%o\n"
1210 "This is known as CVE-2013-4476.\n"
1211 "Removing all tls .pem files will cause an "
1212 "auto-regeneration with the correct permissions.\n",
1214 (unsigned int)st
.st_uid
, geteuid(),
1215 (unsigned int)(st
.st_mode
& 0777), 0600));
1216 TALLOC_FREE(__tlsp
);
1217 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1220 ret
= gnutls_certificate_allocate_credentials(&tlsp
->x509_cred
);
1221 if (ret
!= GNUTLS_E_SUCCESS
) {
1222 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1223 TALLOC_FREE(__tlsp
);
1224 return NT_STATUS_NO_MEMORY
;
1227 if (ca_file
&& *ca_file
) {
1228 ret
= gnutls_certificate_set_x509_trust_file(tlsp
->x509_cred
,
1230 GNUTLS_X509_FMT_PEM
);
1232 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1233 ca_file
, gnutls_strerror(ret
)));
1234 TALLOC_FREE(__tlsp
);
1235 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1239 if (crl_file
&& *crl_file
) {
1240 ret
= gnutls_certificate_set_x509_crl_file(tlsp
->x509_cred
,
1242 GNUTLS_X509_FMT_PEM
);
1244 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1245 crl_file
, gnutls_strerror(ret
)));
1246 TALLOC_FREE(__tlsp
);
1247 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1251 ret
= gnutls_certificate_set_x509_key_file(tlsp
->x509_cred
,
1252 cert_file
, key_file
,
1253 GNUTLS_X509_FMT_PEM
);
1254 if (ret
!= GNUTLS_E_SUCCESS
) {
1255 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1256 cert_file
, key_file
, gnutls_strerror(ret
)));
1257 TALLOC_FREE(__tlsp
);
1258 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1261 ret
= gnutls_dh_params_init(&tlsp
->dh_params
);
1262 if (ret
!= GNUTLS_E_SUCCESS
) {
1263 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1264 TALLOC_FREE(__tlsp
);
1265 return NT_STATUS_NO_MEMORY
;
1268 if (dhp_file
&& *dhp_file
) {
1269 gnutls_datum_t dhparms
;
1272 dhparms
.data
= (uint8_t *)file_load(dhp_file
, &size
, 0, tlsp
);
1274 if (!dhparms
.data
) {
1275 DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1276 dhp_file
, errno
, strerror(errno
)));
1277 TALLOC_FREE(__tlsp
);
1278 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1280 dhparms
.size
= size
;
1282 ret
= gnutls_dh_params_import_pkcs3(tlsp
->dh_params
,
1284 GNUTLS_X509_FMT_PEM
);
1285 if (ret
!= GNUTLS_E_SUCCESS
) {
1286 DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1287 dhp_file
, gnutls_strerror(ret
)));
1288 TALLOC_FREE(__tlsp
);
1289 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1292 ret
= gnutls_dh_params_generate2(tlsp
->dh_params
, DH_BITS
);
1293 if (ret
!= GNUTLS_E_SUCCESS
) {
1294 DEBUG(0,("TLS failed to generate dh_params - %s\n",
1295 gnutls_strerror(ret
)));
1296 TALLOC_FREE(__tlsp
);
1297 return NT_STATUS_INTERNAL_ERROR
;
1301 gnutls_certificate_set_dh_params(tlsp
->x509_cred
, tlsp
->dh_params
);
1303 tlsp
->tls_priority
= talloc_strdup(tlsp
, tls_priority
);
1304 if (tlsp
->tls_priority
== NULL
) {
1305 TALLOC_FREE(__tlsp
);
1306 return NT_STATUS_NO_MEMORY
;
1309 tlsp
->tls_enabled
= true;
1312 return NT_STATUS_OK
;
1315 struct tstream_tls_accept_state
{
1316 struct tstream_context
*tls_stream
;
1319 struct tevent_req
*_tstream_tls_accept_send(TALLOC_CTX
*mem_ctx
,
1320 struct tevent_context
*ev
,
1321 struct tstream_context
*plain_stream
,
1322 struct tstream_tls_params
*_tlsp
,
1323 const char *location
)
1325 struct tevent_req
*req
;
1326 struct tstream_tls_accept_state
*state
;
1327 struct tstream_tls
*tlss
;
1328 const char *error_pos
;
1329 struct tstream_tls_params_internal
*tlsp
= NULL
;
1332 req
= tevent_req_create(mem_ctx
, &state
,
1333 struct tstream_tls_accept_state
);
1338 state
->tls_stream
= tstream_context_create(state
,
1343 if (tevent_req_nomem(state
->tls_stream
, req
)) {
1344 return tevent_req_post(req
, ev
);
1347 talloc_set_destructor(tlss
, tstream_tls_destructor
);
1350 * Note we need to make sure x509_cred and dh_params
1351 * from tstream_tls_params_internal stay alive for
1352 * the whole lifetime of this session!
1354 * See 'man gnutls_credentials_set' and
1355 * 'man gnutls_certificate_set_dh_params'.
1357 * Note: here we use talloc_reference() in a way
1358 * that does not expose it to the caller.
1360 tlsp
= talloc_reference(tlss
, _tlsp
->internal
);
1361 if (tevent_req_nomem(tlsp
, req
)) {
1362 return tevent_req_post(req
, ev
);
1365 tlss
->plain_stream
= plain_stream
;
1367 tlss
->current_ev
= ev
;
1368 tlss
->retry_im
= tevent_create_immediate(tlss
);
1369 if (tevent_req_nomem(tlss
->retry_im
, req
)) {
1370 return tevent_req_post(req
, ev
);
1373 ret
= gnutls_init(&tlss
->tls_session
, GNUTLS_SERVER
);
1374 if (ret
!= GNUTLS_E_SUCCESS
) {
1375 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1376 tevent_req_error(req
, EINVAL
);
1377 return tevent_req_post(req
, ev
);
1380 ret
= gnutls_set_default_priority(tlss
->tls_session
);
1381 if (ret
!= GNUTLS_E_SUCCESS
) {
1382 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1383 __location__
, gnutls_strerror(ret
));
1384 tevent_req_error(req
, EINVAL
);
1385 return tevent_req_post(req
, ev
);
1388 if (strlen(tlsp
->tls_priority
) > 0) {
1389 ret
= gnutls_priority_set_direct(tlss
->tls_session
,
1392 if (ret
!= GNUTLS_E_SUCCESS
) {
1393 DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1394 __location__
, gnutls_strerror(ret
), error_pos
));
1395 tevent_req_error(req
, EINVAL
);
1396 return tevent_req_post(req
, ev
);
1400 ret
= gnutls_credentials_set(tlss
->tls_session
, GNUTLS_CRD_CERTIFICATE
,
1402 if (ret
!= GNUTLS_E_SUCCESS
) {
1403 DEBUG(0,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1404 tevent_req_error(req
, EINVAL
);
1405 return tevent_req_post(req
, ev
);
1408 gnutls_certificate_server_set_request(tlss
->tls_session
,
1409 GNUTLS_CERT_REQUEST
);
1410 gnutls_dh_set_prime_bits(tlss
->tls_session
, DH_BITS
);
1412 gnutls_transport_set_ptr(tlss
->tls_session
,
1413 (gnutls_transport_ptr_t
)state
->tls_stream
);
1414 gnutls_transport_set_pull_function(tlss
->tls_session
,
1415 (gnutls_pull_func
)tstream_tls_pull_function
);
1416 gnutls_transport_set_push_function(tlss
->tls_session
,
1417 (gnutls_push_func
)tstream_tls_push_function
);
1419 tlss
->handshake
.req
= req
;
1420 tstream_tls_retry_handshake(state
->tls_stream
);
1421 if (!tevent_req_is_in_progress(req
)) {
1422 return tevent_req_post(req
, ev
);
1428 static void tstream_tls_retry_handshake(struct tstream_context
*stream
)
1430 struct tstream_tls
*tlss
=
1431 tstream_context_data(stream
,
1432 struct tstream_tls
);
1433 struct tevent_req
*req
= tlss
->handshake
.req
;
1436 if (tlss
->error
!= 0) {
1437 tevent_req_error(req
, tlss
->error
);
1441 ret
= gnutls_handshake(tlss
->tls_session
);
1442 if (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
) {
1446 tlss
->handshake
.req
= NULL
;
1448 if (gnutls_error_is_fatal(ret
) != 0) {
1449 DEBUG(1,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1451 tevent_req_error(req
, tlss
->error
);
1455 if (ret
!= GNUTLS_E_SUCCESS
) {
1456 DEBUG(1,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1458 tevent_req_error(req
, tlss
->error
);
1462 if (tlss
->verify_peer
>= TLS_VERIFY_PEER_CA_ONLY
) {
1463 unsigned int status
= UINT32_MAX
;
1465 const char *hostname
= NULL
;
1467 if (tlss
->peer_name
!= NULL
) {
1468 ip
= is_ipaddress(tlss
->peer_name
);
1472 hostname
= tlss
->peer_name
;
1475 if (tlss
->verify_peer
== TLS_VERIFY_PEER_CA_ONLY
) {
1479 if (tlss
->verify_peer
>= TLS_VERIFY_PEER_CA_AND_NAME
) {
1480 if (hostname
== NULL
) {
1481 DEBUG(1,("TLS %s - no hostname available for "
1482 "verify_peer[%s] and peer_name[%s]\n",
1484 tls_verify_peer_string(tlss
->verify_peer
),
1486 tlss
->error
= EINVAL
;
1487 tevent_req_error(req
, tlss
->error
);
1492 ret
= gnutls_certificate_verify_peers3(tlss
->tls_session
,
1495 if (ret
!= GNUTLS_E_SUCCESS
) {
1496 DEBUG(1,("TLS %s - %s\n", __location__
, gnutls_strerror(ret
)));
1498 tevent_req_error(req
, tlss
->error
);
1503 DEBUG(1,("TLS %s - check failed for "
1504 "verify_peer[%s] and peer_name[%s] "
1505 "status 0x%x (%s%s%s%s%s%s%s%s)\n",
1507 tls_verify_peer_string(tlss
->verify_peer
),
1510 status
& GNUTLS_CERT_INVALID
? "invalid " : "",
1511 status
& GNUTLS_CERT_REVOKED
? "revoked " : "",
1512 status
& GNUTLS_CERT_SIGNER_NOT_FOUND
?
1513 "signer_not_found " : "",
1514 status
& GNUTLS_CERT_SIGNER_NOT_CA
?
1515 "signer_not_ca " : "",
1516 status
& GNUTLS_CERT_INSECURE_ALGORITHM
?
1517 "insecure_algorithm " : "",
1518 status
& GNUTLS_CERT_NOT_ACTIVATED
?
1519 "not_activated " : "",
1520 status
& GNUTLS_CERT_EXPIRED
?
1522 status
& GNUTLS_CERT_UNEXPECTED_OWNER
?
1523 "unexptected_owner " : ""));
1524 tlss
->error
= EINVAL
;
1525 tevent_req_error(req
, tlss
->error
);
1530 tevent_req_done(req
);
1533 int tstream_tls_accept_recv(struct tevent_req
*req
,
1535 TALLOC_CTX
*mem_ctx
,
1536 struct tstream_context
**tls_stream
)
1538 struct tstream_tls_accept_state
*state
=
1539 tevent_req_data(req
,
1540 struct tstream_tls_accept_state
);
1542 if (tevent_req_is_unix_error(req
, perrno
)) {
1543 tevent_req_received(req
);
1547 *tls_stream
= talloc_move(mem_ctx
, &state
->tls_stream
);
1548 tevent_req_received(req
);