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 "../util/tevent_unix.h"
23 #include "../lib/tsocket/tsocket.h"
24 #include "../lib/tsocket/tsocket_internal.h"
25 #include "lib/tls/tls.h"
28 #include "gnutls/gnutls.h"
32 #if defined(HAVE_GNUTLS_DATUM) && !defined(HAVE_GNUTLS_DATUM_T)
33 typedef gnutls_datum gnutls_datum_t;
36 #endif /* ENABLE_GNUTLS */
38 static const struct tstream_context_ops tstream_tls_ops;
41 struct tstream_context *plain_stream;
45 gnutls_session tls_session;
46 #endif /* ENABLE_GNUTLS */
48 struct tevent_context *current_ev;
50 struct tevent_immediate *im;
55 struct tevent_req *subreq;
59 struct tevent_req *req;
66 struct tevent_req *req;
73 struct tevent_req *req;
77 struct tevent_req *req;
81 static void tstream_tls_retry_handshake(struct tstream_context *stream);
82 static void tstream_tls_retry_read(struct tstream_context *stream);
83 static void tstream_tls_retry_write(struct tstream_context *stream);
84 static void tstream_tls_retry_disconnect(struct tstream_context *stream);
85 static void tstream_tls_retry_trigger(struct tevent_context *ctx,
86 struct tevent_immediate *im,
89 static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
92 struct tstream_tls *tlss =
93 tstream_context_data(stream,
96 if (tlss->disconnect.req) {
97 tstream_tls_retry_disconnect(stream);
101 if (tlss->handshake.req) {
102 tstream_tls_retry_handshake(stream);
106 if (tlss->write.req && tlss->read.req && !deferred) {
107 tevent_schedule_immediate(tlss->im, tlss->current_ev,
108 tstream_tls_retry_trigger,
112 if (tlss->write.req) {
113 tstream_tls_retry_write(stream);
117 if (tlss->read.req) {
118 tstream_tls_retry_read(stream);
123 static void tstream_tls_retry_trigger(struct tevent_context *ctx,
124 struct tevent_immediate *im,
127 struct tstream_context *stream =
128 talloc_get_type_abort(private_data,
129 struct tstream_context);
131 tstream_tls_retry(stream, true);
135 static void tstream_tls_push_done(struct tevent_req *subreq);
137 static ssize_t tstream_tls_push_function(gnutls_transport_ptr ptr,
138 const void *buf, size_t size)
140 struct tstream_context *stream =
141 talloc_get_type_abort(ptr,
142 struct tstream_context);
143 struct tstream_tls *tlss =
144 tstream_context_data(stream,
146 struct tevent_req *subreq;
148 if (tlss->error != 0) {
153 if (tlss->push.subreq) {
158 tlss->push.iov.iov_base = tlss->push.buffer;
159 tlss->push.iov.iov_len = MIN(size, sizeof(tlss->push.buffer));
161 memcpy(tlss->push.buffer, buf, tlss->push.iov.iov_len);
163 subreq = tstream_writev_send(tlss,
167 if (subreq == NULL) {
171 tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
173 tlss->push.subreq = subreq;
175 return tlss->push.iov.iov_len;
178 static void tstream_tls_push_done(struct tevent_req *subreq)
180 struct tstream_context *stream =
181 tevent_req_callback_data(subreq,
182 struct tstream_context);
183 struct tstream_tls *tlss =
184 tstream_context_data(stream,
189 tlss->push.subreq = NULL;
190 ZERO_STRUCT(tlss->push.iov);
192 ret = tstream_writev_recv(subreq, &sys_errno);
195 tlss->error = sys_errno;
196 tstream_tls_retry(stream, false);
200 tstream_tls_retry(stream, false);
203 static void tstream_tls_pull_done(struct tevent_req *subreq);
205 static ssize_t tstream_tls_pull_function(gnutls_transport_ptr ptr,
206 void *buf, size_t size)
208 struct tstream_context *stream =
209 talloc_get_type_abort(ptr,
210 struct tstream_context);
211 struct tstream_tls *tlss =
212 tstream_context_data(stream,
214 struct tevent_req *subreq;
216 if (tlss->error != 0) {
221 if (tlss->pull.subreq) {
226 if (tlss->pull.iov.iov_base) {
229 n = MIN(tlss->pull.iov.iov_len, size);
230 memcpy(buf, tlss->pull.iov.iov_base, n);
232 tlss->pull.iov.iov_len -= n;
233 if (tlss->pull.iov.iov_len == 0) {
234 tlss->pull.iov.iov_base = NULL;
244 tlss->pull.iov.iov_base = tlss->pull.buffer;
245 tlss->pull.iov.iov_len = MIN(size, sizeof(tlss->pull.buffer));
247 subreq = tstream_readv_send(tlss,
251 if (subreq == NULL) {
255 tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
257 tlss->pull.subreq = subreq;
262 static void tstream_tls_pull_done(struct tevent_req *subreq)
264 struct tstream_context *stream =
265 tevent_req_callback_data(subreq,
266 struct tstream_context);
267 struct tstream_tls *tlss =
268 tstream_context_data(stream,
273 tlss->pull.subreq = NULL;
275 ret = tstream_readv_recv(subreq, &sys_errno);
278 tlss->error = sys_errno;
279 tstream_tls_retry(stream, false);
283 tstream_tls_retry(stream, false);
285 #endif /* ENABLE_GNUTLS */
287 static int tstream_tls_destructor(struct tstream_tls *tlss)
290 if (tlss->tls_session) {
291 gnutls_deinit(tlss->tls_session);
292 tlss->tls_session = NULL;
294 #endif /* ENABLE_GNUTLS */
298 static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
300 struct tstream_tls *tlss =
301 tstream_context_data(stream,
305 if (tlss->error != 0) {
311 ret = gnutls_record_check_pending(tlss->tls_session);
312 ret += tlss->read.left;
313 #else /* ENABLE_GNUTLS */
316 #endif /* ENABLE_GNUTLS */
320 struct tstream_tls_readv_state {
321 struct tstream_context *stream;
323 struct iovec *vector;
329 static void tstream_tls_readv_crypt_next(struct tevent_req *req);
331 static struct tevent_req *tstream_tls_readv_send(TALLOC_CTX *mem_ctx,
332 struct tevent_context *ev,
333 struct tstream_context *stream,
334 struct iovec *vector,
337 struct tstream_tls *tlss =
338 tstream_context_data(stream,
340 struct tevent_req *req;
341 struct tstream_tls_readv_state *state;
343 tlss->read.req = NULL;
344 tlss->current_ev = ev;
346 req = tevent_req_create(mem_ctx, &state,
347 struct tstream_tls_readv_state);
352 state->stream = stream;
355 if (tlss->error != 0) {
356 tevent_req_error(req, tlss->error);
357 return tevent_req_post(req, ev);
361 * we make a copy of the vector so we can change the structure
363 state->vector = talloc_array(state, struct iovec, count);
364 if (tevent_req_nomem(state->vector, req)) {
365 return tevent_req_post(req, ev);
367 memcpy(state->vector, vector, sizeof(struct iovec) * count);
368 state->count = count;
370 tstream_tls_readv_crypt_next(req);
371 if (!tevent_req_is_in_progress(req)) {
372 return tevent_req_post(req, ev);
378 static void tstream_tls_readv_crypt_next(struct tevent_req *req)
380 struct tstream_tls_readv_state *state =
382 struct tstream_tls_readv_state);
383 struct tstream_tls *tlss =
384 tstream_context_data(state->stream,
388 * copy the pending buffer first
390 while (tlss->read.left > 0 && state->count > 0) {
391 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
392 size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
394 memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
397 state->vector[0].iov_base = base;
398 state->vector[0].iov_len -= len;
400 tlss->read.ofs += len;
401 tlss->read.left -= len;
403 if (state->vector[0].iov_len == 0) {
411 if (state->count == 0) {
412 tevent_req_done(req);
416 tlss->read.req = req;
417 tstream_tls_retry_read(state->stream);
420 static void tstream_tls_retry_read(struct tstream_context *stream)
422 struct tstream_tls *tlss =
423 tstream_context_data(stream,
425 struct tevent_req *req = tlss->read.req;
429 if (tlss->error != 0) {
430 tevent_req_error(req, tlss->error);
437 ret = gnutls_record_recv(tlss->tls_session,
439 sizeof(tlss->read.buffer));
440 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
444 tlss->read.req = NULL;
446 if (gnutls_error_is_fatal(ret) != 0) {
447 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
449 tevent_req_error(req, tlss->error);
455 tevent_req_error(req, tlss->error);
459 tlss->read.left = ret;
460 tstream_tls_readv_crypt_next(req);
461 #else /* ENABLE_GNUTLS */
462 tevent_req_error(req, ENOSYS);
463 #endif /* ENABLE_GNUTLS */
466 static int tstream_tls_readv_recv(struct tevent_req *req,
469 struct tstream_tls_readv_state *state =
471 struct tstream_tls_readv_state);
472 struct tstream_tls *tlss =
473 tstream_context_data(state->stream,
477 tlss->read.req = NULL;
479 ret = tsocket_simple_int_recv(req, perrno);
484 tevent_req_received(req);
488 struct tstream_tls_writev_state {
489 struct tstream_context *stream;
491 struct iovec *vector;
497 static void tstream_tls_writev_crypt_next(struct tevent_req *req);
499 static struct tevent_req *tstream_tls_writev_send(TALLOC_CTX *mem_ctx,
500 struct tevent_context *ev,
501 struct tstream_context *stream,
502 const struct iovec *vector,
505 struct tstream_tls *tlss =
506 tstream_context_data(stream,
508 struct tevent_req *req;
509 struct tstream_tls_writev_state *state;
511 tlss->write.req = NULL;
512 tlss->current_ev = ev;
514 req = tevent_req_create(mem_ctx, &state,
515 struct tstream_tls_writev_state);
520 state->stream = stream;
523 if (tlss->error != 0) {
524 tevent_req_error(req, tlss->error);
525 return tevent_req_post(req, ev);
529 * we make a copy of the vector so we can change the structure
531 state->vector = talloc_array(state, struct iovec, count);
532 if (tevent_req_nomem(state->vector, req)) {
533 return tevent_req_post(req, ev);
535 memcpy(state->vector, vector, sizeof(struct iovec) * count);
536 state->count = count;
538 tstream_tls_writev_crypt_next(req);
539 if (!tevent_req_is_in_progress(req)) {
540 return tevent_req_post(req, ev);
546 static void tstream_tls_writev_crypt_next(struct tevent_req *req)
548 struct tstream_tls_writev_state *state =
550 struct tstream_tls_writev_state);
551 struct tstream_tls *tlss =
552 tstream_context_data(state->stream,
555 tlss->write.left = sizeof(tlss->write.buffer);
559 * first fill our buffer
561 while (tlss->write.left > 0 && state->count > 0) {
562 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
563 size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
565 memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
568 state->vector[0].iov_base = base;
569 state->vector[0].iov_len -= len;
571 tlss->write.ofs += len;
572 tlss->write.left -= len;
574 if (state->vector[0].iov_len == 0) {
582 if (tlss->write.ofs == 0) {
583 tevent_req_done(req);
587 tlss->write.left = tlss->write.ofs;
590 tlss->write.req = req;
591 tstream_tls_retry_write(state->stream);
594 static void tstream_tls_retry_write(struct tstream_context *stream)
596 struct tstream_tls *tlss =
597 tstream_context_data(stream,
599 struct tevent_req *req = tlss->write.req;
603 if (tlss->error != 0) {
604 tevent_req_error(req, tlss->error);
608 ret = gnutls_record_send(tlss->tls_session,
609 tlss->write.buffer + tlss->write.ofs,
611 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
615 tlss->write.req = NULL;
617 if (gnutls_error_is_fatal(ret) != 0) {
618 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
620 tevent_req_error(req, tlss->error);
626 tevent_req_error(req, tlss->error);
630 tlss->write.ofs += ret;
631 tlss->write.left -= ret;
633 if (tlss->write.left > 0) {
634 tlss->write.req = req;
635 tstream_tls_retry_write(stream);
639 tstream_tls_writev_crypt_next(req);
640 #else /* ENABLE_GNUTLS */
641 tevent_req_error(req, ENOSYS);
642 #endif /* ENABLE_GNUTLS */
645 static int tstream_tls_writev_recv(struct tevent_req *req,
648 struct tstream_tls_writev_state *state =
650 struct tstream_tls_writev_state);
651 struct tstream_tls *tlss =
652 tstream_context_data(state->stream,
656 tlss->write.req = NULL;
658 ret = tsocket_simple_int_recv(req, perrno);
663 tevent_req_received(req);
667 struct tstream_tls_disconnect_state {
671 static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
672 struct tevent_context *ev,
673 struct tstream_context *stream)
675 struct tstream_tls *tlss =
676 tstream_context_data(stream,
678 struct tevent_req *req;
679 struct tstream_tls_disconnect_state *state;
681 tlss->disconnect.req = NULL;
682 tlss->current_ev = ev;
684 req = tevent_req_create(mem_ctx, &state,
685 struct tstream_tls_disconnect_state);
690 if (tlss->error != 0) {
691 tevent_req_error(req, tlss->error);
692 return tevent_req_post(req, ev);
695 tlss->disconnect.req = req;
696 tstream_tls_retry_disconnect(stream);
697 if (!tevent_req_is_in_progress(req)) {
698 return tevent_req_post(req, ev);
704 static void tstream_tls_retry_disconnect(struct tstream_context *stream)
706 struct tstream_tls *tlss =
707 tstream_context_data(stream,
709 struct tevent_req *req = tlss->disconnect.req;
713 if (tlss->error != 0) {
714 tevent_req_error(req, tlss->error);
718 ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
719 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
723 tlss->disconnect.req = NULL;
725 if (gnutls_error_is_fatal(ret) != 0) {
726 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
728 tevent_req_error(req, tlss->error);
732 if (ret != GNUTLS_E_SUCCESS) {
733 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
735 tevent_req_error(req, tlss->error);
739 tevent_req_done(req);
740 #else /* ENABLE_GNUTLS */
741 tevent_req_error(req, ENOSYS);
742 #endif /* ENABLE_GNUTLS */
745 static int tstream_tls_disconnect_recv(struct tevent_req *req,
750 ret = tsocket_simple_int_recv(req, perrno);
752 tevent_req_received(req);
756 static const struct tstream_context_ops tstream_tls_ops = {
759 .pending_bytes = tstream_tls_pending_bytes,
761 .readv_send = tstream_tls_readv_send,
762 .readv_recv = tstream_tls_readv_recv,
764 .writev_send = tstream_tls_writev_send,
765 .writev_recv = tstream_tls_writev_recv,
767 .disconnect_send = tstream_tls_disconnect_send,
768 .disconnect_recv = tstream_tls_disconnect_recv,
771 struct tstream_tls_params {
773 gnutls_certificate_credentials x509_cred;
774 gnutls_dh_params dh_params;
775 #endif /* ENABLE_GNUTLS */
779 static int tstream_tls_params_destructor(struct tstream_tls_params *tlsp)
782 if (tlsp->x509_cred) {
783 gnutls_certificate_free_credentials(tlsp->x509_cred);
784 tlsp->x509_cred = NULL;
786 if (tlsp->dh_params) {
787 gnutls_dh_params_deinit(tlsp->dh_params);
788 tlsp->dh_params = NULL;
790 #endif /* ENABLE_GNUTLS */
794 bool tstream_tls_params_enabled(struct tstream_tls_params *tlsp)
796 return tlsp->tls_enabled;
799 NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
801 const char *crl_file,
802 struct tstream_tls_params **_tlsp)
805 struct tstream_tls_params *tlsp;
808 ret = gnutls_global_init();
809 if (ret != GNUTLS_E_SUCCESS) {
810 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
811 return NT_STATUS_NOT_SUPPORTED;
814 tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
815 NT_STATUS_HAVE_NO_MEMORY(tlsp);
817 talloc_set_destructor(tlsp, tstream_tls_params_destructor);
819 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
820 if (ret != GNUTLS_E_SUCCESS) {
821 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
823 return NT_STATUS_NO_MEMORY;
826 if (ca_file && *ca_file) {
827 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
829 GNUTLS_X509_FMT_PEM);
831 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
832 ca_file, gnutls_strerror(ret)));
834 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
838 if (crl_file && *crl_file) {
839 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
841 GNUTLS_X509_FMT_PEM);
843 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
844 crl_file, gnutls_strerror(ret)));
846 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
850 tlsp->tls_enabled = true;
854 #else /* ENABLE_GNUTLS */
855 return NT_STATUS_NOT_IMPLEMENTED;
856 #endif /* ENABLE_GNUTLS */
859 struct tstream_tls_connect_state {
860 struct tstream_context *tls_stream;
863 struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
864 struct tevent_context *ev,
865 struct tstream_context *plain_stream,
866 struct tstream_tls_params *tls_params,
867 const char *location)
869 struct tevent_req *req;
870 struct tstream_tls_connect_state *state;
872 struct tstream_tls *tlss;
874 static const int cert_type_priority[] = {
879 #endif /* ENABLE_GNUTLS */
881 req = tevent_req_create(mem_ctx, &state,
882 struct tstream_tls_connect_state);
888 state->tls_stream = tstream_context_create(state,
893 if (tevent_req_nomem(state->tls_stream, req)) {
894 return tevent_req_post(req, ev);
897 talloc_set_destructor(tlss, tstream_tls_destructor);
899 tlss->plain_stream = plain_stream;
901 tlss->current_ev = ev;
902 tlss->im = tevent_create_immediate(tlss);
903 if (tevent_req_nomem(tlss->im, req)) {
904 return tevent_req_post(req, ev);
907 ret = gnutls_init(&tlss->tls_session, GNUTLS_CLIENT);
908 if (ret != GNUTLS_E_SUCCESS) {
909 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
910 tevent_req_error(req, EINVAL);
911 return tevent_req_post(req, ev);
914 ret = gnutls_set_default_priority(tlss->tls_session);
915 if (ret != GNUTLS_E_SUCCESS) {
916 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
917 tevent_req_error(req, EINVAL);
918 return tevent_req_post(req, ev);
921 gnutls_certificate_type_set_priority(tlss->tls_session, cert_type_priority);
923 ret = gnutls_credentials_set(tlss->tls_session,
924 GNUTLS_CRD_CERTIFICATE,
925 tls_params->x509_cred);
926 if (ret != GNUTLS_E_SUCCESS) {
927 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
928 tevent_req_error(req, EINVAL);
929 return tevent_req_post(req, ev);
932 gnutls_transport_set_ptr(tlss->tls_session, (gnutls_transport_ptr)state->tls_stream);
933 gnutls_transport_set_pull_function(tlss->tls_session,
934 (gnutls_pull_func)tstream_tls_pull_function);
935 gnutls_transport_set_push_function(tlss->tls_session,
936 (gnutls_push_func)tstream_tls_push_function);
937 gnutls_transport_set_lowat(tlss->tls_session, 0);
939 tlss->handshake.req = req;
940 tstream_tls_retry_handshake(state->tls_stream);
941 if (!tevent_req_is_in_progress(req)) {
942 return tevent_req_post(req, ev);
946 #else /* ENABLE_GNUTLS */
947 tevent_req_error(req, ENOSYS);
948 return tevent_req_post(req, ev);
949 #endif /* ENABLE_GNUTLS */
952 int tstream_tls_connect_recv(struct tevent_req *req,
955 struct tstream_context **tls_stream)
957 struct tstream_tls_connect_state *state =
959 struct tstream_tls_connect_state);
961 if (tevent_req_is_unix_error(req, perrno)) {
962 tevent_req_received(req);
966 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
967 tevent_req_received(req);
971 extern void tls_cert_generate(TALLOC_CTX *, const char *, const char *, const char *, const char *);
974 initialise global tls state
976 NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
977 const char *dns_host_name,
979 const char *key_file,
980 const char *cert_file,
982 const char *crl_file,
983 const char *dhp_file,
984 struct tstream_tls_params **_tlsp)
986 struct tstream_tls_params *tlsp;
990 if (!enabled || key_file == NULL || *key_file == 0) {
991 tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
992 NT_STATUS_HAVE_NO_MEMORY(tlsp);
993 talloc_set_destructor(tlsp, tstream_tls_params_destructor);
994 tlsp->tls_enabled = false;
1000 ret = gnutls_global_init();
1001 if (ret != GNUTLS_E_SUCCESS) {
1002 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1003 return NT_STATUS_NOT_SUPPORTED;
1006 tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1007 NT_STATUS_HAVE_NO_MEMORY(tlsp);
1009 talloc_set_destructor(tlsp, tstream_tls_params_destructor);
1011 if (!file_exist(ca_file)) {
1012 tls_cert_generate(tlsp, dns_host_name,
1013 key_file, cert_file, ca_file);
1016 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
1017 if (ret != GNUTLS_E_SUCCESS) {
1018 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1020 return NT_STATUS_NO_MEMORY;
1023 if (ca_file && *ca_file) {
1024 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1026 GNUTLS_X509_FMT_PEM);
1028 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1029 ca_file, gnutls_strerror(ret)));
1031 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1035 if (crl_file && *crl_file) {
1036 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1038 GNUTLS_X509_FMT_PEM);
1040 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1041 crl_file, gnutls_strerror(ret)));
1043 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1047 ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
1048 cert_file, key_file,
1049 GNUTLS_X509_FMT_PEM);
1050 if (ret != GNUTLS_E_SUCCESS) {
1051 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1052 cert_file, key_file, gnutls_strerror(ret)));
1054 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1057 ret = gnutls_dh_params_init(&tlsp->dh_params);
1058 if (ret != GNUTLS_E_SUCCESS) {
1059 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1061 return NT_STATUS_NO_MEMORY;
1064 if (dhp_file && *dhp_file) {
1065 gnutls_datum_t dhparms;
1068 dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
1070 if (!dhparms.data) {
1071 DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1072 dhp_file, errno, strerror(errno)));
1074 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1076 dhparms.size = size;
1078 ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
1080 GNUTLS_X509_FMT_PEM);
1081 if (ret != GNUTLS_E_SUCCESS) {
1082 DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1083 dhp_file, gnutls_strerror(ret)));
1085 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1088 ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
1089 if (ret != GNUTLS_E_SUCCESS) {
1090 DEBUG(0,("TLS failed to generate dh_params - %s\n",
1091 gnutls_strerror(ret)));
1093 return NT_STATUS_INTERNAL_ERROR;
1097 gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
1099 tlsp->tls_enabled = true;
1101 #else /* ENABLE_GNUTLS */
1102 tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1103 NT_STATUS_HAVE_NO_MEMORY(tlsp);
1104 talloc_set_destructor(tlsp, tstream_tls_params_destructor);
1105 tlsp->tls_enabled = false;
1106 #endif /* ENABLE_GNUTLS */
1109 return NT_STATUS_OK;
1112 struct tstream_tls_accept_state {
1113 struct tstream_context *tls_stream;
1116 struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
1117 struct tevent_context *ev,
1118 struct tstream_context *plain_stream,
1119 struct tstream_tls_params *tlsp,
1120 const char *location)
1122 struct tevent_req *req;
1123 struct tstream_tls_accept_state *state;
1124 struct tstream_tls *tlss;
1127 #endif /* ENABLE_GNUTLS */
1129 req = tevent_req_create(mem_ctx, &state,
1130 struct tstream_tls_accept_state);
1135 state->tls_stream = tstream_context_create(state,
1140 if (tevent_req_nomem(state->tls_stream, req)) {
1141 return tevent_req_post(req, ev);
1144 talloc_set_destructor(tlss, tstream_tls_destructor);
1147 tlss->plain_stream = plain_stream;
1149 tlss->current_ev = ev;
1150 tlss->im = tevent_create_immediate(tlss);
1151 if (tevent_req_nomem(tlss->im, req)) {
1152 return tevent_req_post(req, ev);
1155 ret = gnutls_init(&tlss->tls_session, GNUTLS_SERVER);
1156 if (ret != GNUTLS_E_SUCCESS) {
1157 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1158 tevent_req_error(req, EINVAL);
1159 return tevent_req_post(req, ev);
1162 ret = gnutls_set_default_priority(tlss->tls_session);
1163 if (ret != GNUTLS_E_SUCCESS) {
1164 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1165 tevent_req_error(req, EINVAL);
1166 return tevent_req_post(req, ev);
1169 ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE,
1171 if (ret != GNUTLS_E_SUCCESS) {
1172 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1173 tevent_req_error(req, EINVAL);
1174 return tevent_req_post(req, ev);
1177 gnutls_certificate_server_set_request(tlss->tls_session,
1178 GNUTLS_CERT_REQUEST);
1179 gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
1181 gnutls_transport_set_ptr(tlss->tls_session, (gnutls_transport_ptr)state->tls_stream);
1182 gnutls_transport_set_pull_function(tlss->tls_session,
1183 (gnutls_pull_func)tstream_tls_pull_function);
1184 gnutls_transport_set_push_function(tlss->tls_session,
1185 (gnutls_push_func)tstream_tls_push_function);
1186 gnutls_transport_set_lowat(tlss->tls_session, 0);
1188 tlss->handshake.req = req;
1189 tstream_tls_retry_handshake(state->tls_stream);
1190 if (!tevent_req_is_in_progress(req)) {
1191 return tevent_req_post(req, ev);
1195 #else /* ENABLE_GNUTLS */
1196 tevent_req_error(req, ENOSYS);
1197 return tevent_req_post(req, ev);
1198 #endif /* ENABLE_GNUTLS */
1201 static void tstream_tls_retry_handshake(struct tstream_context *stream)
1203 struct tstream_tls *tlss =
1204 tstream_context_data(stream,
1205 struct tstream_tls);
1206 struct tevent_req *req = tlss->handshake.req;
1210 if (tlss->error != 0) {
1211 tevent_req_error(req, tlss->error);
1215 ret = gnutls_handshake(tlss->tls_session);
1216 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
1220 tlss->handshake.req = NULL;
1222 if (gnutls_error_is_fatal(ret) != 0) {
1223 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1225 tevent_req_error(req, tlss->error);
1229 if (ret != GNUTLS_E_SUCCESS) {
1230 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1232 tevent_req_error(req, tlss->error);
1236 tevent_req_done(req);
1237 #else /* ENABLE_GNUTLS */
1238 tevent_req_error(req, ENOSYS);
1239 #endif /* ENABLE_GNUTLS */
1242 int tstream_tls_accept_recv(struct tevent_req *req,
1244 TALLOC_CTX *mem_ctx,
1245 struct tstream_context **tls_stream)
1247 struct tstream_tls_accept_state *state =
1248 tevent_req_data(req,
1249 struct tstream_tls_accept_state);
1251 if (tevent_req_is_unix_error(req, perrno)) {
1252 tevent_req_received(req);
1256 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1257 tevent_req_received(req);