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 <ueno@unixuser.org>
+ * 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 <ueno@unixuser.org>
+
* starttls.c (do_tls_negotiate): New signal handler.
* openssl.c: New file; split functions which use OpenSSL API from
starttls.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)
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)
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <gnutls/gnutls.h>
+
+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);
+}
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
+#include <stdio.h>
+#include <stdlib.h>
#include <openssl/lhash.h>
#include <openssl/bn.h>
#include <openssl/err.h>
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;
}
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;
int
tls_pending()
{
- return tls_conn && SSL_pending(tls_conn);
+ return tls_conn && SSL_pending (tls_conn);
}
#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);
}
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;
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;
}