summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2012-01-25 23:48:46 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2012-01-26 19:18:40 +0100
commitc62c365b893c783ca466912dc830ace1bff87653 (patch)
treeca95ba712f0907482fcf33b5fb270a60d10f6725 /src
parentee7b5358c29aa106e62c554fdb61aa43aa589d46 (diff)
downloadgnutls-c62c365b893c783ca466912dc830ace1bff87653.tar.gz
Added --ask option to ocsptool.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am22
-rw-r--r--src/cli.c200
-rw-r--r--src/common.c39
-rw-r--r--src/common.h2
-rw-r--r--src/ocsptool-args.def.in11
-rw-r--r--src/ocsptool.c262
-rw-r--r--src/serv.c4
-rw-r--r--src/socket.c250
-rw-r--r--src/socket.h23
-rw-r--r--src/tls_test.c4
10 files changed, 537 insertions, 280 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 5335b1bc6b..136484d3ce 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -50,11 +50,12 @@ endif
noinst_LTLIBRARIES =
-gnutls_serv_SOURCES = \
- list.h serv.c \
- udp-serv.c udp-serv.h \
- common.h common.c \
- certtool-common.h \
+gnutls_serv_SOURCES = \
+ list.h serv.c \
+ udp-serv.c udp-serv.h \
+ socket.c socket.h \
+ common.h common.c \
+ certtool-common.h \
$(PKCS11_SRCS)
gnutls_serv_LDADD = ../lib/libgnutls.la
gnutls_serv_LDADD += libcmd-serv.la ../gl/libgnu.la $(LIBOPTS_LDADD)
@@ -72,7 +73,8 @@ libcmd_srp_la_SOURCES = srptool-args.def srptool-args.c srptool-args.h
endif
if ENABLE_OCSP
-ocsptool_SOURCES = ocsptool.c ocsptool-common.h
+ocsptool_SOURCES = ocsptool.c ocsptool-common.h \
+ socket.c socket.h
ocsptool_LDADD = ../lib/libgnutls.la libcmd-ocsp.la ../gl/libgnu.la $(LIBOPTS_LDADD)
noinst_LTLIBRARIES += libcmd-ocsp.la
libcmd_ocsp_la_CFLAGS =
@@ -87,7 +89,9 @@ libcmd_psk_la_SOURCES = psk-args.def psk-args.c psk-args.h
BENCHMARK_SRCS = benchmark-cipher.c benchmark.c benchmark.h benchmark-tls.c
-gnutls_cli_SOURCES = cli.c common.h common.c $(PKCS11_SRCS) $(BENCHMARK_SRCS)
+gnutls_cli_SOURCES = cli.c common.h common.c \
+ socket.c socket.h \
+ $(PKCS11_SRCS) $(BENCHMARK_SRCS)
gnutls_cli_LDADD = ../lib/libgnutls.la
gnutls_cli_LDADD += libcmd-cli.la ../gl/libgnu.la $(LIBOPTS_LDADD)
gnutls_cli_LDADD += $(LIBSOCKET) $(GETADDRINFO_LIB) $(LIB_CLOCK_GETTIME)
@@ -95,7 +99,9 @@ noinst_LTLIBRARIES += libcmd-cli.la
libcmd_cli_la_CFLAGS =
libcmd_cli_la_SOURCES = cli-args.def cli-args.c cli-args.h
-gnutls_cli_debug_SOURCES = tls_test.c tests.h tests.c common.h common.c $(PKCS11_SRCS)
+gnutls_cli_debug_SOURCES = tls_test.c tests.h tests.c \
+ socket.c socket.h common.h common.c \
+ $(PKCS11_SRCS)
gnutls_cli_debug_LDADD = ../lib/libgnutls.la libcmd-cli-debug.la $(LIBOPTS_LDADD)
gnutls_cli_debug_LDADD += ../gl/libgnu.la $(LIBSOCKET) $(GETADDRINFO_LIB)
noinst_LTLIBRARIES += libcmd-cli-debug.la
diff --git a/src/cli.c b/src/cli.c
index ac0a02fc1c..27885c5f72 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -49,12 +49,14 @@
#include <read-file.h>
#include <getpass.h>
#include <minmax.h>
+
#include "sockets.h"
-#include "common.h"
+#include <common.h>
+#include <socket.h>
-#include "gettext.h"
-#include "cli-args.h"
+#include <gettext.h>
+#include <cli-args.h>
#define MAX_BUF 4096
@@ -65,7 +67,7 @@ const char *service = NULL;
int record_max_size;
int fingerprint;
int crlf;
-int verbose = 0;
+unsigned int verbose = 0;
extern int print_cert;
const char *srp_passwd = NULL;
@@ -92,24 +94,6 @@ static gnutls_certificate_credentials_t xcred;
/* end of global stuff */
/* prototypes */
-typedef struct
-{
- int fd;
- gnutls_session_t session;
- int secure;
- char *hostname;
- char *ip;
- char *service;
- struct addrinfo *ptr;
- struct addrinfo *addr_info;
-} socket_st;
-
-ssize_t socket_recv (const socket_st * socket, void *buffer, int buffer_size);
-ssize_t socket_send (const socket_st * socket, const void *buffer,
- int buffer_size);
-void socket_open (socket_st * hd, const char *hostname, const char *service);
-void socket_connect (const socket_st * hd);
-void socket_bye (socket_st * socket);
static void check_rehandshake (socket_st * socket, int ret);
static int do_handshake (socket_st * socket);
@@ -773,13 +757,9 @@ main (int argc, char **argv)
sockets_init ();
-#ifndef _WIN32
- signal (SIGPIPE, SIG_IGN);
-#endif
-
init_global_tls_stuff ();
- socket_open (&hd, hostname, service);
+ socket_open (&hd, hostname, service, udp);
socket_connect (&hd);
hd.session = init_tls_session (hostname);
@@ -833,7 +813,7 @@ main (int argc, char **argv)
printf
("\n\n- Connecting again- trying to resume previous session\n");
- socket_open (&hd, hostname, service);
+ socket_open (&hd, hostname, service, udp);
socket_connect (&hd);
}
else
@@ -1384,168 +1364,4 @@ init_global_tls_stuff (void)
}
-/* Functions to manipulate sockets
- */
-
-ssize_t
-socket_recv (const socket_st * socket, void *buffer, int buffer_size)
-{
- int ret;
-
- if (socket->secure)
- do
- {
- ret = gnutls_record_recv (socket->session, buffer, buffer_size);
- }
- while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
- else
- do
- {
- ret = recv (socket->fd, buffer, buffer_size, 0);
- }
- while (ret == -1 && errno == EINTR);
-
- return ret;
-}
-
-ssize_t
-socket_send (const socket_st * socket, const void *buffer, int buffer_size)
-{
- int ret;
-
- if (socket->secure)
- do
- {
- ret = gnutls_record_send (socket->session, buffer, buffer_size);
- }
- while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
- else
- do
- {
- ret = send (socket->fd, buffer, buffer_size, 0);
- }
- while (ret == -1 && errno == EINTR);
-
- if (ret > 0 && ret != buffer_size && verbose)
- fprintf (stderr,
- "*** Only sent %d bytes instead of %d.\n", ret, buffer_size);
-
- return ret;
-}
-
-void
-socket_bye (socket_st * socket)
-{
- int ret;
- if (socket->secure)
- {
- do
- ret = gnutls_bye (socket->session, GNUTLS_SHUT_WR);
- while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
- if (ret < 0)
- fprintf (stderr, "*** gnutls_bye() error: %s\n",
- gnutls_strerror (ret));
- gnutls_deinit (socket->session);
- socket->session = NULL;
- }
-
- freeaddrinfo (socket->addr_info);
- socket->addr_info = socket->ptr = NULL;
-
- free (socket->ip);
- free (socket->hostname);
- free (socket->service);
-
- shutdown (socket->fd, SHUT_RDWR); /* no more receptions */
- close (socket->fd);
-
- socket->fd = -1;
- socket->secure = 0;
-}
-
-void
-socket_connect (const socket_st * hd)
-{
- int err;
-
- printf ("Connecting to '%s:%s'...\n", hd->ip, hd->service);
-
- err = connect (hd->fd, hd->ptr->ai_addr, hd->ptr->ai_addrlen);
- if (err < 0)
- {
- fprintf (stderr, "Cannot connect to %s:%s: %s\n", hd->hostname,
- hd->service, strerror (errno));
- exit (1);
- }
-}
-
-void
-socket_open (socket_st * hd, const char *hostname, const char *service)
-{
- struct addrinfo hints, *res, *ptr;
- int sd, err;
- char buffer[MAX_BUF + 1];
- char portname[16] = { 0 };
-
- printf ("Resolving '%s'...\n", hostname);
- /* get server name */
- memset (&hints, 0, sizeof (hints));
- hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
- if ((err = getaddrinfo (hostname, service, &hints, &res)))
- {
- fprintf (stderr, "Cannot resolve %s:%s: %s\n", hostname, service,
- gai_strerror (err));
- exit (1);
- }
-
- sd = -1;
- for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
- {
- sd = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
- if (sd == -1)
- continue;
-
- if ((err = getnameinfo (ptr->ai_addr, ptr->ai_addrlen, buffer, MAX_BUF,
- portname, sizeof (portname),
- NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
- {
- fprintf (stderr, "getnameinfo(): %s\n", gai_strerror (err));
- freeaddrinfo (res);
- exit (1);
- }
-
- break;
- }
-
- if (sd == -1)
- {
- fprintf (stderr, "socket(): %s\n", strerror (errno));
- exit (1);
- }
-
- if (hints.ai_socktype == SOCK_DGRAM)
- {
-#if defined(IP_DONTFRAG)
- int yes = 1;
- if (setsockopt (sd, IPPROTO_IP, IP_DONTFRAG,
- (const void *) &yes, sizeof (yes)) < 0)
- perror ("setsockopt(IP_DF) failed");
-#elif defined(IP_MTU_DISCOVER)
- int yes = IP_PMTUDISC_DO;
- if (setsockopt(sd, IPPROTO_IP, IP_MTU_DISCOVER,
- (const void*) &yes, sizeof (yes)) < 0)
- perror ("setsockopt(IP_DF) failed");
-#endif
- }
-
- hd->secure = 0;
- hd->fd = sd;
- hd->hostname = strdup (hostname);
- hd->ip = strdup (buffer);
- hd->service = strdup (portname);
- hd->ptr = ptr;
- hd->addr_info = res;
-
- return;
-}
diff --git a/src/common.c b/src/common.c
index dcaf421dcd..40aa5b05d5 100644
--- a/src/common.c
+++ b/src/common.c
@@ -882,42 +882,3 @@ print_list (const char *priorities, int verbose)
}
}
-void
-sockets_init (void)
-{
-#ifdef _WIN32
- WORD wVersionRequested;
- WSADATA wsaData;
-
- wVersionRequested = MAKEWORD (1, 1);
- if (WSAStartup (wVersionRequested, &wsaData) != 0)
- {
- perror ("WSA_STARTUP_ERROR");
- }
-#endif
-}
-
-/* converts a service name or a port (in string) to a
- * port number. The protocol is assumed to be TCP.
- *
- * returns -1 on error;
- */
-int
-service_to_port (const char *service)
-{
- int port;
- struct servent *server_port;
-
- port = atoi (service);
- if (port != 0)
- return port;
-
- server_port = getservbyname (service, "tcp");
- if (server_port == NULL)
- {
- perror ("getservbyname()");
- return (-1);
- }
-
- return ntohs (server_port->s_port);
-}
diff --git a/src/common.h b/src/common.h
index f8254cf71f..dd6d569881 100644
--- a/src/common.h
+++ b/src/common.h
@@ -55,6 +55,4 @@ void print_cert_info (gnutls_session_t state, const char *hostname,
void print_list (const char* priorities, int verbose);
const char *raw_to_string (const unsigned char *raw, size_t raw_size);
-int service_to_port (const char *service);
void pkcs11_common (void);
-void sockets_init (void);
diff --git a/src/ocsptool-args.def.in b/src/ocsptool-args.def.in
index 70182b6310..7f4fb3ab85 100644
--- a/src/ocsptool-args.def.in
+++ b/src/ocsptool-args.def.in
@@ -36,6 +36,17 @@ flag = {
};
flag = {
+ name = ask;
+ arg-type = string;
+ arg-name = "url";
+ arg-optional;
+ descrip = "Ask server about the loaded certificate";
+ flags-must = load-cert;
+ flags-must = load-issuer;
+ doc = "Connects to the specified HTTP URL and queries an OCSP request.";
+};
+
+flag = {
name = verify-response;
value = e;
descrip = "Verify response";
diff --git a/src/ocsptool.c b/src/ocsptool.c
index c90e6a9bff..9810f0db43 100644
--- a/src/ocsptool.c
+++ b/src/ocsptool.c
@@ -35,6 +35,7 @@
#include <progname.h>
#include <version-etc.h>
#include <read-file.h>
+#include <socket.h>
#include <ocsptool-common.h>
#include <ocsptool-args.h>
@@ -42,6 +43,7 @@
FILE *outfile;
FILE *infile;
static unsigned int encoding;
+unsigned int verbose = 0;
static void
tls_log_func (int level, const char *str)
@@ -85,17 +87,39 @@ request_info (void)
}
static void
-response_info (void)
+_response_info (const gnutls_datum_t* data)
{
gnutls_ocsp_resp_t resp;
int ret;
- gnutls_datum_t dat;
- size_t size;
+ gnutls_datum buf;
ret = gnutls_ocsp_resp_init (&resp);
if (ret < 0)
error (EXIT_FAILURE, 0, "ocsp_resp_init: %s", gnutls_strerror (ret));
+ ret = gnutls_ocsp_resp_import (resp, data);
+ if (ret < 0)
+ error (EXIT_FAILURE, 0, "importing response: %s", gnutls_strerror (ret));
+
+ if (ENABLED_OPT(VERBOSE))
+ ret = gnutls_ocsp_resp_print (resp, GNUTLS_OCSP_PRINT_FULL, &buf);
+ else
+ ret = gnutls_ocsp_resp_print (resp, GNUTLS_OCSP_PRINT_COMPACT, &buf);
+ if (ret != 0)
+ error (EXIT_FAILURE, 0, "ocsp_resp_print: %s", gnutls_strerror (ret));
+
+ printf ("%.*s", buf.size, buf.data);
+ gnutls_free (buf.data);
+
+ gnutls_ocsp_resp_deinit (resp);
+}
+
+static void
+response_info (void)
+{
+ gnutls_datum_t dat;
+ size_t size;
+
if (HAVE_OPT(LOAD_RESPONSE))
dat.data = (void*)read_binary_file (OPT_ARG(LOAD_RESPONSE), &size);
else
@@ -104,19 +128,8 @@ response_info (void)
error (EXIT_FAILURE, errno, "reading response");
dat.size = size;
- ret = gnutls_ocsp_resp_import (resp, &dat);
- free (dat.data);
- if (ret < 0)
- error (EXIT_FAILURE, 0, "importing response: %s", gnutls_strerror (ret));
-
- ret = gnutls_ocsp_resp_print (resp, GNUTLS_OCSP_PRINT_FULL, &dat);
- if (ret != 0)
- error (EXIT_FAILURE, 0, "ocsp_resp_print: %s", gnutls_strerror (ret));
-
- printf ("%.*s", dat.size, dat.data);
+ _response_info(&dat);
gnutls_free (dat.data);
-
- gnutls_ocsp_resp_deinit (resp);
}
static gnutls_x509_crt_t
@@ -180,7 +193,7 @@ load_cert (void)
}
static void
-generate_request (void)
+_generate_request (gnutls_datum_t * rdata)
{
gnutls_ocsp_req_t req;
int ret;
@@ -193,14 +206,14 @@ generate_request (void)
issuer = load_issuer ();
cert = load_cert ();
-
+
ret = gnutls_ocsp_req_add_cert (req, GNUTLS_DIG_SHA1,
- issuer, cert);
+ issuer, cert);
if (ret < 0)
error (EXIT_FAILURE, 0, "ocsp_req_add_cert: %s", gnutls_strerror (ret));
-
- gnutls_x509_crt_deinit (cert);
+
gnutls_x509_crt_deinit (issuer);
+ gnutls_x509_crt_deinit (cert);
if (ENABLED_OPT(NONCE))
{
@@ -221,13 +234,25 @@ generate_request (void)
if (ret != 0)
error (EXIT_FAILURE, 0, "ocsp_req_export: %s", gnutls_strerror (ret));
+ gnutls_ocsp_req_deinit (req);
+
+ memcpy(rdata, &dat, sizeof(*rdata));
+ return;
+}
+
+static void
+generate_request (void)
+{
+ gnutls_datum_t dat;
+
+ _generate_request(&dat);
+
fwrite (dat.data, 1, dat.size, outfile);
gnutls_free (dat.data);
-
- gnutls_ocsp_req_deinit (req);
}
+
static void
print_verify_res (unsigned int output)
{
@@ -301,33 +326,24 @@ print_verify_res (unsigned int output)
}
}
-static void
-verify_response (void)
+static int
+_verify_response (gnutls_datum_t *data)
{
gnutls_ocsp_resp_t resp;
int ret;
- gnutls_datum_t dat;
size_t size;
gnutls_x509_crt_t *x509_ca_list = NULL;
unsigned int x509_ncas = 0;
gnutls_x509_trust_list_t list;
gnutls_x509_crt_t signer;
unsigned verify;
+ gnutls_datum_t dat;
ret = gnutls_ocsp_resp_init (&resp);
if (ret < 0)
error (EXIT_FAILURE, 0, "ocsp_resp_init: %s", gnutls_strerror (ret));
- if (HAVE_OPT(LOAD_RESPONSE))
- dat.data = (void*)read_binary_file (OPT_ARG(LOAD_RESPONSE), &size);
- else
- dat.data = (void*)fread_file (infile, &size);
- if (dat.data == NULL)
- error (EXIT_FAILURE, errno, "reading response");
- dat.size = size;
-
- ret = gnutls_ocsp_resp_import (resp, &dat);
- free (dat.data);
+ ret = gnutls_ocsp_resp_import (resp, data);
if (ret < 0)
error (EXIT_FAILURE, 0, "importing response: %s", gnutls_strerror (ret));
@@ -423,8 +439,182 @@ verify_response (void)
printf (".\n");
gnutls_ocsp_resp_deinit (resp);
+
+ return verify;
+}
+
+static void
+verify_response (void)
+{
+ gnutls_datum_t dat;
+ size_t size;
+
+ if (HAVE_OPT(LOAD_RESPONSE))
+ dat.data = (void*)read_binary_file (OPT_ARG(LOAD_RESPONSE), &size);
+ else
+ dat.data = (void*)fread_file (infile, &size);
+ if (dat.data == NULL)
+ error (EXIT_FAILURE, errno, "reading response");
+ dat.size = size;
+
+ _verify_response(&dat);
+}
+
+static size_t get_data(void *buffer, size_t size, size_t nmemb, void *userp)
+{
+gnutls_datum_t *ud = userp;
+
+ size *= nmemb;
+
+ ud->data = realloc(ud->data, size+ud->size);
+ if (ud->data == NULL)
+ {
+ fprintf(stderr, "Not enough memory for the request\n");
+ exit(1);
+ }
+
+ memcpy(&ud->data[ud->size], buffer, size);
+ ud->size += size;
+
+ return size;
}
+/* returns the host part of a URL */
+static const char* host_from_url(const char* url, unsigned int* port)
+{
+static char hostname[512];
+char * p;
+
+ *port = 0;
+
+ if ((p=strstr(url, "http://")) != NULL)
+ {
+ snprintf(hostname, sizeof(hostname), "%s", p+7);
+ p = strchr(hostname, '/');
+ if (p != NULL) *p = 0;
+
+ p = strchr(hostname, ':');
+ if (p != NULL) {
+ *p = 0;
+ *port = atoi(p+1);
+ }
+
+ return hostname;
+ }
+ else
+ {
+ return url;
+ }
+}
+
+#define MAX_BUF 4*1024
+#define HEADER_PATTERN "POST / HTTP/1.1\r\n" \
+ "Host: %s\r\n" \
+ "Accept: */*\r\n" \
+ "Content-Type: application/ocsp-request\r\n" \
+ "Content-Length: %u\r\n" \
+ "Connection: close\r\n\r\n"
+static char buffer[MAX_BUF + 1];
+
+static void ask_server(const char* _url)
+{
+gnutls_datum_t ud, resp_data;
+int ret, v;
+gnutls_datum_t req;
+char* url = (void*)_url;
+char headers[1024];
+char service[16];
+const char *hostname;
+unsigned int headers_size = 0, port;
+socket_st hd;
+
+ sockets_init ();
+
+ if (url == NULL)
+ {
+ /* try to read URL from issuer certificate */
+ gnutls_x509_crt_t issuer = load_issuer();
+ gnutls_datum_t data;
+
+ ret = gnutls_x509_crt_get_authority_info_access(issuer, 0,
+ GNUTLS_IA_OCSP_URI, &data, NULL);
+ if (ret < 0)
+ {
+ fprintf(stderr, "Cannot find URL from issuer: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ url = malloc(data.size+1);
+ memcpy(url, data.data, data.size);
+ url[data.size] = 0;
+
+ gnutls_free(data.data);
+
+ gnutls_x509_crt_deinit(issuer);
+ }
+
+ hostname = host_from_url(url, &port);
+ if (port != 0)
+ snprintf(service, sizeof(service), "%u", port);
+ else strcpy(service, "80");
+
+ fprintf(stderr, "Connecting to %s\n", hostname);
+
+ memset(&ud, 0, sizeof(ud));
+
+ _generate_request(&req);
+
+ snprintf(headers, sizeof(headers), HEADER_PATTERN, hostname, (unsigned int)req.size);
+ headers_size = strlen(headers);
+
+ socket_open(&hd, hostname, service, 0);
+ socket_connect (&hd);
+
+ socket_send(&hd, headers, headers_size);
+ socket_send(&hd, req.data, req.size);
+
+ do {
+ ret = socket_recv(&hd, buffer, sizeof(buffer));
+ if (ret > 0) get_data(buffer, ret, 1, &ud);
+ } while(ret > 0);
+
+ if (ret < 0 || ud.size == 0)
+ {
+ perror("recv");
+ exit(1);
+ }
+
+ socket_bye(&hd);
+
+ resp_data.data = memmem(ud.data, ud.size, "\r\n\r\n", 4);
+ if (resp_data.data == NULL)
+ {
+ fprintf(stderr, "Cannot interpret HTTP response\n");
+ exit(1);
+ }
+
+ resp_data.data += 4;
+ resp_data.size = ud.size - (resp_data.data - ud.data);
+
+ _response_info (&resp_data);
+
+ if (HAVE_OPT(LOAD_SIGNER))
+ {
+ fprintf(outfile, "\n");
+ v = _verify_response(&resp_data);
+ }
+ else
+ {
+ fprintf(stderr, "\nResponse could not be verified (use --load-signer).\n");
+ v = 0;
+ }
+
+ if (HAVE_OPT(OUTFILE) && v == 0)
+ {
+ fwrite(resp_data.data, 1, resp_data.size, outfile);
+ }
+}
+
int
main (int argc, char **argv)
{
@@ -471,6 +661,8 @@ main (int argc, char **argv)
generate_request ();
else if (HAVE_OPT(VERIFY_RESPONSE))
verify_response ();
+ else if (HAVE_OPT(ASK))
+ ask_server(OPT_ARG(ASK));
else
{
USAGE(1);
diff --git a/src/serv.c b/src/serv.c
index 351df98fd0..151ee301e3 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -40,6 +40,7 @@
#include <list.h>
#include <netdb.h>
#include <unistd.h>
+#include <socket.h>
/* Gnulib portability files. */
#include "progname.h"
@@ -58,7 +59,7 @@ static int http = 0;
static int x509ctype;
static int debug = 0;
-int verbose = 1;
+unsigned int verbose = 1;
static int nodb;
static int noticket;
int require_cert;
@@ -911,7 +912,6 @@ main (int argc, char **argv)
cmd_parser(argc, argv);
#ifndef _WIN32
- signal (SIGPIPE, SIG_IGN);
signal (SIGHUP, SIG_IGN);
signal (SIGTERM, terminate);
if (signal (SIGINT, terminate) == SIG_IGN)
diff --git a/src/socket.c b/src/socket.c
new file mode 100644
index 0000000000..3dc722b648
--- /dev/null
+++ b/src/socket.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2000-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#elif HAVE_WS2TCPIP_H
+# include <ws2tcpip.h>
+#endif
+#include <netdb.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef _WIN32
+# include <unistd.h>
+# include <signal.h>
+#endif
+#include <socket.h>
+#include "sockets.h"
+
+#define MAX_BUF 4096
+
+extern unsigned int verbose;
+/* Functions to manipulate sockets
+ */
+
+ssize_t
+socket_recv (const socket_st * socket, void *buffer, int buffer_size)
+{
+ int ret;
+
+ if (socket->secure)
+ do
+ {
+ ret = gnutls_record_recv (socket->session, buffer, buffer_size);
+ }
+ while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
+ else
+ do
+ {
+ ret = recv (socket->fd, buffer, buffer_size, 0);
+ }
+ while (ret == -1 && errno == EINTR);
+
+ return ret;
+}
+
+ssize_t
+socket_send (const socket_st * socket, const void *buffer, int buffer_size)
+{
+ int ret;
+
+ if (socket->secure)
+ do
+ {
+ ret = gnutls_record_send (socket->session, buffer, buffer_size);
+ }
+ while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
+ else
+ do
+ {
+ ret = send (socket->fd, buffer, buffer_size, 0);
+ }
+ while (ret == -1 && errno == EINTR);
+
+ if (ret > 0 && ret != buffer_size && verbose)
+ fprintf (stderr,
+ "*** Only sent %d bytes instead of %d.\n", ret, buffer_size);
+
+ return ret;
+}
+
+void
+socket_bye (socket_st * socket)
+{
+ int ret;
+ if (socket->secure)
+ {
+ do
+ ret = gnutls_bye (socket->session, GNUTLS_SHUT_WR);
+ while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
+ if (ret < 0)
+ fprintf (stderr, "*** gnutls_bye() error: %s\n",
+ gnutls_strerror (ret));
+ gnutls_deinit (socket->session);
+ socket->session = NULL;
+ }
+
+ freeaddrinfo (socket->addr_info);
+ socket->addr_info = socket->ptr = NULL;
+
+ free (socket->ip);
+ free (socket->hostname);
+ free (socket->service);
+
+ shutdown (socket->fd, SHUT_RDWR); /* no more receptions */
+ close (socket->fd);
+
+ socket->fd = -1;
+ socket->secure = 0;
+}
+
+void
+socket_connect (const socket_st * hd)
+{
+ int err;
+
+ printf ("Connecting to '%s:%s'...\n", hd->ip, hd->service);
+
+ err = connect (hd->fd, hd->ptr->ai_addr, hd->ptr->ai_addrlen);
+ if (err < 0)
+ {
+ fprintf (stderr, "Cannot connect to %s:%s: %s\n", hd->hostname,
+ hd->service, strerror (errno));
+ exit (1);
+ }
+}
+
+void
+socket_open (socket_st * hd, const char *hostname, const char *service, int udp)
+{
+ struct addrinfo hints, *res, *ptr;
+ int sd, err;
+ char buffer[MAX_BUF + 1];
+ char portname[16] = { 0 };
+
+ printf ("Resolving '%s'...\n", hostname);
+ /* get server name */
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
+ if ((err = getaddrinfo (hostname, service, &hints, &res)))
+ {
+ fprintf (stderr, "Cannot resolve %s:%s: %s\n", hostname, service,
+ gai_strerror (err));
+ exit (1);
+ }
+
+ sd = -1;
+ for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
+ {
+ sd = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
+ if (sd == -1)
+ continue;
+
+ if ((err = getnameinfo (ptr->ai_addr, ptr->ai_addrlen, buffer, MAX_BUF,
+ portname, sizeof (portname),
+ NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
+ {
+ fprintf (stderr, "getnameinfo(): %s\n", gai_strerror (err));
+ freeaddrinfo (res);
+ exit (1);
+ }
+
+ break;
+ }
+
+ if (sd == -1)
+ {
+ fprintf (stderr, "socket(): %s\n", strerror (errno));
+ exit (1);
+ }
+
+ if (hints.ai_socktype == SOCK_DGRAM)
+ {
+#if defined(IP_DONTFRAG)
+ int yes = 1;
+ if (setsockopt (sd, IPPROTO_IP, IP_DONTFRAG,
+ (const void *) &yes, sizeof (yes)) < 0)
+ perror ("setsockopt(IP_DF) failed");
+#elif defined(IP_MTU_DISCOVER)
+ int yes = IP_PMTUDISC_DO;
+ if (setsockopt(sd, IPPROTO_IP, IP_MTU_DISCOVER,
+ (const void*) &yes, sizeof (yes)) < 0)
+ perror ("setsockopt(IP_DF) failed");
+#endif
+ }
+
+ hd->secure = 0;
+ hd->fd = sd;
+ hd->hostname = strdup (hostname);
+ hd->ip = strdup (buffer);
+ hd->service = strdup (portname);
+ hd->ptr = ptr;
+ hd->addr_info = res;
+
+ return;
+}
+
+void
+sockets_init (void)
+{
+#ifdef _WIN32
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+ wVersionRequested = MAKEWORD (1, 1);
+ if (WSAStartup (wVersionRequested, &wsaData) != 0)
+ {
+ perror ("WSA_STARTUP_ERROR");
+ }
+#else
+ signal (SIGPIPE, SIG_IGN);
+#endif
+
+}
+
+/* converts a service name or a port (in string) to a
+ * port number. The protocol is assumed to be TCP.
+ *
+ * returns -1 on error;
+ */
+int
+service_to_port (const char *service)
+{
+ int port;
+ struct servent *server_port;
+
+ port = atoi (service);
+ if (port != 0)
+ return port;
+
+ server_port = getservbyname (service, "tcp");
+ if (server_port == NULL)
+ {
+ perror ("getservbyname()");
+ return (-1);
+ }
+
+ return ntohs (server_port->s_port);
+}
diff --git a/src/socket.h b/src/socket.h
new file mode 100644
index 0000000000..4846465092
--- /dev/null
+++ b/src/socket.h
@@ -0,0 +1,23 @@
+#include <gnutls/gnutls.h>
+
+typedef struct
+{
+ int fd;
+ gnutls_session_t session;
+ int secure;
+ char *hostname;
+ char *ip;
+ char *service;
+ struct addrinfo *ptr;
+ struct addrinfo *addr_info;
+} socket_st;
+
+ssize_t socket_recv (const socket_st * socket, void *buffer, int buffer_size);
+ssize_t socket_send (const socket_st * socket, const void *buffer,
+ int buffer_size);
+void socket_open (socket_st * hd, const char *hostname, const char *service, int udp);
+void socket_connect (const socket_st * hd);
+void socket_bye (socket_st * socket);
+
+void sockets_init (void);
+int service_to_port (const char *service);
diff --git a/src/tls_test.c b/src/tls_test.c
index efef925842..2ba714ded1 100644
--- a/src/tls_test.c
+++ b/src/tls_test.c
@@ -34,6 +34,7 @@
#include <tests.h>
#include <common.h>
#include <cli-debug-args.h>
+#include <socket.h>
/* Gnulib portability files. */
#include <progname.h>
@@ -59,8 +60,7 @@ gnutls_certificate_credentials_t xcred;
/* end of global stuff */
-
-int verbose = 0;
+unsigned int verbose = 0;
extern int tls1_ok;
extern int tls1_1_ok;