From: ueno Date: Wed, 9 Jun 2004 06:56:12 +0000 (+0000) Subject: * Makefile.am (starttls_SOURCES): Add gnutls.c if USE_GNUTLS X-Git-Tag: starttls-0_11-branchpoint~5 X-Git-Url: http://git.chise.org/gitweb/?a=commitdiff_plain;h=a676a49c84f8790fda17ae1ce7544f8656eff6d2;p=elisp%2Fstarttls.git * Makefile.am (starttls_SOURCES): Add gnutls.c if USE_GNUTLS conditional is asserted. * starttls.c (socket_connect): Renamed from tls_connect. * configure.in: Add --with-gnutls. * gnutls.c: New file; support build with GnuTLS. --- diff --git a/ChangeLog b/ChangeLog index cca24c5..bbbd974 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2004-06-09 Daiki Ueno + * Makefile.am (starttls_SOURCES): Add gnutls.c if USE_GNUTLS + conditional is asserted. + * starttls.c (socket_connect): Renamed from tls_connect. + * configure.in: Add --with-gnutls. + * gnutls.c: New file; support build with GnuTLS. + +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. diff --git a/Makefile.am b/Makefile.am index 468edb6..733ec97 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,5 +6,9 @@ EXTRA_DIST = starttls.el basename.c getopt.c getopt.h getopt1.c bin_PROGRAMS= starttls lisp_LISP = starttls.el +if USE_GNUTLS +starttls_SOURCES = starttls.c gnutls.c +else starttls_SOURCES = starttls.c openssl.c +endif starttls_LDADD = $(LIBOBJS) diff --git a/configure.in b/configure.in index 9b530a8..c3aa0c1 100644 --- a/configure.in +++ b/configure.in @@ -23,15 +23,24 @@ AC_REPLACE_FUNCS(basename) AC_CHECK_FUNC(poll) AC_ARG_WITH(openssl,[ --with-openssl=PATH use OpenSSL from PATH]) - -if test -n "$with_openssl"; then - CPPFLAGS="$CPPFLAGS -I${with_openssl}/include" - LDFLAGS="$LDFLAGS -L${with_openssl}/lib" +AC_ARG_WITH(gnutls,[ --with-gnutls use GnuTLS instead of OpenSSL], + use_gnutls=true, use_gnutls=false) +AM_CONDITIONAL(USE_GNUTLS, test x$use_gnutls = xtrue) + +if $use_gnutls; then + AC_CHECK_HEADER(gnutls/gnutls.h, [ + AC_DEFINE(USE_GNUTLS) + AC_CHECK_LIB(gnutls, gnutls_global_init, LIBS="-lgnutls $LIBS")], + [GnuTLS is selected, but it is not installed]) +else + if test -n "$with_openssl"; then + CPPFLAGS="$CPPFLAGS -I${with_openssl}/include" + LDFLAGS="$LDFLAGS -L${with_openssl}/lib" + fi + AC_CHECK_HEADER(openssl/ssl.h, [ + AC_CHECK_LIB(crypto, BIO_accept, LIBS="-lcrypto $LIBS") + AC_CHECK_LIB(ssl, SSL_CTX_new, LIBS="-lssl $LIBS")], + AC_MSG_ERROR([OpenSSL not installed - please install first])) fi -AC_CHECK_HEADER(openssl/ssl.h, [ - AC_CHECK_LIB(crypto, BIO_accept, LIBS="-lcrypto $LIBS") - AC_CHECK_LIB(ssl, SSL_CTX_new, LIBS="-lssl $LIBS")], - AC_MSG_ERROR([OpenSSL not installed - please install first])) - AC_OUTPUT(Makefile) diff --git a/gnutls.c b/gnutls.c new file mode 100644 index 0000000..ba53a90 --- /dev/null +++ b/gnutls.c @@ -0,0 +1,59 @@ +#include +#include +#include + +static gnutls_session tls_session = NULL; + +void +tls_negotiate (fd, cert_file, key_file) + int fd; + const char *cert_file, *key_file; +{ + gnutls_certificate_credentials xcred; + + gnutls_global_init (); + + gnutls_certificate_allocate_credentials(&xcred); + + if (cert_file) + { + if (!key_file) + key_file = cert_file; + gnutls_certificate_set_x509_key_file (xcred, cert_file, key_file, + GNUTLS_X509_FMT_PEM); + } + + gnutls_init (&tls_session, GNUTLS_CLIENT); + gnutls_set_default_priority (tls_session); + gnutls_credentials_set (tls_session, GNUTLS_CRD_CERTIFICATE, xcred); + + gnutls_transport_set_ptr (tls_session, (gnutls_transport_ptr)fd); + + gnutls_handshake (tls_session); +} + +int +tls_write(fd, buf, num) + const char *buf; + int fd, num; +{ + if (tls_session) + return gnutls_record_send (tls_session, buf, num); + return write (fd, buf, num); +} + +int +tls_read(fd, buf, num) + char *buf; + int fd, num; +{ + if (tls_session) + return gnutls_record_recv (tls_session, buf, num); + return read (fd, buf, num); +} + +int +tls_pending() +{ + return tls_session && gnutls_record_check_pending (tls_session); +} diff --git a/openssl.c b/openssl.c index 1eeff0a..89e5374 100644 --- a/openssl.c +++ b/openssl.c @@ -1,7 +1,5 @@ -#include -#include -#include - +#include +#include #include #include #include @@ -68,7 +66,7 @@ tls_ssl_new(ctx, s) session = SSL_get_session (tls_conn); if (session) SSL_CTX_remove_session (ctx, session); - if (tls_conn!=NULL) + if (tls_conn) SSL_free (tls_conn); return -1; } @@ -76,73 +74,10 @@ tls_ssl_new(ctx, s) 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; + const char *cert_file, *key_file; { if (tls_ssl_ctx_new (cert_file, key_file) == -1) return; @@ -173,5 +108,5 @@ tls_read(fd, buf, num) int tls_pending() { - return tls_conn && SSL_pending(tls_conn); + return tls_conn && SSL_pending (tls_conn); } diff --git a/starttls.c b/starttls.c index ba867f7..2cf7ced 100644 --- a/starttls.c +++ b/starttls.c @@ -49,7 +49,6 @@ #define _GNU_SOURCE #include "getopt.h" -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); @@ -82,6 +81,70 @@ do_tls_negotiate(sig) } int +socket_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; +} + +int main (argc, argv) int argc; char **argv; @@ -131,10 +194,10 @@ main (argc, argv) return 1; } - tls_fd = tls_connect (argv[optind], argv[optind+1]); + tls_fd = socket_connect (argv[optind], argv[optind+1]); if (tls_fd < 0) { - perror ("tls_connect"); + perror ("socket_connect"); return 1; }