From 074b050ab6fcda22a1df3988908fc3746255ff1e Mon Sep 17 00:00:00 2001 From: ueno Date: Wed, 9 Jun 2004 02:53:45 +0000 Subject: [PATCH] * starttls.c (do_tls_negotiate): New signal handler. * openssl.c: New file; split functions which use OpenSSL API from starttls.c. * Makefile.am (starttls_SOURCES): Add openssl.c. --- ChangeLog | 7 +++ Makefile.am | 2 +- openssl.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ starttls.c | 188 +++++++---------------------------------------------------- 4 files changed, 206 insertions(+), 168 deletions(-) create mode 100644 openssl.c diff --git a/ChangeLog b/ChangeLog index 9278e1f..cca24c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2004-06-09 Daiki Ueno + + * starttls.c (do_tls_negotiate): New signal handler. + * openssl.c: New file; split functions which use OpenSSL API from + starttls.c. + * Makefile.am (starttls_SOURCES): Add openssl.c. + 2004-03-21 Kenichi Okada * configure.in (VERSION): Bump up to 0.10. diff --git a/Makefile.am b/Makefile.am index c9eb5f7..468edb6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,5 +6,5 @@ EXTRA_DIST = starttls.el basename.c getopt.c getopt.h getopt1.c bin_PROGRAMS= starttls lisp_LISP = starttls.el -starttls_SOURCES = starttls.c +starttls_SOURCES = starttls.c openssl.c starttls_LDADD = $(LIBOBJS) diff --git a/openssl.c b/openssl.c new file mode 100644 index 0000000..1eeff0a --- /dev/null +++ b/openssl.c @@ -0,0 +1,177 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static SSL_CTX *tls_ctx = NULL; +static SSL *tls_conn = NULL; + +static int +tls_ssl_ctx_new (cert_file, key_file) + const char *cert_file, *key_file; +{ + SSL_load_error_strings (); + SSLeay_add_ssl_algorithms (); + + tls_ctx = SSL_CTX_new (TLSv1_client_method()); + if (!tls_ctx) + return -1; + + SSL_CTX_set_options (tls_ctx, SSL_OP_ALL /* Work around all known bugs */); + + if (cert_file) + { + if (SSL_CTX_use_certificate_file (tls_ctx, cert_file, + SSL_FILETYPE_PEM) <= 0) + return -1; + if (!key_file) + key_file = cert_file; + if (SSL_CTX_use_PrivateKey_file (tls_ctx, key_file, + SSL_FILETYPE_PEM) <= 0) + return -1; + if (!SSL_CTX_check_private_key (tls_ctx)) + return -1; + } + + SSL_CTX_set_verify (tls_ctx, SSL_VERIFY_NONE, NULL); + + return 0; +} + +static int +tls_ssl_new(ctx, s) + SSL_CTX *ctx; + int s; +{ + SSL_SESSION *session; + SSL_CIPHER *cipher; + X509 *peer; + + tls_conn = (SSL *) SSL_new (ctx); + if (!tls_conn) + return -1; + SSL_clear(tls_conn); + + if (!SSL_set_fd (tls_conn, s)) + return -1; + + SSL_set_connect_state (tls_conn); + + if (SSL_connect (tls_conn) <= 0) + { + session = SSL_get_session (tls_conn); + if (session) + SSL_CTX_remove_session (ctx, session); + if (tls_conn!=NULL) + SSL_free (tls_conn); + return -1; + } + + return 0; +} + +int +tls_connect (hostname, service) + const char *hostname, *service; +{ + int server, false = 0; +#ifdef HAVE_ADDRINFO + struct addrinfo *in, *in0, hints; +#else + struct hostent *host; + struct servent *serv; + struct sockaddr_in sin; +#endif + +#ifdef HAVE_ADDRINFO + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if (getaddrinfo (hostname, service, &hints, &in0)) + return -1; + + for (in = in0; in; in = in->ai_next) + { + server = socket (in->ai_family, in->ai_socktype, in->ai_protocol); + if (server < 0) + continue; + if (connect (server, in->ai_addr, in->ai_addrlen) < 0) + { + server = -1; + continue; + } + break; + } + + if (server < 0) + return -1; +#else + memset (&sin, 0, sizeof (sin)); + host = gethostbyname (hostname); + if (!host) + return -1; + memcpy (&sin.sin_addr, host->h_addr, host->h_length); + serv = getservbyname (service, "tcp"); + if (serv) + sin.sin_port = serv->s_port; + else if (isdigit (service[0])) + sin.sin_port = htons (atoi (service)); + sin.sin_family = AF_INET; + server = socket (sin.sin_family, SOCK_STREAM, 0); + if (server == -1) + return -1; + + if (connect (server, (struct sockaddr *)&sin, sizeof (sin)) < 0) + { + close (server); + return -1; + } +#endif + + setsockopt (server, SOL_SOCKET, SO_KEEPALIVE, (const char *) &false, + sizeof (false)); + + return server; +} + +void +tls_negotiate (fd, cert_file, key_file) + int fd; +{ + if (tls_ssl_ctx_new (cert_file, key_file) == -1) + return; + + (void) tls_ssl_new (tls_ctx, fd); /* Negotiation has done. */ +} + +int +tls_write(fd, buf, num) + const char *buf; + int fd, num; +{ + if (tls_conn) + return SSL_write (tls_conn, buf, num); + return write (fd, buf, num); +} + +int +tls_read(fd, buf, num) + char *buf; + int fd, num; +{ + if (tls_conn) + return SSL_read (tls_conn, buf, num); + return read (fd, buf, num); +} + +int +tls_pending() +{ + return tls_conn && SSL_pending(tls_conn); +} diff --git a/starttls.c b/starttls.c index f0d61ce..ba867f7 100644 --- a/starttls.c +++ b/starttls.c @@ -32,13 +32,7 @@ #include -#include -#include -#include -#include -#include -#include - +#include #include #include #include @@ -55,150 +49,14 @@ #define _GNU_SOURCE #include "getopt.h" -static SSL_CTX *tls_ctx = NULL; -static SSL *tls_conn = NULL; -static int tls_fd; +extern int tls_connect (const char *, const char *); +extern void tls_negotiate (int, const char *, const char *); +extern int tls_write(int, const char *, int); +extern int tls_read(int, char *, int); +extern int tls_pending(); static char *opt_cert_file = NULL, *opt_key_file = NULL; -static int opt_verify = 0; - -static int -tls_ssl_ctx_new (cert_file, key_file) - const char *cert_file, *key_file; -{ - SSL_load_error_strings (); - SSLeay_add_ssl_algorithms (); - - tls_ctx = SSL_CTX_new (TLSv1_client_method()); - if (!tls_ctx) - return -1; - - SSL_CTX_set_options (tls_ctx, SSL_OP_ALL /* Work around all known bugs */); - - if (cert_file) - { - if (SSL_CTX_use_certificate_file (tls_ctx, cert_file, - SSL_FILETYPE_PEM) <= 0) - return -1; - if (!key_file) - key_file = cert_file; - if (SSL_CTX_use_PrivateKey_file (tls_ctx, key_file, - SSL_FILETYPE_PEM) <= 0) - return -1; - if (!SSL_CTX_check_private_key (tls_ctx)) - return -1; - } - - SSL_CTX_set_verify (tls_ctx, SSL_VERIFY_NONE, NULL); - - return 0; -} - -static int -tls_ssl_new(ctx, s) - SSL_CTX *ctx; - int s; -{ - SSL_SESSION *session; - SSL_CIPHER *cipher; - X509 *peer; - - tls_conn = (SSL *) SSL_new (ctx); - if (!tls_conn) - return -1; - SSL_clear(tls_conn); - - if (!SSL_set_fd (tls_conn, s)) - return -1; - - SSL_set_connect_state (tls_conn); - - if (SSL_connect (tls_conn) <= 0) - { - session = SSL_get_session (tls_conn); - if (session) - SSL_CTX_remove_session (ctx, session); - if (tls_conn!=NULL) - SSL_free (tls_conn); - return -1; - } - - return 0; -} - -static int -tls_connect (hostname, service) - const char *hostname, *service; -{ - int server, false = 0; -#ifdef HAVE_ADDRINFO - struct addrinfo *in, *in0, hints; -#else - struct hostent *host; - struct servent *serv; - struct sockaddr_in sin; -#endif - -#ifdef HAVE_ADDRINFO - memset (&hints, 0, sizeof (hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - if (getaddrinfo (hostname, service, &hints, &in0)) - return -1; - - for (in = in0; in; in = in->ai_next) - { - server = socket (in->ai_family, in->ai_socktype, in->ai_protocol); - if (server < 0) - continue; - if (connect (server, in->ai_addr, in->ai_addrlen) < 0) - { - server = -1; - continue; - } - break; - } - - if (server < 0) - return -1; -#else - memset (&sin, 0, sizeof (sin)); - host = gethostbyname (hostname); - if (!host) - return -1; - memcpy (&sin.sin_addr, host->h_addr, host->h_length); - serv = getservbyname (service, "tcp"); - if (serv) - sin.sin_port = serv->s_port; - else if (isdigit (service[0])) - sin.sin_port = htons (atoi (service)); - sin.sin_family = AF_INET; - server = socket (sin.sin_family, SOCK_STREAM, 0); - if (server == -1) - return -1; - - if (connect (server, (struct sockaddr *)&sin, sizeof (sin)) < 0) - { - close (server); - return -1; - } -#endif - - setsockopt (server, SOL_SOCKET, SO_KEEPALIVE, (const char *) &false, - sizeof (false)); - - return server; -} - -static void -tls_negotiate (sig) - int sig; -{ - if (tls_ssl_ctx_new (opt_cert_file, opt_key_file) == -1) - return; - - (void) tls_ssl_new (tls_ctx, tls_fd); /* Negotiation has done. */ -} +static int tls_fd; static void usage (progname) @@ -212,11 +70,17 @@ usage (progname) "Usage: %s [options] host port\n\n" "Options:\n\n" " --cert-file [file] specify certificate file\n" - " --key-file [file] specify private key file\n" - " --verify [level] set verification level\n", + " --key-file [file] specify private key file\n", progname, PACKAGE, VERSION, progname); } - + +static void +do_tls_negotiate(sig) + int sig; +{ + tls_negotiate(tls_fd, opt_cert_file, opt_key_file); +} + int main (argc, argv) int argc; @@ -238,13 +102,12 @@ main (argc, argv) { {"cert-file", 1, 0, 'c'}, {"key-file", 1, 0, 'k'}, - {"verify", 1, 0, 'v'}, {0, 0, 0, 0} }; while (1) { - c = getopt_long (argc, argv, "c:k:v:", long_options, &option_index); + c = getopt_long (argc, argv, "c:k:", long_options, &option_index); if (c == -1) break; @@ -256,9 +119,6 @@ main (argc, argv) case 'k': opt_key_file = optarg; break; - case 'v': - opt_verify = atoi (optarg); - break; default: usage (basename (argv[0])); return 1; @@ -279,7 +139,7 @@ main (argc, argv) } memset (&act, 0, sizeof (act)); - act.sa_handler = tls_negotiate; + act.sa_handler = do_tls_negotiate; sigemptyset (&act.sa_mask); act.sa_flags = SA_RESTART|SA_RESETHAND; sigaction (SIGALRM, &act, NULL); @@ -331,10 +191,7 @@ main (argc, argv) perror ("poll"); return 1; } - if (tls_conn) - wrote = SSL_write (tls_conn, retry, nbuffer); - else - wrote = write (tls_fd, retry, nbuffer); + wrote = tls_write(tls_fd, retry, nbuffer); if (wrote < 0) goto finish; } } @@ -345,10 +202,7 @@ main (argc, argv) #endif { readtop: - if (tls_conn) - nbuffer = SSL_read (tls_conn, buffer, sizeof buffer -1); - else - nbuffer = read (tls_fd, buffer, sizeof buffer -1); + nbuffer = tls_read(tls_fd, buffer, sizeof buffer -1); if (nbuffer == 0) goto finish; for (retry = buffer; nbuffer > 0; nbuffer -= wrote, retry += wrote) @@ -368,7 +222,7 @@ readtop: wrote = write (out, retry, nbuffer); if (wrote < 0) goto finish; } - if (tls_conn && SSL_pending(tls_conn)) + if (tls_pending()) goto readtop; } } -- 1.7.10.4