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 ret = gnutls_global_init();
991 if (ret != GNUTLS_E_SUCCESS) {
992 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
993 return NT_STATUS_NOT_SUPPORTED;
996 tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
997 NT_STATUS_HAVE_NO_MEMORY(tlsp);
999 talloc_set_destructor(tlsp, tstream_tls_params_destructor);
1001 if (!file_exist(ca_file)) {
1002 tls_cert_generate(tlsp, dns_host_name,
1003 key_file, cert_file, ca_file);
1006 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
1007 if (ret != GNUTLS_E_SUCCESS) {
1008 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1010 return NT_STATUS_NO_MEMORY;
1013 if (ca_file && *ca_file) {
1014 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1016 GNUTLS_X509_FMT_PEM);
1018 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1019 ca_file, gnutls_strerror(ret)));
1021 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1025 if (crl_file && *crl_file) {
1026 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1028 GNUTLS_X509_FMT_PEM);
1030 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1031 crl_file, gnutls_strerror(ret)));
1033 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1037 ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
1038 cert_file, key_file,
1039 GNUTLS_X509_FMT_PEM);
1040 if (ret != GNUTLS_E_SUCCESS) {
1041 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1042 cert_file, key_file, gnutls_strerror(ret)));
1044 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1047 ret = gnutls_dh_params_init(&tlsp->dh_params);
1048 if (ret != GNUTLS_E_SUCCESS) {
1049 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1051 return NT_STATUS_NO_MEMORY;
1054 if (dhp_file && *dhp_file) {
1055 gnutls_datum_t dhparms;
1058 dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
1060 if (!dhparms.data) {
1061 DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1062 dhp_file, errno, strerror(errno)));
1064 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1066 dhparms.size = size;
1068 ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
1070 GNUTLS_X509_FMT_PEM);
1071 if (ret != GNUTLS_E_SUCCESS) {
1072 DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1073 dhp_file, gnutls_strerror(ret)));
1075 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1078 ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
1079 if (ret != GNUTLS_E_SUCCESS) {
1080 DEBUG(0,("TLS failed to generate dh_params - %s\n",
1081 gnutls_strerror(ret)));
1083 return NT_STATUS_INTERNAL_ERROR;
1087 gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
1089 tlsp->tls_enabled = true;
1091 #else /* ENABLE_GNUTLS */
1092 tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1093 NT_STATUS_HAVE_NO_MEMORY(tlsp);
1094 talloc_set_destructor(tlsp, tstream_tls_params_destructor);
1095 tlsp->tls_enabled = false;
1096 #endif /* ENABLE_GNUTLS */
1099 return NT_STATUS_OK;
1102 struct tstream_tls_accept_state {
1103 struct tstream_context *tls_stream;
1106 struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
1107 struct tevent_context *ev,
1108 struct tstream_context *plain_stream,
1109 struct tstream_tls_params *tlsp,
1110 const char *location)
1112 struct tevent_req *req;
1113 struct tstream_tls_accept_state *state;
1114 struct tstream_tls *tlss;
1117 #endif /* ENABLE_GNUTLS */
1119 req = tevent_req_create(mem_ctx, &state,
1120 struct tstream_tls_accept_state);
1125 state->tls_stream = tstream_context_create(state,
1130 if (tevent_req_nomem(state->tls_stream, req)) {
1131 return tevent_req_post(req, ev);
1134 talloc_set_destructor(tlss, tstream_tls_destructor);
1137 tlss->plain_stream = plain_stream;
1139 tlss->current_ev = ev;
1140 tlss->im = tevent_create_immediate(tlss);
1141 if (tevent_req_nomem(tlss->im, req)) {
1142 return tevent_req_post(req, ev);
1145 ret = gnutls_init(&tlss->tls_session, GNUTLS_SERVER);
1146 if (ret != GNUTLS_E_SUCCESS) {
1147 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1148 tevent_req_error(req, EINVAL);
1149 return tevent_req_post(req, ev);
1152 ret = gnutls_set_default_priority(tlss->tls_session);
1153 if (ret != GNUTLS_E_SUCCESS) {
1154 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1155 tevent_req_error(req, EINVAL);
1156 return tevent_req_post(req, ev);
1159 ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE,
1161 if (ret != GNUTLS_E_SUCCESS) {
1162 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1163 tevent_req_error(req, EINVAL);
1164 return tevent_req_post(req, ev);
1167 gnutls_certificate_server_set_request(tlss->tls_session,
1168 GNUTLS_CERT_REQUEST);
1169 gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
1171 gnutls_transport_set_ptr(tlss->tls_session, (gnutls_transport_ptr)state->tls_stream);
1172 gnutls_transport_set_pull_function(tlss->tls_session,
1173 (gnutls_pull_func)tstream_tls_pull_function);
1174 gnutls_transport_set_push_function(tlss->tls_session,
1175 (gnutls_push_func)tstream_tls_push_function);
1176 gnutls_transport_set_lowat(tlss->tls_session, 0);
1178 tlss->handshake.req = req;
1179 tstream_tls_retry_handshake(state->tls_stream);
1180 if (!tevent_req_is_in_progress(req)) {
1181 return tevent_req_post(req, ev);
1185 #else /* ENABLE_GNUTLS */
1186 tevent_req_error(req, ENOSYS);
1187 return tevent_req_post(req, ev);
1188 #endif /* ENABLE_GNUTLS */
1191 static void tstream_tls_retry_handshake(struct tstream_context *stream)
1193 struct tstream_tls *tlss =
1194 tstream_context_data(stream,
1195 struct tstream_tls);
1196 struct tevent_req *req = tlss->handshake.req;
1200 if (tlss->error != 0) {
1201 tevent_req_error(req, tlss->error);
1205 ret = gnutls_handshake(tlss->tls_session);
1206 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
1210 tlss->handshake.req = NULL;
1212 if (gnutls_error_is_fatal(ret) != 0) {
1213 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1215 tevent_req_error(req, tlss->error);
1219 if (ret != GNUTLS_E_SUCCESS) {
1220 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1222 tevent_req_error(req, tlss->error);
1226 tevent_req_done(req);
1227 #else /* ENABLE_GNUTLS */
1228 tevent_req_error(req, ENOSYS);
1229 #endif /* ENABLE_GNUTLS */
1232 int tstream_tls_accept_recv(struct tevent_req *req,
1234 TALLOC_CTX *mem_ctx,
1235 struct tstream_context **tls_stream)
1237 struct tstream_tls_accept_state *state =
1238 tevent_req_data(req,
1239 struct tstream_tls_accept_state);
1241 if (tevent_req_is_unix_error(req, perrno)) {
1242 tevent_req_received(req);
1246 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1247 tevent_req_received(req);