]> git.pld-linux.org Git - packages/rsync.git/blame - rsync-ssl.patch
- updated for 2.6.7
[packages/rsync.git] / rsync-ssl.patch
CommitLineData
b16de604
AM
1diff -urbBN rsync-2.6.6.org/cleanup.c rsync-2.6.6/cleanup.c
2--- rsync-2.6.6.org/cleanup.c 2005-03-05 19:58:38.000000000 +0100
3+++ rsync-2.6.6/cleanup.c 2005-11-14 16:49:56.182884500 +0100
4@@ -22,6 +22,9 @@
5 #include "rsync.h"
6
7 extern int io_error;
8+#if HAVE_OPENSSL
9+extern int use_ssl;
10+#endif
11 extern int keep_partial;
12 extern int log_got_error;
13 extern char *partial_dir;
14@@ -97,6 +100,11 @@
15 signal(SIGUSR1, SIG_IGN);
16 signal(SIGUSR2, SIG_IGN);
17
18+#if HAVE_OPENSSL
19+ if (use_ssl)
20+ end_tls();
21+#endif
22+
23 if (verbose > 3) {
24 rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
25 code, safe_fname(file), line);
26diff -urbBN rsync-2.6.6.org/clientserver.c rsync-2.6.6/clientserver.c
27--- rsync-2.6.6.org/clientserver.c 2005-06-10 18:57:43.000000000 +0200
28+++ rsync-2.6.6/clientserver.c 2005-11-14 16:49:56.182884500 +0100
29@@ -44,6 +44,9 @@
30 extern int orig_umask;
31 extern int no_detach;
32 extern int default_af_hint;
33+#if HAVE_OPENSSL
34+extern int use_ssl;
35+#endif
36 extern char *bind_address;
37 extern struct filter_list_struct server_filter_list;
38 extern char *config_file;
39@@ -98,8 +101,18 @@
40 exit_cleanup(RERR_SOCKETIO);
41
42 ret = start_inband_exchange(user, path, fd, fd, argc);
43+ if (ret)
44+ return ret;
45+
46+#if HAVE_OPENSSL
47+ if (use_ssl) {
48+ int f_in = get_tls_rfd();
49+ int f_out = get_tls_wfd();
50+ return client_run(f_in, f_out, -1, argc, argv);
51+ }
52+#endif
53
54- return ret ? ret : client_run(fd, fd, -1, argc, argv);
55+ return client_run(fd, fd, -1, argc, argv);
56 }
57
58 int start_inband_exchange(char *user, char *path, int f_in, int f_out,
59@@ -160,6 +173,33 @@
60 if (verbose > 1)
61 print_child_argv(sargs);
62
63+#if HAVE_OPENSSL
64+ if (use_ssl) {
65+ io_printf(f_out, "#starttls\n");
66+ while (1) {
67+ if (!read_line(f_in, line, sizeof(line)-1)) {
68+ rprintf(FERROR, "rsync: did not receive reply to #starttls\n");
69+ return -1;
70+ }
71+ if (strncmp(line, "@ERROR", 6) == 0) {
72+ rprintf(FERROR, "%s\n", line);
73+ return -1;
74+ }
75+ if (strcmp(line, "@RSYNCD: starttls") == 0) {
76+ break;
77+ }
78+ rprintf(FINFO, "%s\n", line);
79+ }
80+ if (start_tls(f_in, f_out)) {
81+ rprintf(FERROR, "rsync: error during SSL handshake: %s\n",
82+ get_ssl_error());
83+ return -1;
84+ }
85+ f_in = get_tls_rfd();
86+ f_out = get_tls_wfd();
87+ }
88+#endif
89+
90 p = strchr(path,'/');
91 if (p) *p = 0;
92 io_printf(f_out, "%s\n", path);
93@@ -188,6 +228,10 @@
94 * server to terminate the listing of modules.
95 * We don't want to go on and transfer
96 * anything; just exit. */
97+#if HAVE_OPENSSL
98+ if (use_ssl)
99+ end_tls();
100+#endif
101 exit(0);
102 }
103
104@@ -195,6 +239,10 @@
105 rprintf(FERROR, "%s\n", line);
106 /* This is always fatal; the server will now
107 * close the socket. */
108+#if HAVE_OPENSSL
109+ if (use_ssl)
110+ end_tls();
111+#endif
112 return -1;
113 }
114
115@@ -590,6 +639,9 @@
116 if (protocol_version > remote_protocol)
117 protocol_version = remote_protocol;
118
119+#if HAVE_OPENSSL
120+retry:
121+#endif
122 line[0] = 0;
123 if (!read_line(f_in, line, sizeof line - 1))
124 return -1;
125@@ -599,6 +651,20 @@
126 return -1;
127 }
128
129+#if HAVE_OPENSSL
130+ if (use_ssl && strcmp(line, "#starttls") == 0) {
131+ io_printf(f_out, "@RSYNCD: starttls\n");
132+ if (start_tls(f_in, f_out)) {
133+ rprintf(FLOG, "SSL connection failed: %s\n",
134+ get_ssl_error());
135+ return -1;
136+ }
137+ f_in = get_tls_rfd();
138+ f_out = get_tls_wfd();
139+ goto retry;
140+ }
141+#endif
142+
143 if (*line == '#') {
144 /* it's some sort of command that I don't understand */
145 io_printf(f_out, "@ERROR: Unknown command '%s'\n", line);
146diff -urbBN rsync-2.6.6.org/configure.in rsync-2.6.6/configure.in
147--- rsync-2.6.6.org/configure.in 2005-07-28 21:31:05.000000000 +0200
148+++ rsync-2.6.6/configure.in 2005-11-14 16:49:56.186884750 +0100
149@@ -293,6 +293,21 @@
150 AC_SEARCH_LIBS(getaddrinfo, inet6)
151 fi
152
153+AC_ARG_ENABLE(openssl,
154+ AC_HELP_STRING([--enable-openssl], [compile SSL support with OpenSSL.]))
155+
156+if test "x$enable_openssl" != xno
157+then
158+ have_ssl=yes
159+ AC_CHECK_LIB(ssl, SSL_library_init, , [have_ssl=no])
160+ if test "x$have_ssl" = xyes
161+ then
162+ AC_DEFINE(HAVE_OPENSSL, 1, [true if you want to use SSL.])
163+ SSL_OBJS=ssl.o
164+ AC_SUBST(SSL_OBJS)
165+ fi
166+fi
167+
168 AC_MSG_CHECKING([whether to call shutdown on all sockets])
169 case $host_os in
170 *cygwin* ) AC_MSG_RESULT(yes)
171diff -urbBN rsync-2.6.6.org/Makefile.in rsync-2.6.6/Makefile.in
172--- rsync-2.6.6.org/Makefile.in 2005-07-07 23:29:57.000000000 +0200
173+++ rsync-2.6.6/Makefile.in 2005-11-14 16:49:56.182884500 +0100
174@@ -38,7 +38,7 @@
175 DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
176 popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
177 popt/popthelp.o popt/poptparse.o
178-OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
179+OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@ @SSL_OBJS@
180
181 TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o
182
183diff -urbBN rsync-2.6.6.org/options.c rsync-2.6.6/options.c
184--- rsync-2.6.6.org/options.c 2005-05-19 10:52:17.000000000 +0200
185+++ rsync-2.6.6/options.c 2005-11-14 16:50:48.190134750 +0100
186@@ -157,6 +157,14 @@
187 int always_checksum = 0;
188 int list_only = 0;
189
190+#if HAVE_OPENSSL
191+int use_ssl = 0;
192+char *ssl_cert_path = NULL;
193+char *ssl_key_path = NULL;
194+char *ssl_key_passwd = NULL;
195+char *ssl_ca_path = NULL;
196+#endif
197+
198 #define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */
199 char *batch_name = NULL;
200
201@@ -182,6 +190,7 @@
202 char const *hardlinks = "no ";
203 char const *links = "no ";
204 char const *ipv6 = "no ";
205+ char const *ssl = "no ";
206 STRUCT_STAT *dumstat;
207
208 #ifdef HAVE_SOCKETPAIR
209@@ -204,6 +213,10 @@
210 ipv6 = "";
211 #endif
212
213+#if HAVE_OPENSSL
214+ ssl = "";
215+#endif
216+
217 rprintf(f, "%s version %s protocol version %d\n",
218 RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
219 rprintf(f,
220@@ -217,10 +230,10 @@
221 /* Note that this field may not have type ino_t. It depends
222 * on the complicated interaction between largefile feature
223 * macros. */
224- rprintf(f, " %sinplace, %sIPv6, %d-bit system inums, %d-bit internal inums\n",
225+ rprintf(f, " %sinplace, %sIPv6, %d-bit system inums, %d-bit internal inums, %sssl\n",
226 have_inplace, ipv6,
227 (int) (sizeof dumstat->st_ino * 8),
228- (int) (sizeof (int64) * 8));
229+ (int) (sizeof (int64) * 8), ssl);
230 #ifdef MAINTAINER_MODE
231 rprintf(f, " panic action: \"%s\"\n",
232 get_panic_action());
233@@ -352,6 +365,13 @@
234 rprintf(F," -4, --ipv4 prefer IPv4\n");
235 rprintf(F," -6, --ipv6 prefer IPv6\n");
236 #endif
237+#if HAVE_OPENSSL
238+ rprintf(F," --ssl allow socket connections to use SSL\n");
239+ rprintf(F," --ssl-cert=FILE path to daemon's SSL certificate\n");
240+ rprintf(F," --ssl-key=FILE path to daemon's SSL private key\n");
241+ rprintf(F," --ssl-key-passwd=PASS password for PEM-encoded private key\n");
242+ rprintf(F," --ssl-ca-certs=FILE path to trusted CA certificates\n");
243+#endif
244 rprintf(F," --version print version number\n");
245 rprintf(F," -h, --help show this help screen\n");
246
247@@ -362,7 +382,7 @@
248
249 enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
250 OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST,
251- OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
252+ OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_USE_SSL,
253 OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
254 OPT_REFUSED_BASE = 9000};
255
256@@ -464,6 +484,13 @@
257 {"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
258 {"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
259 #endif
260+#if HAVE_OPENSSL
261+ {"ssl", 0, POPT_ARG_NONE, 0, OPT_USE_SSL, 0, 0},
262+ {"ssl-cert", 0, POPT_ARG_STRING, &ssl_cert_path, OPT_USE_SSL, 0, 0},
263+ {"ssl-key", 0, POPT_ARG_STRING, &ssl_key_path, OPT_USE_SSL, 0, 0},
264+ {"ssl-key-passwd", 0, POPT_ARG_STRING, &ssl_key_passwd, OPT_USE_SSL, 0, 0},
265+ {"ssl-ca-certs", 0, POPT_ARG_STRING, &ssl_ca_path, OPT_USE_SSL, 0, 0},
266+#endif
267 /* All these options switch us into daemon-mode option-parsing. */
268 {"config", 0, POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
269 {"daemon", 0, POPT_ARG_NONE, 0, OPT_DAEMON, 0, 0 },
270@@ -508,6 +535,13 @@
271 {"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
272 {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
273 {"server", 0, POPT_ARG_NONE, &am_server, 0, 0, 0 },
274+#if HAVE_OPENSSL
275+ {"ssl", 0, POPT_ARG_NONE, 0, OPT_USE_SSL, 0, 0},
276+ {"ssl-cert", 0, POPT_ARG_STRING, &ssl_cert_path, OPT_USE_SSL, 0, 0},
277+ {"ssl-key", 0, POPT_ARG_STRING, &ssl_key_path, OPT_USE_SSL, 0, 0},
278+ {"ssl-key-passwd", 0, POPT_ARG_STRING, &ssl_key_passwd, OPT_USE_SSL, 0, 0},
279+ {"ssl-ca-certs", 0, POPT_ARG_STRING, &ssl_ca_path, OPT_USE_SSL, 0, 0},
280+#endif
281 {"verbose", 'v', POPT_ARG_NONE, 0, 'v', 0, 0 },
282 {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 },
283 {0,0,0,0, 0, 0, 0}
284@@ -876,6 +910,12 @@
285 basis_dir[basis_dir_cnt++] = (char *)arg;
286 break;
287
288+ case OPT_USE_SSL:
289+#if HAVE_OPENSSL
290+ use_ssl = 1;
291+#endif
292+ break;
293+
294 default:
295 /* A large opt value means that set_refuse_options()
296 * turned this option off. */
297@@ -1129,6 +1169,17 @@
298 if (delay_updates && !partial_dir)
299 partial_dir = partialdir_for_delayupdate;
300
301+#if HAVE_OPENSSL
302+ if (use_ssl) {
303+ if (init_tls()) {
304+ snprintf(err_buf, sizeof(err_buf),
305+ "Openssl error: %s\n",
306+ get_ssl_error());
307+ return 0;
308+ }
309+ }
310+#endif
311+
312 if (inplace) {
313 #ifdef HAVE_FTRUNCATE
314 if (partial_dir) {
315@@ -1498,11 +1549,28 @@
316 {
317 char *p;
318 int not_host;
319+ int url_prefix_len = sizeof URL_PREFIX - 1;
320
321- if (port_ptr && strncasecmp(URL_PREFIX, s, strlen(URL_PREFIX)) == 0) {
322+ if (!port_ptr)
323+ url_prefix_len = 0;
324+ else if (strncasecmp(URL_PREFIX, s, url_prefix_len) != 0) {
325+#if HAVE_OPENSSL
326+ url_prefix_len = sizeof SSL_URL_PREFIX - 1;
327+ if (strncasecmp(SSL_URL_PREFIX, s, url_prefix_len) != 0)
328+ url_prefix_len = 0;
329+ else {
330+ if (!use_ssl)
331+ init_tls();
332+ use_ssl = 1;
333+ }
334+#else
335+ url_prefix_len = 0;
336+#endif
337+ }
338+ if (url_prefix_len) {
339 char *path;
340 int hostlen;
341- s += strlen(URL_PREFIX);
342+ s += url_prefix_len;
343 if ((p = strchr(s, '/')) != NULL) {
344 hostlen = p - s;
345 path = p + 1;
346diff -urbBN rsync-2.6.6.org/rsync.h rsync-2.6.6/rsync.h
347--- rsync-2.6.6.org/rsync.h 2005-05-03 19:00:47.000000000 +0200
348+++ rsync-2.6.6/rsync.h 2005-11-14 16:49:56.190885000 +0100
349@@ -32,6 +32,7 @@
350
351 #define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
352 #define URL_PREFIX "rsync://"
353+#define SSL_URL_PREFIX "rsyncs://"
354
355 #define BACKUP_SUFFIX "~"
356
357@@ -410,6 +411,11 @@
358 # define SIZEOF_INT64 SIZEOF_OFF_T
359 #endif
360
361+#if HAVE_OPENSSL
362+#include <openssl/ssl.h>
363+#include <openssl/err.h>
364+#endif
365+
366 /* Starting from protocol version 26, we always use 64-bit
367 * ino_t and dev_t internally, even if this platform does not
368 * allow files to have 64-bit inums. That's because the
369diff -urbBN rsync-2.6.6.org/ssl.c rsync-2.6.6/ssl.c
370--- rsync-2.6.6.org/ssl.c 1970-01-01 01:00:00.000000000 +0100
371+++ rsync-2.6.6/ssl.c 2005-11-14 16:49:56.190885000 +0100
372@@ -0,0 +1,366 @@
373+/* -*- c-file-style: "linux" -*-
374+ * ssl.c: operations for negotiating SSL rsync connections.
375+ *
376+ * Copyright (C) 2003 Casey Marshall <rsdio@metastatic.org>
377+ *
378+ * This program is free software; you can redistribute it and/or modify
379+ * it under the terms of the GNU General Public License as published by
380+ * the Free Software Foundation; either version 2 of the License, or
381+ * (at your option) any later version.
382+ *
383+ * This program is distributed in the hope that it will be useful,
384+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
385+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
386+ * GNU General Public License for more details.
387+ *
388+ * You should have received a copy of the GNU General Public License
389+ * along with this program; if not, write to the Free Software
390+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
391+ */
392+
393+#include "rsync.h"
394+
395+#if HAVE_SYS_SELECT_H
396+#include <sys/select.h>
397+#else
398+#include <sys/time.h>
399+#include <sys/types.h>
400+#include <unistd.h>
401+#endif
402+#include <string.h>
403+
404+#define BUF_SIZE 1024
405+
406+extern int verbose;
407+extern int am_daemon;
408+extern int am_server;
409+
410+extern char *ssl_cert_path;
411+extern char *ssl_key_path;
412+extern char *ssl_key_passwd;
413+extern char *ssl_ca_path;
414+
415+static SSL_CTX *ssl_ctx;
416+static SSL *ssl;
417+static int tls_read[2] = { -1, -1 };
418+static int tls_write[2] = { -1, -1 };
419+static int ssl_running;
420+static int ssl_pid = -1;
421+
422+/**
423+ * A non-interactive callback to be passed to SSL_CTX_set_default_password_cb,
424+ * which merely copies the value of ssl_key_passwd into buf. This is
425+ * used for when the private key password is supplied via an option.
426+ */
427+static int default_password_cb(char *buf, int n, UNUSED(int f), UNUSED(void *u))
428+{
429+ if (ssl_key_passwd == NULL || n < (int)strlen(ssl_key_passwd))
430+ return 0;
431+ strncpy(buf, ssl_key_passwd, n-1);
432+ return strlen(ssl_key_passwd);
433+}
434+
435+/**
436+ * If verbose, this method traces the status of the SSL handshake.
437+ */
438+static void info_callback(const SSL *ssl, int cb, int val)
439+{
440+ char buf[128];
441+ char *cbs;
442+
443+ switch (cb) {
444+ case SSL_CB_LOOP:
445+ cbs = "SSL_CB_LOOP";
446+ break;
447+ case SSL_CB_EXIT:
448+ cbs = "SSL_CB_EXIT";
449+ break;
450+ case SSL_CB_READ:
451+ cbs = "SSL_CB_READ";
452+ break;
453+ case SSL_CB_WRITE:
454+ cbs = "SSL_CB_WRITE";
455+ break;
456+ case SSL_CB_ALERT:
457+ cbs = "SSL_CB_ALERT";
458+ break;
459+ case SSL_CB_READ_ALERT:
460+ cbs = "SSL_CB_READ_ALERT";
461+ break;
462+ case SSL_CB_WRITE_ALERT:
463+ cbs = "SSL_CB_WRITE_ALERT";
464+ break;
465+ case SSL_CB_ACCEPT_LOOP:
466+ cbs = "SSL_CB_ACCEPT_LOOP";
467+ break;
468+ case SSL_CB_ACCEPT_EXIT:
469+ cbs = "SSL_CB_ACCEPT_EXIT";
470+ break;
471+ case SSL_CB_CONNECT_LOOP:
472+ cbs = "SSL_CB_CONNECT_LOOP";
473+ break;
474+ case SSL_CB_CONNECT_EXIT:
475+ cbs = "SSL_CB_CONNECT_EXIT";
476+ break;
477+ case SSL_CB_HANDSHAKE_START:
478+ cbs = "SSL_CB_HANDSHAKE_START";
479+ break;
480+ case SSL_CB_HANDSHAKE_DONE:
481+ cbs = "SSL_CB_HANDSHAKE_DONE";
482+ break;
483+ default:
484+ snprintf(buf, sizeof buf, "??? (%d)", cb);
485+ cbs = buf;
486+ break;
487+ }
488+ if (verbose > 2) {
489+ rprintf(FLOG, "SSL: info_callback(%p,%s,%d)\n", ssl, cbs, val);
490+ if (cb == SSL_CB_HANDSHAKE_DONE) {
491+ SSL_CIPHER_description(SSL_get_current_cipher((SSL*)ssl),
492+ buf, sizeof buf);
493+ rprintf(FLOG, "SSL: cipher: %s", buf);
494+ }
495+ }
496+}
497+
498+/**
499+ * Initializes the SSL context for TLSv1 connections; returns zero on
500+ * success.
501+ */
502+int init_tls(void)
503+{
504+ if (ssl_ctx)
505+ return 0;
506+ SSL_library_init();
507+ SSL_load_error_strings();
508+ ssl_ctx = SSL_CTX_new(TLSv1_method());
509+ if (!ssl_ctx)
510+ return 1;
511+ SSL_CTX_set_info_callback(ssl_ctx, info_callback);
512+
513+ /* Sets the certificate sent to the other party. */
514+ if (ssl_cert_path != NULL
515+ && SSL_CTX_use_certificate_file(ssl_ctx, ssl_cert_path,
516+ SSL_FILETYPE_PEM) != 1)
517+ return 1;
518+ /* Set up the simple non-interactive callback if the password
519+ * was supplied on the command line. */
520+ if (ssl_key_passwd != NULL)
521+ SSL_CTX_set_default_passwd_cb(ssl_ctx, default_password_cb);
522+ /* Sets the private key that matches the public certificate. */
523+ if (ssl_key_path != NULL) {
524+ if (SSL_CTX_use_PrivateKey_file(ssl_ctx, ssl_key_path,
525+ SSL_FILETYPE_PEM) != 1)
526+ return 1;
527+ if (SSL_CTX_check_private_key(ssl_ctx) != 1)
528+ return 1;
529+ }
530+ if (ssl_ca_path != NULL
531+ && !SSL_CTX_load_verify_locations(ssl_ctx, ssl_ca_path, NULL))
532+ return 1;
533+
534+ return 0;
535+}
536+
537+/**
538+ * Returns the error string for the current SSL error, if any.
539+ */
540+char *get_ssl_error(void)
541+{
542+ return ERR_error_string(ERR_get_error(), NULL);
543+}
544+
545+/**
546+ * Returns the input file descriptor for the SSL connection.
547+ */
548+int get_tls_rfd(void)
549+{
550+ return tls_read[0];
551+}
552+
553+/**
554+ * Returns the output file descriptor for the SSL connection.
555+ */
556+int get_tls_wfd(void)
557+{
558+ return tls_write[1];
559+}
560+
561+/**
562+ * Signal handler that ends the SSL connection.
563+ */
564+static RETSIGTYPE tls_sigusr1(int UNUSED(val))
565+{
566+ if (ssl) {
567+ SSL_shutdown(ssl);
568+ SSL_free(ssl);
569+ ssl = NULL;
570+ }
571+ ssl_running = 0;
572+}
573+
574+/**
575+ * Negotiates the TLS connection, creates a socket pair for communicating
576+ * with the rsync process, then forks into a new process that will handle
577+ * the communication.
578+ *
579+ * 0 is returned on success.
580+ */
581+int start_tls(int f_in, int f_out)
582+{
583+ int tls_fd;
584+ int n = 0, r;
585+ unsigned char buf1[BUF_SIZE], buf2[BUF_SIZE];
586+ int avail1 = 0, avail2 = 0, write1 = 0, write2 = 0;
587+ fd_set rd, wd;
588+
589+ if (fd_pair(tls_read))
590+ return 1;
591+ if (fd_pair(tls_write))
592+ return 1;
593+
594+ set_blocking(tls_read[0]);
595+ set_blocking(tls_read[1]);
596+ set_blocking(tls_write[0]);
597+ set_blocking(tls_write[1]);
598+ set_blocking(f_in);
599+ set_blocking(f_out);
600+
601+ ssl_pid = do_fork();
602+ if (ssl_pid < 0)
603+ return -1;
604+ if (ssl_pid != 0) {
605+ close(tls_write[0]);
606+ close(tls_read[1]);
607+ return 0;
608+ }
609+
610+ signal(SIGUSR1, tls_sigusr1);
611+ ssl = SSL_new(ssl_ctx);
612+ if (!ssl)
613+ goto closed;
614+ if (am_daemon || am_server)
615+ SSL_set_accept_state(ssl);
616+ else
617+ SSL_set_connect_state(ssl);
618+ SSL_set_rfd(ssl, f_in);
619+ SSL_set_wfd(ssl, f_out);
620+
621+ tls_fd = SSL_get_fd(ssl);
622+ n = tls_write[0];
623+ n = MAX(tls_read[1], n);
624+ n = MAX(tls_fd, n) + 1;
625+
626+ ssl_running = 1;
627+ while (ssl_running) {
628+ FD_ZERO(&rd);
629+ FD_ZERO(&wd);
630+ FD_SET(tls_write[0], &rd);
631+ FD_SET(tls_read[1], &wd);
632+ FD_SET(tls_fd, &rd);
633+ FD_SET(tls_fd, &wd);
634+
635+ r = select(n, &rd, &wd, NULL, NULL);
636+
637+ if (r == -1 && errno == EINTR)
638+ continue;
639+ if (FD_ISSET(tls_write[0], &rd)) {
640+ r = read(tls_write[0], buf1+avail1, BUF_SIZE-avail1);
641+ if (r >= 0)
642+ avail1 += r;
643+ else {
644+ rprintf(FERROR, "pipe read error: %s\n",
645+ strerror(errno));
646+ break;
647+ }
648+ }
649+ if (FD_ISSET(tls_fd, &rd)) {
650+ r = SSL_read(ssl, buf2+avail2, BUF_SIZE-avail2);
651+ if (r > 0)
652+ avail2 += r;
653+ else {
654+ switch (SSL_get_error(ssl, r)) {
655+ case SSL_ERROR_ZERO_RETURN:
656+ goto closed;
657+ case SSL_ERROR_WANT_READ:
658+ case SSL_ERROR_WANT_WRITE:
659+ break;
660+ case SSL_ERROR_SYSCALL:
661+ if (r == 0)
662+ rprintf(FERROR, "SSL spurious EOF\n");
663+ else
664+ rprintf(FERROR, "SSL I/O error: %s\n",
665+ strerror(errno));
666+ goto closed;
667+ case SSL_ERROR_SSL:
668+ rprintf(FERROR, "SSL: %s\n",
669+ ERR_error_string(ERR_get_error(), NULL));
670+ goto closed;
671+ default:
672+ rprintf(FERROR, "unexpected ssl error %d\n", r);
673+ goto closed;
674+ }
675+ }
676+ }
677+ if (FD_ISSET(tls_read[1], &wd) && write2 < avail2) {
678+ r = write(tls_read[1], buf2+write2, avail2-write2);
679+ if (r >= 0)
680+ write2 += r;
681+ else {
682+ rprintf(FERROR, "pipe write error: %s\n",
683+ strerror(errno));
684+ break;
685+ }
686+ }
687+ if (FD_ISSET(tls_fd, &wd) && write1 < avail1) {
688+ r = SSL_write(ssl, buf1+write1, avail1-write1);
689+ if (r > 0)
690+ write1 += r;
691+ else {
692+ switch (SSL_get_error(ssl, r)) {
693+ case SSL_ERROR_ZERO_RETURN:
694+ goto closed;
695+ case SSL_ERROR_WANT_READ:
696+ case SSL_ERROR_WANT_WRITE:
697+ break;
698+ case SSL_ERROR_SYSCALL:
699+ if (r == 0)
700+ rprintf(FERROR, "SSL: spurious EOF\n");
701+ else
702+ rprintf(FERROR, "SSL: I/O error: %s\n",
703+ strerror(errno));
704+ goto closed;
705+ case SSL_ERROR_SSL:
706+ rprintf(FERROR, "SSL: %s\n",
707+ ERR_error_string(ERR_get_error(), NULL));
708+ goto closed;
709+ default:
710+ rprintf(FERROR, "unexpected ssl error %d\n", r);
711+ goto closed;
712+ }
713+ }
714+ }
715+ if (avail1 == write1)
716+ avail1 = write1 = 0;
717+ if (avail2 == write2)
718+ avail2 = write2 = 0;
719+ }
720+
721+ /* XXX I'm pretty sure that there is a lot that I am not considering
722+ here. Bugs? Yes, probably. */
723+
724+ /* We're finished. */
725+ closed:
726+ close(tls_read[1]);
727+ close(tls_write[0]);
728+ exit(0);
729+}
730+
731+/**
732+ * Ends the TLS connection.
733+ */
734+void end_tls(void)
735+{
736+ if (ssl_pid > 0)
737+ kill(ssl_pid, SIGUSR1);
738+}
This page took 0.112822 seconds and 4 git commands to generate.