• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source4/lib/tls/
1/*
2   Unix SMB/CIFS implementation.
3
4   transport layer security handling code
5
6   Copyright (C) Andrew Tridgell 2004-2005
7   Copyright (C) Stefan Metzmacher 2004
8   Copyright (C) Andrew Bartlett 2006
9
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.
14
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.
19
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/>.
22*/
23
24#include "includes.h"
25#include "lib/events/events.h"
26#include "lib/socket/socket.h"
27#include "lib/tls/tls.h"
28#include "param/param.h"
29
30#if ENABLE_GNUTLS
31#include "gnutls/gnutls.h"
32
33#define DH_BITS 1024
34
35#if defined(HAVE_GNUTLS_DATUM) && !defined(HAVE_GNUTLS_DATUM_T)
36typedef gnutls_datum gnutls_datum_t;
37#endif
38
39/* hold persistent tls data */
40struct tls_params {
41	gnutls_certificate_credentials x509_cred;
42	gnutls_dh_params dh_params;
43	bool tls_enabled;
44};
45#endif
46
47/* hold per connection tls data */
48struct tls_context {
49	struct socket_context *socket;
50	struct tevent_fd *fde;
51	bool tls_enabled;
52#if ENABLE_GNUTLS
53	gnutls_session session;
54	bool done_handshake;
55	bool have_first_byte;
56	uint8_t first_byte;
57	bool tls_detect;
58	const char *plain_chars;
59	bool output_pending;
60	gnutls_certificate_credentials xcred;
61	bool interrupted;
62#endif
63};
64
65bool tls_enabled(struct socket_context *sock)
66{
67	struct tls_context *tls;
68	if (!sock) {
69		return false;
70	}
71	if (strcmp(sock->backend_name, "tls") != 0) {
72		return false;
73	}
74	tls = talloc_get_type(sock->private_data, struct tls_context);
75	if (!tls) {
76		return false;
77	}
78	return tls->tls_enabled;
79}
80
81
82#if ENABLE_GNUTLS
83
84static const struct socket_ops tls_socket_ops;
85
86static NTSTATUS tls_socket_init(struct socket_context *sock)
87{
88	switch (sock->type) {
89	case SOCKET_TYPE_STREAM:
90		break;
91	default:
92		return NT_STATUS_INVALID_PARAMETER;
93	}
94
95	sock->backend_name = "tls";
96
97	return NT_STATUS_OK;
98}
99
100#define TLSCHECK(call) do { \
101	ret = call; \
102	if (ret < 0) { \
103		DEBUG(0,("TLS %s - %s\n", #call, gnutls_strerror(ret))); \
104		goto failed; \
105	} \
106} while (0)
107
108
109/*
110  callback for reading from a socket
111*/
112static ssize_t tls_pull(gnutls_transport_ptr ptr, void *buf, size_t size)
113{
114	struct tls_context *tls = talloc_get_type(ptr, struct tls_context);
115	NTSTATUS status;
116	size_t nread;
117
118	if (tls->have_first_byte) {
119		*(uint8_t *)buf = tls->first_byte;
120		tls->have_first_byte = false;
121		return 1;
122	}
123
124	status = socket_recv(tls->socket, buf, size, &nread);
125	if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
126		return 0;
127	}
128	if (NT_STATUS_IS_ERR(status)) {
129		EVENT_FD_NOT_READABLE(tls->fde);
130		EVENT_FD_NOT_WRITEABLE(tls->fde);
131		errno = EBADF;
132		return -1;
133	}
134	if (!NT_STATUS_IS_OK(status)) {
135		EVENT_FD_READABLE(tls->fde);
136		errno = EAGAIN;
137		return -1;
138	}
139	if (tls->output_pending) {
140		EVENT_FD_WRITEABLE(tls->fde);
141	}
142	if (size != nread) {
143		EVENT_FD_READABLE(tls->fde);
144	}
145	return nread;
146}
147
148/*
149  callback for writing to a socket
150*/
151static ssize_t tls_push(gnutls_transport_ptr ptr, const void *buf, size_t size)
152{
153	struct tls_context *tls = talloc_get_type(ptr, struct tls_context);
154	NTSTATUS status;
155	size_t nwritten;
156	DATA_BLOB b;
157
158	if (!tls->tls_enabled) {
159		return size;
160	}
161
162	b.data = discard_const(buf);
163	b.length = size;
164
165	status = socket_send(tls->socket, &b, &nwritten);
166	if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
167		errno = EAGAIN;
168		return -1;
169	}
170	if (!NT_STATUS_IS_OK(status)) {
171		EVENT_FD_WRITEABLE(tls->fde);
172		return -1;
173	}
174	if (size != nwritten) {
175		EVENT_FD_WRITEABLE(tls->fde);
176	}
177	return nwritten;
178}
179
180/*
181  destroy a tls session
182 */
183static int tls_destructor(struct tls_context *tls)
184{
185	int ret;
186	ret = gnutls_bye(tls->session, GNUTLS_SHUT_WR);
187	if (ret < 0) {
188		DEBUG(4,("TLS gnutls_bye failed - %s\n", gnutls_strerror(ret)));
189	}
190	return 0;
191}
192
193
194/*
195  possibly continue the handshake process
196*/
197static NTSTATUS tls_handshake(struct tls_context *tls)
198{
199	int ret;
200
201	if (tls->done_handshake) {
202		return NT_STATUS_OK;
203	}
204
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			EVENT_FD_WRITEABLE(tls->fde);
209		}
210		return STATUS_MORE_ENTRIES;
211	}
212	if (ret < 0) {
213		DEBUG(0,("TLS gnutls_handshake failed - %s\n", gnutls_strerror(ret)));
214		return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
215	}
216	tls->done_handshake = true;
217	return NT_STATUS_OK;
218}
219
220/*
221  possibly continue an interrupted operation
222*/
223static NTSTATUS tls_interrupted(struct tls_context *tls)
224{
225	int ret;
226
227	if (!tls->interrupted) {
228		return NT_STATUS_OK;
229	}
230	if (gnutls_record_get_direction(tls->session) == 1) {
231		ret = gnutls_record_send(tls->session, NULL, 0);
232	} else {
233		ret = gnutls_record_recv(tls->session, NULL, 0);
234	}
235	if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
236		return STATUS_MORE_ENTRIES;
237	}
238	tls->interrupted = false;
239	return NT_STATUS_OK;
240}
241
242/*
243  see how many bytes are pending on the connection
244*/
245static NTSTATUS tls_socket_pending(struct socket_context *sock, size_t *npending)
246{
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);
250	}
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 */
256			(*npending) = 100;
257		}
258		return status;
259	}
260	return NT_STATUS_OK;
261}
262
263/*
264  receive data either by tls or normal socket_recv
265*/
266static NTSTATUS tls_socket_recv(struct socket_context *sock, void *buf,
267				size_t wantlen, size_t *nread)
268{
269	int ret;
270	NTSTATUS status;
271	struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
272
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)) {
280			/* not a tls link */
281			tls->tls_enabled = false;
282			*(uint8_t *)buf = tls->first_byte;
283			return NT_STATUS_OK;
284		}
285		tls->have_first_byte = true;
286	}
287
288	if (!tls->tls_enabled) {
289		return socket_recv(tls->socket, buf, wantlen, nread);
290	}
291
292	status = tls_handshake(tls);
293	NT_STATUS_NOT_OK_RETURN(status);
294
295	status = tls_interrupted(tls);
296	NT_STATUS_NOT_OK_RETURN(status);
297
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			EVENT_FD_WRITEABLE(tls->fde);
302		}
303		tls->interrupted = true;
304		return STATUS_MORE_ENTRIES;
305	}
306	if (ret < 0) {
307		return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
308	}
309	*nread = ret;
310	return NT_STATUS_OK;
311}
312
313
314/*
315  send data either by tls or normal socket_recv
316*/
317static NTSTATUS tls_socket_send(struct socket_context *sock,
318				const DATA_BLOB *blob, size_t *sendlen)
319{
320	NTSTATUS status;
321	int ret;
322	struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
323
324	if (!tls->tls_enabled) {
325		return socket_send(tls->socket, blob, sendlen);
326	}
327
328	status = tls_handshake(tls);
329	NT_STATUS_NOT_OK_RETURN(status);
330
331	status = tls_interrupted(tls);
332	NT_STATUS_NOT_OK_RETURN(status);
333
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			EVENT_FD_WRITEABLE(tls->fde);
338		}
339		tls->interrupted = true;
340		return STATUS_MORE_ENTRIES;
341	}
342	if (ret < 0) {
343		DEBUG(0,("gnutls_record_send of %d failed - %s\n", (int)blob->length, gnutls_strerror(ret)));
344		return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
345	}
346	*sendlen = ret;
347	tls->output_pending = (ret < blob->length);
348	return NT_STATUS_OK;
349}
350
351
352/*
353  initialise global tls state
354*/
355struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
356{
357	struct tls_params *params;
358	int ret;
359	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
360	const char *keyfile = lp_tls_keyfile(tmp_ctx, lp_ctx);
361	const char *certfile = lp_tls_certfile(tmp_ctx, lp_ctx);
362	const char *cafile = lp_tls_cafile(tmp_ctx, lp_ctx);
363	const char *crlfile = lp_tls_crlfile(tmp_ctx, lp_ctx);
364	const char *dhpfile = lp_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);
369		return NULL;
370	}
371
372	if (!lp_tls_enabled(lp_ctx) || keyfile == NULL || *keyfile == 0) {
373		params->tls_enabled = false;
374		talloc_free(tmp_ctx);
375		return params;
376	}
377
378	if (!file_exist(cafile)) {
379		char *hostname = talloc_asprintf(mem_ctx, "%s.%s",
380						 lp_netbios_name(lp_ctx), lp_realm(lp_ctx));
381		if (hostname == NULL) {
382			goto init_failed;
383		}
384		tls_cert_generate(params, hostname, keyfile, certfile, cafile);
385		talloc_free(hostname);
386	}
387
388	ret = gnutls_global_init();
389	if (ret < 0) goto init_failed;
390
391	gnutls_certificate_allocate_credentials(&params->x509_cred);
392	if (ret < 0) goto init_failed;
393
394	if (cafile && *cafile) {
395		ret = gnutls_certificate_set_x509_trust_file(params->x509_cred, cafile,
396							     GNUTLS_X509_FMT_PEM);
397		if (ret < 0) {
398			DEBUG(0,("TLS failed to initialise cafile %s\n", cafile));
399			goto init_failed;
400		}
401	}
402
403	if (crlfile && *crlfile) {
404		ret = gnutls_certificate_set_x509_crl_file(params->x509_cred,
405							   crlfile,
406							   GNUTLS_X509_FMT_PEM);
407		if (ret < 0) {
408			DEBUG(0,("TLS failed to initialise crlfile %s\n", crlfile));
409			goto init_failed;
410		}
411	}
412
413	ret = gnutls_certificate_set_x509_key_file(params->x509_cred,
414						   certfile, keyfile,
415						   GNUTLS_X509_FMT_PEM);
416	if (ret < 0) {
417		DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s\n",
418			 certfile, keyfile));
419		goto init_failed;
420	}
421
422
423	ret = gnutls_dh_params_init(&params->dh_params);
424	if (ret < 0) goto init_failed;
425
426	if (dhpfile && *dhpfile) {
427		gnutls_datum_t dhparms;
428		size_t size;
429		dhparms.data = (uint8_t *)file_load(dhpfile, &size, 0, mem_ctx);
430
431		if (!dhparms.data) {
432			DEBUG(0,("Failed to read DH Parms from %s\n", dhpfile));
433			goto init_failed;
434		}
435		dhparms.size = size;
436
437		ret = gnutls_dh_params_import_pkcs3(params->dh_params, &dhparms, GNUTLS_X509_FMT_PEM);
438		if (ret < 0) goto init_failed;
439	} else {
440		ret = gnutls_dh_params_generate2(params->dh_params, DH_BITS);
441		if (ret < 0) goto init_failed;
442	}
443
444	gnutls_certificate_set_dh_params(params->x509_cred, params->dh_params);
445
446	params->tls_enabled = true;
447
448	talloc_free(tmp_ctx);
449	return params;
450
451init_failed:
452	DEBUG(0,("GNUTLS failed to initialise - %s\n", gnutls_strerror(ret)));
453	params->tls_enabled = false;
454	talloc_free(tmp_ctx);
455	return params;
456}
457
458
459/*
460  setup for a new connection
461*/
462struct socket_context *tls_init_server(struct tls_params *params,
463				       struct socket_context *socket_ctx,
464				       struct tevent_fd *fde,
465				       const char *plain_chars)
466{
467	struct tls_context *tls;
468	int ret;
469	struct socket_context *new_sock;
470	NTSTATUS nt_status;
471
472	nt_status = socket_create_with_ops(socket_ctx, &tls_socket_ops, &new_sock,
473					   SOCKET_TYPE_STREAM,
474					   socket_ctx->flags | SOCKET_FLAG_ENCRYPT);
475	if (!NT_STATUS_IS_OK(nt_status)) {
476		return NULL;
477	}
478
479	tls = talloc(new_sock, struct tls_context);
480	if (tls == NULL) {
481		return NULL;
482	}
483
484	tls->socket          = socket_ctx;
485	talloc_steal(tls, socket_ctx);
486	tls->fde             = fde;
487
488	new_sock->private_data    = tls;
489
490	if (!params->tls_enabled) {
491		talloc_free(new_sock);
492		return NULL;
493	}
494
495	TLSCHECK(gnutls_init(&tls->session, GNUTLS_SERVER));
496
497	talloc_set_destructor(tls, tls_destructor);
498
499	TLSCHECK(gnutls_set_default_priority(tls->session));
500	TLSCHECK(gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE,
501					params->x509_cred));
502	gnutls_certificate_server_set_request(tls->session, GNUTLS_CERT_REQUEST);
503	gnutls_dh_set_prime_bits(tls->session, DH_BITS);
504	gnutls_transport_set_ptr(tls->session, (gnutls_transport_ptr)tls);
505	gnutls_transport_set_pull_function(tls->session, (gnutls_pull_func)tls_pull);
506	gnutls_transport_set_push_function(tls->session, (gnutls_push_func)tls_push);
507	gnutls_transport_set_lowat(tls->session, 0);
508
509	tls->plain_chars = plain_chars;
510	if (plain_chars) {
511		tls->tls_detect = true;
512	} else {
513		tls->tls_detect = false;
514	}
515
516	tls->output_pending  = false;
517	tls->done_handshake  = false;
518	tls->have_first_byte = false;
519	tls->tls_enabled     = true;
520	tls->interrupted     = false;
521
522	new_sock->state = SOCKET_STATE_SERVER_CONNECTED;
523
524	return new_sock;
525
526failed:
527	DEBUG(0,("TLS init connection failed - %s\n", gnutls_strerror(ret)));
528	talloc_free(new_sock);
529	return NULL;
530}
531
532
533/*
534  setup for a new client connection
535*/
536struct socket_context *tls_init_client(struct socket_context *socket_ctx,
537				       struct tevent_fd *fde,
538				       const char *ca_path)
539{
540	struct tls_context *tls;
541	int ret = 0;
542	const int cert_type_priority[] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 };
543	struct socket_context *new_sock;
544	NTSTATUS nt_status;
545
546	nt_status = socket_create_with_ops(socket_ctx, &tls_socket_ops, &new_sock,
547					   SOCKET_TYPE_STREAM,
548					   socket_ctx->flags | SOCKET_FLAG_ENCRYPT);
549	if (!NT_STATUS_IS_OK(nt_status)) {
550		return NULL;
551	}
552
553	tls = talloc(new_sock, struct tls_context);
554	if (tls == NULL) return NULL;
555
556	tls->socket          = socket_ctx;
557	talloc_steal(tls, socket_ctx);
558	tls->fde             = fde;
559
560	new_sock->private_data    = tls;
561
562	gnutls_global_init();
563
564	gnutls_certificate_allocate_credentials(&tls->xcred);
565	gnutls_certificate_set_x509_trust_file(tls->xcred, ca_path, GNUTLS_X509_FMT_PEM);
566	TLSCHECK(gnutls_init(&tls->session, GNUTLS_CLIENT));
567	TLSCHECK(gnutls_set_default_priority(tls->session));
568	gnutls_certificate_type_set_priority(tls->session, cert_type_priority);
569	TLSCHECK(gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE, tls->xcred));
570
571	talloc_set_destructor(tls, tls_destructor);
572
573	gnutls_transport_set_ptr(tls->session, (gnutls_transport_ptr)tls);
574	gnutls_transport_set_pull_function(tls->session, (gnutls_pull_func)tls_pull);
575	gnutls_transport_set_push_function(tls->session, (gnutls_push_func)tls_push);
576	gnutls_transport_set_lowat(tls->session, 0);
577	tls->tls_detect = false;
578
579	tls->output_pending  = false;
580	tls->done_handshake  = false;
581	tls->have_first_byte = false;
582	tls->tls_enabled     = true;
583	tls->interrupted     = false;
584
585	new_sock->state = SOCKET_STATE_CLIENT_CONNECTED;
586
587	return new_sock;
588
589failed:
590	DEBUG(0,("TLS init connection failed - %s\n", gnutls_strerror(ret)));
591	tls->tls_enabled = false;
592	return new_sock;
593}
594
595static NTSTATUS tls_socket_set_option(struct socket_context *sock, const char *option, const char *val)
596{
597	set_socket_options(socket_get_fd(sock), option);
598	return NT_STATUS_OK;
599}
600
601static char *tls_socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
602{
603	struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
604	return socket_get_peer_name(tls->socket, mem_ctx);
605}
606
607static struct socket_address *tls_socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
608{
609	struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
610	return socket_get_peer_addr(tls->socket, mem_ctx);
611}
612
613static struct socket_address *tls_socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
614{
615	struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
616	return socket_get_my_addr(tls->socket, mem_ctx);
617}
618
619static int tls_socket_get_fd(struct socket_context *sock)
620{
621	struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
622	return socket_get_fd(tls->socket);
623}
624
625static const struct socket_ops tls_socket_ops = {
626	.name			= "tls",
627	.fn_init		= tls_socket_init,
628	.fn_recv		= tls_socket_recv,
629	.fn_send		= tls_socket_send,
630	.fn_pending		= tls_socket_pending,
631
632	.fn_set_option		= tls_socket_set_option,
633
634	.fn_get_peer_name	= tls_socket_get_peer_name,
635	.fn_get_peer_addr	= tls_socket_get_peer_addr,
636	.fn_get_my_addr		= tls_socket_get_my_addr,
637	.fn_get_fd		= tls_socket_get_fd
638};
639
640bool tls_support(struct tls_params *params)
641{
642	return params->tls_enabled;
643}
644
645#else
646
647/* for systems without tls we just fail the operations, and the caller
648 * will retain the original socket */
649
650struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
651{
652	return talloc_new(mem_ctx);
653}
654
655/*
656  setup for a new connection
657*/
658struct socket_context *tls_init_server(struct tls_params *params,
659				    struct socket_context *socket,
660				    struct tevent_fd *fde,
661				    const char *plain_chars)
662{
663	return NULL;
664}
665
666
667/*
668  setup for a new client connection
669*/
670struct socket_context *tls_init_client(struct socket_context *socket,
671				       struct tevent_fd *fde,
672				       const char *ca_path)
673{
674	return NULL;
675}
676
677bool tls_support(struct tls_params *params)
678{
679	return false;
680}
681
682#endif
683
684