--- /dev/null
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include <openssl/lhash.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+
+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);
+}
#include <unistd.h>
-#include <openssl/lhash.h>
-#include <openssl/bn.h>
-#include <openssl/err.h>
-#include <openssl/pem.h>
-#include <openssl/x509.h>
-#include <openssl/ssl.h>
-
+#include <errno.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/file.h>
#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)
"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;
{
{"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;
case 'k':
opt_key_file = optarg;
break;
- case 'v':
- opt_verify = atoi (optarg);
- break;
default:
usage (basename (argv[0]));
return 1;
}
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);
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;
}
}
#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)
wrote = write (out, retry, nbuffer);
if (wrote < 0) goto finish;
}
- if (tls_conn && SSL_pending(tls_conn))
+ if (tls_pending())
goto readtop;
}
}