2 Unix SMB/CIFS implementation.
4 transport layer security handling code
6 Copyright (C) Andrew Tridgell 2004-2005
7 Copyright (C) Stefan Metzmacher 2004
8 Copyright (C) Andrew Bartlett 2006
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "lib/events/events.h"
26 #include "lib/socket/socket.h"
27 #include "lib/tls/tls.h"
28 #include "param/param.h"
31 #include <gnutls/gnutls.h>
35 #if defined(HAVE_GNUTLS_DATUM) && !defined(HAVE_GNUTLS_DATUM_T)
36 typedef gnutls_datum gnutls_datum_t
;
39 /* hold persistent tls data */
41 gnutls_certificate_credentials x509_cred
;
42 gnutls_dh_params dh_params
;
47 /* hold per connection tls data */
49 struct socket_context
*socket
;
50 struct tevent_fd
*fde
;
53 gnutls_session session
;
58 const char *plain_chars
;
60 gnutls_certificate_credentials xcred
;
65 bool tls_enabled(struct socket_context
*sock
)
67 struct tls_context
*tls
;
71 if (strcmp(sock
->backend_name
, "tls") != 0) {
74 tls
= talloc_get_type(sock
->private_data
, struct tls_context
);
78 return tls
->tls_enabled
;
84 static const struct socket_ops tls_socket_ops
;
86 static NTSTATUS
tls_socket_init(struct socket_context
*sock
)
89 case SOCKET_TYPE_STREAM
:
92 return NT_STATUS_INVALID_PARAMETER
;
95 sock
->backend_name
= "tls";
100 #define TLSCHECK(call) do { \
103 DEBUG(0,("TLS %s - %s\n", #call, gnutls_strerror(ret))); \
110 callback for reading from a socket
112 static ssize_t
tls_pull(gnutls_transport_ptr ptr
, void *buf
, size_t size
)
114 struct tls_context
*tls
= talloc_get_type(ptr
, struct tls_context
);
118 if (tls
->have_first_byte
) {
119 *(uint8_t *)buf
= tls
->first_byte
;
120 tls
->have_first_byte
= false;
124 status
= socket_recv(tls
->socket
, buf
, size
, &nread
);
125 if (NT_STATUS_EQUAL(status
, NT_STATUS_END_OF_FILE
)) {
128 if (NT_STATUS_IS_ERR(status
)) {
129 TEVENT_FD_NOT_READABLE(tls
->fde
);
130 TEVENT_FD_NOT_WRITEABLE(tls
->fde
);
134 if (!NT_STATUS_IS_OK(status
)) {
135 TEVENT_FD_READABLE(tls
->fde
);
139 if (tls
->output_pending
) {
140 TEVENT_FD_WRITEABLE(tls
->fde
);
143 TEVENT_FD_READABLE(tls
->fde
);
149 callback for writing to a socket
151 static ssize_t
tls_push(gnutls_transport_ptr ptr
, const void *buf
, size_t size
)
153 struct tls_context
*tls
= talloc_get_type(ptr
, struct tls_context
);
158 if (!tls
->tls_enabled
) {
162 b
.data
= discard_const(buf
);
165 status
= socket_send(tls
->socket
, &b
, &nwritten
);
166 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
170 if (!NT_STATUS_IS_OK(status
)) {
171 TEVENT_FD_WRITEABLE(tls
->fde
);
174 if (size
!= nwritten
) {
175 TEVENT_FD_WRITEABLE(tls
->fde
);
181 destroy a tls session
183 static int tls_destructor(struct tls_context
*tls
)
186 ret
= gnutls_bye(tls
->session
, GNUTLS_SHUT_WR
);
188 DEBUG(4,("TLS gnutls_bye failed - %s\n", gnutls_strerror(ret
)));
195 possibly continue the handshake process
197 static NTSTATUS
tls_handshake(struct tls_context
*tls
)
201 if (tls
->done_handshake
) {
205 ret
= gnutls_handshake(tls
->session
);
206 if (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
) {
207 if (gnutls_record_get_direction(tls
->session
) == 1) {
208 TEVENT_FD_WRITEABLE(tls
->fde
);
210 return STATUS_MORE_ENTRIES
;
213 DEBUG(0,("TLS gnutls_handshake failed - %s\n", gnutls_strerror(ret
)));
214 return NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
216 tls
->done_handshake
= true;
221 possibly continue an interrupted operation
223 static NTSTATUS
tls_interrupted(struct tls_context
*tls
)
227 if (!tls
->interrupted
) {
230 if (gnutls_record_get_direction(tls
->session
) == 1) {
231 ret
= gnutls_record_send(tls
->session
, NULL
, 0);
233 ret
= gnutls_record_recv(tls
->session
, NULL
, 0);
235 if (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
) {
236 return STATUS_MORE_ENTRIES
;
238 tls
->interrupted
= false;
243 see how many bytes are pending on the connection
245 static NTSTATUS
tls_socket_pending(struct socket_context
*sock
, size_t *npending
)
247 struct tls_context
*tls
= talloc_get_type(sock
->private_data
, struct tls_context
);
248 if (!tls
->tls_enabled
|| tls
->tls_detect
) {
249 return socket_pending(tls
->socket
, npending
);
251 *npending
= gnutls_record_check_pending(tls
->session
);
252 if (*npending
== 0) {
253 NTSTATUS status
= socket_pending(tls
->socket
, npending
);
254 if (*npending
== 0) {
255 /* seems to be a gnutls bug */
264 receive data either by tls or normal socket_recv
266 static NTSTATUS
tls_socket_recv(struct socket_context
*sock
, void *buf
,
267 size_t wantlen
, size_t *nread
)
271 struct tls_context
*tls
= talloc_get_type(sock
->private_data
, struct tls_context
);
273 if (tls
->tls_enabled
&& tls
->tls_detect
) {
274 status
= socket_recv(tls
->socket
, &tls
->first_byte
, 1, nread
);
275 NT_STATUS_NOT_OK_RETURN(status
);
276 if (*nread
== 0) return NT_STATUS_OK
;
277 tls
->tls_detect
= false;
278 /* look for the first byte of a valid HTTP operation */
279 if (strchr(tls
->plain_chars
, tls
->first_byte
)) {
281 tls
->tls_enabled
= false;
282 *(uint8_t *)buf
= tls
->first_byte
;
285 tls
->have_first_byte
= true;
288 if (!tls
->tls_enabled
) {
289 return socket_recv(tls
->socket
, buf
, wantlen
, nread
);
292 status
= tls_handshake(tls
);
293 NT_STATUS_NOT_OK_RETURN(status
);
295 status
= tls_interrupted(tls
);
296 NT_STATUS_NOT_OK_RETURN(status
);
298 ret
= gnutls_record_recv(tls
->session
, buf
, wantlen
);
299 if (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
) {
300 if (gnutls_record_get_direction(tls
->session
) == 1) {
301 TEVENT_FD_WRITEABLE(tls
->fde
);
303 tls
->interrupted
= true;
304 return STATUS_MORE_ENTRIES
;
307 return NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
315 send data either by tls or normal socket_recv
317 static NTSTATUS
tls_socket_send(struct socket_context
*sock
,
318 const DATA_BLOB
*blob
, size_t *sendlen
)
322 struct tls_context
*tls
= talloc_get_type(sock
->private_data
, struct tls_context
);
324 if (!tls
->tls_enabled
) {
325 return socket_send(tls
->socket
, blob
, sendlen
);
328 status
= tls_handshake(tls
);
329 NT_STATUS_NOT_OK_RETURN(status
);
331 status
= tls_interrupted(tls
);
332 NT_STATUS_NOT_OK_RETURN(status
);
334 ret
= gnutls_record_send(tls
->session
, blob
->data
, blob
->length
);
335 if (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
) {
336 if (gnutls_record_get_direction(tls
->session
) == 1) {
337 TEVENT_FD_WRITEABLE(tls
->fde
);
339 tls
->interrupted
= true;
340 return STATUS_MORE_ENTRIES
;
343 DEBUG(0,("gnutls_record_send of %d failed - %s\n", (int)blob
->length
, gnutls_strerror(ret
)));
344 return NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
347 tls
->output_pending
= (ret
< blob
->length
);
353 initialise global tls state
355 struct tls_params
*tls_initialise(TALLOC_CTX
*mem_ctx
, struct loadparm_context
*lp_ctx
)
357 struct tls_params
*params
;
359 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
360 const char *keyfile
= lpcfg_tls_keyfile(tmp_ctx
, lp_ctx
);
361 const char *certfile
= lpcfg_tls_certfile(tmp_ctx
, lp_ctx
);
362 const char *cafile
= lpcfg_tls_cafile(tmp_ctx
, lp_ctx
);
363 const char *crlfile
= lpcfg_tls_crlfile(tmp_ctx
, lp_ctx
);
364 const char *dhpfile
= lpcfg_tls_dhpfile(tmp_ctx
, lp_ctx
);
365 void tls_cert_generate(TALLOC_CTX
*, const char *, const char *, const char *, const char *);
366 params
= talloc(mem_ctx
, struct tls_params
);
367 if (params
== NULL
) {
368 talloc_free(tmp_ctx
);
372 if (!lpcfg_tls_enabled(lp_ctx
) || keyfile
== NULL
|| *keyfile
== 0) {
373 params
->tls_enabled
= false;
374 talloc_free(tmp_ctx
);
378 if (!file_exist(cafile
)) {
379 char *hostname
= talloc_asprintf(mem_ctx
, "%s.%s",
380 lpcfg_netbios_name(lp_ctx
),
381 lpcfg_dnsdomain(lp_ctx
));
382 if (hostname
== NULL
) {
385 tls_cert_generate(params
, hostname
, keyfile
, certfile
, cafile
);
386 talloc_free(hostname
);
389 ret
= gnutls_global_init();
390 if (ret
< 0) goto init_failed
;
392 gnutls_certificate_allocate_credentials(¶ms
->x509_cred
);
393 if (ret
< 0) goto init_failed
;
395 if (cafile
&& *cafile
) {
396 ret
= gnutls_certificate_set_x509_trust_file(params
->x509_cred
, cafile
,
397 GNUTLS_X509_FMT_PEM
);
399 DEBUG(0,("TLS failed to initialise cafile %s\n", cafile
));
404 if (crlfile
&& *crlfile
) {
405 ret
= gnutls_certificate_set_x509_crl_file(params
->x509_cred
,
407 GNUTLS_X509_FMT_PEM
);
409 DEBUG(0,("TLS failed to initialise crlfile %s\n", crlfile
));
414 ret
= gnutls_certificate_set_x509_key_file(params
->x509_cred
,
416 GNUTLS_X509_FMT_PEM
);
418 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s\n",
424 ret
= gnutls_dh_params_init(¶ms
->dh_params
);
425 if (ret
< 0) goto init_failed
;
427 if (dhpfile
&& *dhpfile
) {
428 gnutls_datum_t dhparms
;
430 dhparms
.data
= (uint8_t *)file_load(dhpfile
, &size
, 0, mem_ctx
);
433 DEBUG(0,("Failed to read DH Parms from %s\n", dhpfile
));
438 ret
= gnutls_dh_params_import_pkcs3(params
->dh_params
, &dhparms
, GNUTLS_X509_FMT_PEM
);
439 if (ret
< 0) goto init_failed
;
441 ret
= gnutls_dh_params_generate2(params
->dh_params
, DH_BITS
);
442 if (ret
< 0) goto init_failed
;
445 gnutls_certificate_set_dh_params(params
->x509_cred
, params
->dh_params
);
447 params
->tls_enabled
= true;
449 talloc_free(tmp_ctx
);
453 DEBUG(0,("GNUTLS failed to initialise - %s\n", gnutls_strerror(ret
)));
454 params
->tls_enabled
= false;
455 talloc_free(tmp_ctx
);
461 setup for a new connection
463 struct socket_context
*tls_init_server(struct tls_params
*params
,
464 struct socket_context
*socket_ctx
,
465 struct tevent_fd
*fde
,
466 const char *plain_chars
)
468 struct tls_context
*tls
;
470 struct socket_context
*new_sock
;
473 nt_status
= socket_create_with_ops(socket_ctx
, &tls_socket_ops
, &new_sock
,
475 socket_ctx
->flags
| SOCKET_FLAG_ENCRYPT
);
476 if (!NT_STATUS_IS_OK(nt_status
)) {
480 tls
= talloc(new_sock
, struct tls_context
);
485 tls
->socket
= socket_ctx
;
486 talloc_steal(tls
, socket_ctx
);
489 new_sock
->private_data
= tls
;
491 if (!params
->tls_enabled
) {
492 talloc_free(new_sock
);
496 TLSCHECK(gnutls_init(&tls
->session
, GNUTLS_SERVER
));
498 talloc_set_destructor(tls
, tls_destructor
);
500 TLSCHECK(gnutls_set_default_priority(tls
->session
));
501 TLSCHECK(gnutls_credentials_set(tls
->session
, GNUTLS_CRD_CERTIFICATE
,
503 gnutls_certificate_server_set_request(tls
->session
, GNUTLS_CERT_REQUEST
);
504 gnutls_dh_set_prime_bits(tls
->session
, DH_BITS
);
505 gnutls_transport_set_ptr(tls
->session
, (gnutls_transport_ptr
)tls
);
506 gnutls_transport_set_pull_function(tls
->session
, (gnutls_pull_func
)tls_pull
);
507 gnutls_transport_set_push_function(tls
->session
, (gnutls_push_func
)tls_push
);
508 #if GNUTLS_VERSION_MAJOR < 3
509 gnutls_transport_set_lowat(tls
->session
, 0);
512 tls
->plain_chars
= plain_chars
;
514 tls
->tls_detect
= true;
516 tls
->tls_detect
= false;
519 tls
->output_pending
= false;
520 tls
->done_handshake
= false;
521 tls
->have_first_byte
= false;
522 tls
->tls_enabled
= true;
523 tls
->interrupted
= false;
525 new_sock
->state
= SOCKET_STATE_SERVER_CONNECTED
;
530 DEBUG(0,("TLS init connection failed - %s\n", gnutls_strerror(ret
)));
531 talloc_free(new_sock
);
537 setup for a new client connection
539 struct socket_context
*tls_init_client(struct socket_context
*socket_ctx
,
540 struct tevent_fd
*fde
,
543 struct tls_context
*tls
;
545 const int cert_type_priority
[] = { GNUTLS_CRT_X509
, GNUTLS_CRT_OPENPGP
, 0 };
546 struct socket_context
*new_sock
;
549 nt_status
= socket_create_with_ops(socket_ctx
, &tls_socket_ops
, &new_sock
,
551 socket_ctx
->flags
| SOCKET_FLAG_ENCRYPT
);
552 if (!NT_STATUS_IS_OK(nt_status
)) {
556 tls
= talloc(new_sock
, struct tls_context
);
557 if (tls
== NULL
) return NULL
;
559 tls
->socket
= socket_ctx
;
560 talloc_steal(tls
, socket_ctx
);
563 new_sock
->private_data
= tls
;
565 gnutls_global_init();
567 gnutls_certificate_allocate_credentials(&tls
->xcred
);
568 gnutls_certificate_set_x509_trust_file(tls
->xcred
, ca_path
, GNUTLS_X509_FMT_PEM
);
569 TLSCHECK(gnutls_init(&tls
->session
, GNUTLS_CLIENT
));
570 TLSCHECK(gnutls_set_default_priority(tls
->session
));
571 gnutls_certificate_type_set_priority(tls
->session
, cert_type_priority
);
572 TLSCHECK(gnutls_credentials_set(tls
->session
, GNUTLS_CRD_CERTIFICATE
, tls
->xcred
));
574 talloc_set_destructor(tls
, tls_destructor
);
576 gnutls_transport_set_ptr(tls
->session
, (gnutls_transport_ptr
)tls
);
577 gnutls_transport_set_pull_function(tls
->session
, (gnutls_pull_func
)tls_pull
);
578 gnutls_transport_set_push_function(tls
->session
, (gnutls_push_func
)tls_push
);
579 #if GNUTLS_VERSION_MAJOR < 3
580 gnutls_transport_set_lowat(tls
->session
, 0);
582 tls
->tls_detect
= false;
584 tls
->output_pending
= false;
585 tls
->done_handshake
= false;
586 tls
->have_first_byte
= false;
587 tls
->tls_enabled
= true;
588 tls
->interrupted
= false;
590 new_sock
->state
= SOCKET_STATE_CLIENT_CONNECTED
;
595 DEBUG(0,("TLS init connection failed - %s\n", gnutls_strerror(ret
)));
596 tls
->tls_enabled
= false;
600 static NTSTATUS
tls_socket_set_option(struct socket_context
*sock
, const char *option
, const char *val
)
602 set_socket_options(socket_get_fd(sock
), option
);
606 static char *tls_socket_get_peer_name(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
608 struct tls_context
*tls
= talloc_get_type(sock
->private_data
, struct tls_context
);
609 return socket_get_peer_name(tls
->socket
, mem_ctx
);
612 static struct socket_address
*tls_socket_get_peer_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
614 struct tls_context
*tls
= talloc_get_type(sock
->private_data
, struct tls_context
);
615 return socket_get_peer_addr(tls
->socket
, mem_ctx
);
618 static struct socket_address
*tls_socket_get_my_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
620 struct tls_context
*tls
= talloc_get_type(sock
->private_data
, struct tls_context
);
621 return socket_get_my_addr(tls
->socket
, mem_ctx
);
624 static int tls_socket_get_fd(struct socket_context
*sock
)
626 struct tls_context
*tls
= talloc_get_type(sock
->private_data
, struct tls_context
);
627 return socket_get_fd(tls
->socket
);
630 static const struct socket_ops tls_socket_ops
= {
632 .fn_init
= tls_socket_init
,
633 .fn_recv
= tls_socket_recv
,
634 .fn_send
= tls_socket_send
,
635 .fn_pending
= tls_socket_pending
,
637 .fn_set_option
= tls_socket_set_option
,
639 .fn_get_peer_name
= tls_socket_get_peer_name
,
640 .fn_get_peer_addr
= tls_socket_get_peer_addr
,
641 .fn_get_my_addr
= tls_socket_get_my_addr
,
642 .fn_get_fd
= tls_socket_get_fd
647 /* for systems without tls we just fail the operations, and the caller
648 * will retain the original socket */
650 struct tls_params
*tls_initialise(TALLOC_CTX
*mem_ctx
, struct loadparm_context
*lp_ctx
)
652 return talloc_new(mem_ctx
);
656 setup for a new connection
658 struct socket_context
*tls_init_server(struct tls_params
*params
,
659 struct socket_context
*socket
,
660 struct tevent_fd
*fde
,
661 const char *plain_chars
)
668 setup for a new client connection
670 struct socket_context
*tls_init_client(struct socket_context
*socket
,
671 struct tevent_fd
*fde
,