gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls-3_0_12-92-g015780d


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls-3_0_12-92-g015780d
Date: Fri, 27 Jan 2012 19:39:17 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=015780d11567c3421c2f92ab5246c2237d210422

The branch, master has been updated
       via  015780d11567c3421c2f92ab5246c2237d210422 (commit)
       via  c62c365b893c783ca466912dc830ace1bff87653 (commit)
      from  ee7b5358c29aa106e62c554fdb61aa43aa589d46 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 015780d11567c3421c2f92ab5246c2237d210422
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Jan 26 19:18:58 2012 +0100

    Combined ocsp apps to 1 using libcurl.

commit c62c365b893c783ca466912dc830ace1bff87653
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Wed Jan 25 23:48:46 2012 +0100

    Added --ask option to ocsptool.

-----------------------------------------------------------------------

Summary of changes:
 NEWS                          |    3 +
 doc/cha-gtls-examples.texi    |   35 +--
 doc/examples/Makefile.am      |    8 +-
 doc/examples/ex-ocsp-client.c |  483 ++++++++++++++++++++++++++---------------
 doc/examples/ex-ocsp-verify.c |  153 -------------
 lib/includes/gnutls/ocsp.h    |    2 +
 lib/x509/ocsp_output.c        |   21 +-
 src/Makefile.am               |   22 ++-
 src/cli.c                     |  200 +----------------
 src/common.c                  |   39 ----
 src/common.h                  |    2 -
 src/ocsptool-args.def.in      |   11 +
 src/ocsptool.c                |  262 +++++++++++++++++++---
 src/serv.c                    |    4 +-
 src/socket.c                  |  250 +++++++++++++++++++++
 src/socket.h                  |   23 ++
 src/tls_test.c                |    4 +-
 17 files changed, 876 insertions(+), 646 deletions(-)
 delete mode 100644 doc/examples/ex-ocsp-verify.c
 create mode 100644 src/socket.c
 create mode 100644 src/socket.h

diff --git a/NEWS b/NEWS
index 2ed8327..c6aed0e 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ See the end for copying conditions.
 
 * Version 3.0.13 (unreleased)
 
+** ocsptool: Added --ask parameter, to verify a certificate's
+status from an ocsp server.
+
 ** command line apps: Use gnu autogen (libopts) to parse command
 line arguments and template files.
 
diff --git a/doc/cha-gtls-examples.texi b/doc/cha-gtls-examples.texi
index c08f9cd..8fbf6b8 100644
--- a/doc/cha-gtls-examples.texi
+++ b/doc/cha-gtls-examples.texi
@@ -11,7 +11,7 @@ no error checking.
 @menu
 * Client examples::
 * Server examples::
-* OCSP examples::
+* OCSP example::
 * Miscellaneous examples::
 @end menu
 
@@ -210,28 +210,6 @@ used to serve the example client for anonymous 
authentication.
 
 @verbatiminclude examples/ex-serv-anon.c
 
address@hidden OCSP examples
address@hidden OCSP examples
-
address@hidden
-* Generate OCSP request::
-* Verify OCSP response::
address@hidden menu
-
address@hidden Generate OCSP request
address@hidden Generate @acronym{OCSP} request
-
-A small tool to generate OCSP requests.
-
address@hidden examples/ex-ocsp-client.c
-
address@hidden Verify OCSP response
address@hidden Verify @acronym{OCSP} response
-
-A small tool to verify OCSP responses.
-
address@hidden examples/ex-ocsp-verify.c
-
 @node DTLS echo server with X.509 authentication
 @subsection DTLS echo server with @acronym{X.509} authentication
 
@@ -240,6 +218,17 @@ This example is a very simple echo server using Datagram 
TLS and
 
 @verbatiminclude examples/ex-serv-dtls.c
 
+
address@hidden OCSP example
address@hidden OCSP example
+
address@hidden OCSP request}
address@hidden Generate @acronym{OCSP} request
+
+A small tool to generate OCSP requests.
+
address@hidden examples/ex-ocsp-client.c
+
 @node Miscellaneous examples
 @section Miscellaneous examples
 
diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am
index 7115e4b..ba6d047 100644
--- a/doc/examples/Makefile.am
+++ b/doc/examples/Makefile.am
@@ -29,7 +29,7 @@ AM_CPPFLAGS = \
 # Gnulib warns and suggests use of fseeko instead of fseek, which is
 # used in ex-cert-select.c, but certificate files will not be > 4 GB,
 # so we just silence the warning instead of fixing the code here.
-AM_CPPFLAGS += -D_GL_NO_LARGE_FILES
+AM_CPPFLAGS += -D_GL_NO_LARGE_FILES -DNO_LIBCURL
 
 AM_LDFLAGS = -no-install
 LDADD = libexamples.la                         \
@@ -76,12 +76,12 @@ if ENABLE_SRP
 noinst_PROGRAMS += ex-client-srp ex-serv-srp
 endif
 
+noinst_LTLIBRARIES = libexamples.la
+
 if ENABLE_OCSP
-noinst_PROGRAMS += ex-ocsp-client ex-ocsp-verify
+noinst_PROGRAMS += ex-ocsp-client
 endif
 
-noinst_LTLIBRARIES = libexamples.la
-
 libexamples_la_SOURCES = examples.h ex-alert.c ex-pkcs12.c \
        ex-session-info.c ex-x509-info.c ex-verify.c    \
        tcp.c udp.c ex-pkcs11-list.c verify.c
diff --git a/doc/examples/ex-ocsp-client.c b/doc/examples/ex-ocsp-client.c
index 6d8f080..9ca7100 100644
--- a/doc/examples/ex-ocsp-client.c
+++ b/doc/examples/ex-ocsp-client.c
@@ -8,186 +8,321 @@
 #include <stdlib.h>
 #include <string.h>
 #include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
 #include <gnutls/ocsp.h>
-
+#ifndef NO_LIBCURL
+#include <curl/curl.h>
+#endif
 #include "read-file.h"
 
-/* This program will read a file (argv[1]) containing a certificate in
-   PEM format and print the "CA issuers" and "OCSP address" extensions
-   for the certificate.  If another file is given (argv[2]) it holds
-   the issuer certificate for the first certificate.  Then the tool
-   will generate an OCSP request for the certificate and write it to
-   the file "ocsp-req.der". */
+size_t get_data (void *buffer, size_t size, size_t nmemb,
+                        void *userp);
+static gnutls_x509_crt_t load_cert (const char *cert_file);
+static void _response_info (const gnutls_datum_t * data);
+static void
+_generate_request (gnutls_datum_t * rdata, const char *cert_file,
+                   const char *issuer_file);
+static int _verify_response (gnutls_datum_t * data,
+                             const char *signer_file);
+
+/* This program queries an OCSP server.
+   It expects three files. argv[1] containing the certificate to
+   be checked, argv[2] holding the issuer for this certificate,
+   and argv[3] holding a trusted certificate to verify OCSP's response.
+   argv[4] is optional and should hold the server host name.
+   
+   For simplicity the libcurl library is used.
+ */
 
 int
 main (int argc, char *argv[])
 {
-  int rc;
-  gnutls_x509_crt_t cert = NULL, issuer = NULL;
-  gnutls_datum_t certdata, issuerdata, tmp;
-  size_t s;
-  unsigned int seq;
-  gnutls_ocsp_req_t ocspreq = NULL;
-  FILE *fh;
-
-  rc = gnutls_global_init ();
-  if (rc < 0)
-    goto done;
-
-  /* Read certificate and print AIA info. */
-
-  rc = gnutls_x509_crt_init (&cert);
-  if (rc < 0)
-    goto done;
-
-  certdata.data = (void*)read_binary_file (argv[1], &s);
-  if (certdata.data == NULL)
-    {
-      printf ("cannot read certificate\n");
-      goto done;
-    }
-  certdata.size = s;
-
-  rc = gnutls_x509_crt_import (cert, &certdata, GNUTLS_X509_FMT_PEM);
-  free (certdata.data);
-  if (rc < 0)
-    goto done;
-
-  rc = gnutls_x509_crt_print (cert, GNUTLS_CRT_PRINT_ONELINE, &tmp);
-  if (rc < 0)
-    goto done;
-
-  printf ("cert: %.*s\n", tmp.size, tmp.data);
-
-  gnutls_free (tmp.data); tmp.data = NULL;
-
-  for (seq = 0; ; seq++)
-    {
-      rc = gnutls_x509_crt_get_authority_info_access (cert, seq,
-                                                     GNUTLS_IA_CAISSUERS_URI,
-                                                     &tmp, NULL);
-      if (rc == GNUTLS_E_UNKNOWN_ALGORITHM)
-       continue;
-      if (rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
-       break;
-      if (rc < 0)
-       goto done;
-
-      printf ("CA issuers URI: %.*s\n", tmp.size, tmp.data);
-      gnutls_free (tmp.data);
-      break;
-    }
-
-  if (!tmp.data)
-    printf ("No CA issuers URI found\n");
-
-  for (seq = 0; ; seq++)
-    {
-      rc = gnutls_x509_crt_get_authority_info_access (cert, seq,
-                                                     GNUTLS_IA_OCSP_URI,
-                                                     &tmp, NULL);
-      if (rc == GNUTLS_E_UNKNOWN_ALGORITHM)
-       continue;
-      if (rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
-       break;
-      if (rc < 0)
-       goto done;
-
-      printf ("OCSP URI: %.*s\n", tmp.size, tmp.data);
-      gnutls_free (tmp.data);
-      break;
-    }
-
-  if (!tmp.data)
-    printf ("No OCSP URI URI found\n");
-
-  if (argc < 3)
-    {
-      printf ("Done...\n");
-      goto done;
-    }
-
-  /* Read issuer cert and print brief info about it. */
-
-  rc = gnutls_x509_crt_init (&issuer);
-  if (rc < 0)
-    goto done;
-
-  issuerdata.data = (void*)read_binary_file (argv[2], &s);
-  if (issuerdata.data == NULL)
-    {
-      printf ("cannot read issuer\n");
-      goto done;
-    }
-  issuerdata.size = s;
-
-  rc = gnutls_x509_crt_import (issuer, &issuerdata, GNUTLS_X509_FMT_PEM);
-  free (issuerdata.data);
-  if (rc < 0)
-    goto done;
-
-  rc = gnutls_x509_crt_print (issuer, GNUTLS_CRT_PRINT_ONELINE, &tmp);
-  if (rc < 0)
-    goto done;
-
-  printf ("issuer: %.*s\n", tmp.size, tmp.data);
-
-  gnutls_free (tmp.data);
-
-  /* Generate OCSP request and write it. */
-
-  rc = gnutls_ocsp_req_init (&ocspreq);
-  if (rc < 0)
-    goto done;
-
-  rc = gnutls_ocsp_req_add_cert (ocspreq, GNUTLS_DIG_SHA1, issuer, cert);
-  if (rc < 0)
-    goto done;
-
-  rc = gnutls_ocsp_req_print (ocspreq, GNUTLS_OCSP_PRINT_FULL, &tmp);
-  if (rc < 0)
-    goto done;
-
-  printf ("ocsp request: %.*s\n", tmp.size, tmp.data);
-
-  gnutls_free (tmp.data);
-
-  fh = fopen ("ocsp-req.der", "w");
-  if (fh == NULL)
-    goto done;
-
-  rc = gnutls_ocsp_req_export (ocspreq, &tmp);
-  if (rc < 0)
-    goto done;
-
-  s = fwrite (tmp.data, 1, tmp.size, fh);
-
-  gnutls_free (tmp.data);
-
-  if (s != tmp.size)
-    {
-      perror ("fwrite");
-      fclose (fh);
-      goto done;
-    }
-
-  rc = fclose (fh);
-  if (rc != 0)
-    {
-      perror ("fclose");
-      rc = 0;
-      goto done;
-    }
-
-  rc = 0;
-
- done:
-  if (rc != 0)
-    printf ("error (%d): %s\n", rc, gnutls_strerror (rc));
-  gnutls_ocsp_req_deinit (ocspreq);
-  gnutls_x509_crt_deinit (cert);
-  gnutls_x509_crt_deinit (issuer);
-  gnutls_global_deinit ();
+    gnutls_datum_t ud, tmp;
+    int ret;
+    gnutls_datum_t req;
+#ifndef NO_LIBCURL
+    CURL *handle;
+    struct curl_slist *headers = NULL;
+#endif
+    int v, seq;
+    const char *cert_file = argv[1];
+    const char *issuer_file = argv[2];
+    const char *signer_file = argv[3];
+    char *hostname = NULL;
+
+    gnutls_global_init ();
+
+    if (argc > 4)
+        hostname = argv[4];
+
+    if (hostname == NULL)
+      {
+          gnutls_x509_crt_t cert = load_cert (cert_file);
+
+          for (seq = 0;; seq++)
+            {
+                ret = gnutls_x509_crt_get_authority_info_access (cert, seq,
+                                                                 
GNUTLS_IA_OCSP_URI,
+                                                                 &tmp,
+                                                                 NULL);
+                if (ret == GNUTLS_E_UNKNOWN_ALGORITHM)
+                    continue;
+                if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+                  {
+                      fprintf (stderr,
+                               "No URI was found in the certificate.\n");
+                      exit (1);
+                  }
+                if (ret < 0)
+                  {
+                      fprintf (stderr, "error: %s\n",
+                               gnutls_strerror (ret));
+                      exit (1);
+                  }
+
+                printf ("CA issuers URI: %.*s\n", tmp.size, tmp.data);
+
+                hostname = malloc (tmp.size + 1);
+                memcpy (hostname, tmp.data, tmp.size);
+                hostname[tmp.size] = 0;
+
+                gnutls_free (tmp.data);
+                break;
+            }
+
+          gnutls_x509_crt_deinit (cert);
+      }
+
+    /* Note that the OCSP servers hostname might be available
+     * using gnutls_x509_crt_get_authority_info_access() in the issuer's
+     * certificate */
+
+    memset (&ud, 0, sizeof (ud));
+    fprintf (stderr, "Connecting to %s\n", hostname);
+
+    _generate_request (&req, cert_file, issuer_file);
+
+#ifndef NO_LIBCURL
+    curl_global_init (CURL_GLOBAL_ALL);
+
+    handle = curl_easy_init ();
+    if (handle == NULL)
+        exit (1);
+
+    headers =
+        curl_slist_append (headers,
+                           "Content-Type: application/ocsp-request");
+
+    curl_easy_setopt (handle, CURLOPT_HTTPHEADER, headers);
+    curl_easy_setopt (handle, CURLOPT_POSTFIELDS, (void *) req.data);
+    curl_easy_setopt (handle, CURLOPT_POSTFIELDSIZE, req.size);
+    curl_easy_setopt (handle, CURLOPT_URL, hostname);
+    curl_easy_setopt (handle, CURLOPT_WRITEFUNCTION, get_data);
+    curl_easy_setopt (handle, CURLOPT_WRITEDATA, &ud);
+
+    ret = curl_easy_perform (handle);
+    if (ret != 0)
+      {
+          fprintf (stderr, "curl[%d] error %d\n", __LINE__, ret);
+          exit (1);
+      }
+
+    curl_easy_cleanup (handle);
+#endif
+
+    _response_info (&ud);
+
+    v = _verify_response (&ud, signer_file);
+
+    gnutls_global_deinit ();
+
+    return v;
+}
+
+static void
+_response_info (const gnutls_datum_t * data)
+{
+    gnutls_ocsp_resp_t resp;
+    int ret;
+    gnutls_datum buf;
+
+    ret = gnutls_ocsp_resp_init (&resp);
+    if (ret < 0)
+        exit (1);
+
+    ret = gnutls_ocsp_resp_import (resp, data);
+    if (ret < 0)
+        exit (1);
+
+    ret = gnutls_ocsp_resp_print (resp, GNUTLS_OCSP_PRINT_FULL, &buf);
+    if (ret != 0)
+        exit (1);
+
+    printf ("%.*s", buf.size, buf.data);
+    gnutls_free (buf.data);
+
+    gnutls_ocsp_resp_deinit (resp);
+}
+
+static gnutls_x509_crt_t
+load_cert (const char *cert_file)
+{
+    gnutls_x509_crt_t crt;
+    int ret;
+    gnutls_datum_t data;
+    size_t size;
+
+    ret = gnutls_x509_crt_init (&crt);
+    if (ret < 0)
+        exit (1);
+
+    data.data = (void *) read_binary_file (cert_file, &size);
+    data.size = size;
+
+    if (!data.data)
+      {
+          fprintf (stderr, "Cannot open file: %s\n", cert_file);
+          exit (1);
+      }
+
+    ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM);
+    free (data.data);
+    if (ret < 0)
+      {
+          fprintf (stderr, "Cannot import certificate in %s: %s\n",
+                   cert_file, gnutls_strerror (ret));
+          exit (1);
+      }
+
+    return crt;
+}
+
+static void
+_generate_request (gnutls_datum_t * rdata, const char *cert_file,
+                   const char *issuer_file)
+{
+    gnutls_ocsp_req_t req;
+    int ret;
+    gnutls_x509_crt_t issuer, cert;
+    unsigned char noncebuf[23];
+    gnutls_datum_t nonce = { noncebuf, sizeof (noncebuf) };
+
+    ret = gnutls_ocsp_req_init (&req);
+    if (ret < 0)
+        exit (1);
+
+    issuer = load_cert (issuer_file);
+    cert = load_cert (cert_file);
+
+    ret = gnutls_ocsp_req_add_cert (req, GNUTLS_DIG_SHA1, issuer, cert);
+    if (ret < 0)
+        exit (1);
+
+    gnutls_x509_crt_deinit (issuer);
+    gnutls_x509_crt_deinit (cert);
+
+    ret = gnutls_rnd (GNUTLS_RND_RANDOM, nonce.data, nonce.size);
+    if (ret < 0)
+        exit (1);
+
+    ret = gnutls_ocsp_req_set_nonce (req, 0, &nonce);
+    if (ret < 0)
+        exit (1);
+
+    ret = gnutls_ocsp_req_export (req, rdata);
+    if (ret != 0)
+        exit (1);
+
+    gnutls_ocsp_req_deinit (req);
+
+    return;
+}
+
+static int
+_verify_response (gnutls_datum_t * data, const char *signer_file)
+{
+    gnutls_ocsp_resp_t resp;
+    int ret;
+    size_t size;
+    gnutls_x509_crt_t signer;
+    unsigned verify;
+    gnutls_datum_t dat;
+
+    ret = gnutls_ocsp_resp_init (&resp);
+    if (ret < 0)
+        exit (1);
+
+    ret = gnutls_ocsp_resp_import (resp, data);
+    if (ret < 0)
+        exit (1);
+
+    ret = gnutls_x509_crt_init (&signer);
+    if (ret < 0)
+        exit (1);
+
+    dat.data = (void *) read_binary_file (signer_file, &size);
+    if (dat.data == NULL)
+        exit (1);
+
+    dat.size = size;
+
+    ret = gnutls_x509_crt_import (signer, &dat, GNUTLS_X509_FMT_PEM);
+    free (dat.data);
+    if (ret < 0)
+        exit (1);
+
+    ret = gnutls_ocsp_resp_verify_direct (resp, signer, &verify, 0);
+    if (ret < 0)
+        exit (1);
+
+    printf ("Verifying OCSP Response: ");
+    if (verify == 0)
+        printf ("Verification success!\n");
+    else
+        printf ("Verification error!\n");
+
+    if (verify & GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND)
+        printf ("Signer cert not found\n");
+
+    if (verify & GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR)
+        printf ("Signer cert keyusage error\n");
+
+    if (verify & GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER)
+        printf ("Signer cert is not trusted\n");
+
+    if (verify & GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM)
+        printf ("Insecure algorithm\n");
+
+    if (verify & GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE)
+        printf ("Signature failure\n");
+
+    if (verify & GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED)
+        printf ("Signer cert not yet activated\n");
+
+    if (verify & GNUTLS_OCSP_VERIFY_CERT_EXPIRED)
+        printf ("Signer cert expired\n");
+
+    gnutls_ocsp_resp_deinit (resp);
+
+    return verify;
+}
+
+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 rc == 0 ? 0 : 1;
+    return size;
 }
diff --git a/doc/examples/ex-ocsp-verify.c b/doc/examples/ex-ocsp-verify.c
deleted file mode 100644
index b023ac3..0000000
--- a/doc/examples/ex-ocsp-verify.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/* This example code is placed in the public domain. */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <gnutls/gnutls.h>
-#include <gnutls/ocsp.h>
-
-#include "read-file.h"
-
-/* This program will read a file (argv[1]) containing an OCSP response
-   and another file (argv[2]) containing a set of OCSP trust anchors.
-   The tool will try to verify the OCSP response against the set of
-   trust anchors.  It will also parse the OCSP response and check that
-   the X.509 certificate is still valid, or print why it is not valid
-   (according to the OCSP response).  */
-
-int
-main (int argc, char *argv[])
-{
-  int rc;
-  gnutls_datum_t tmp;
-  gnutls_ocsp_resp_t ocspresp = NULL;
-  gnutls_x509_trust_list_t trustlist = NULL;
-  gnutls_x509_crt_t *trustcerts = NULL;
-  unsigned int ntrustcerts = 0;
-  unsigned verify, i;
-  size_t s;
-
-  rc = gnutls_global_init ();
-  if (rc < 0)
-    goto done;
-
-  /* Read OCSP response and print it. */
-
-  rc = gnutls_ocsp_resp_init (&ocspresp);
-  if (rc < 0)
-    goto done;
-
-  tmp.data = (void*)read_binary_file (argv[1], &s);
-  if (tmp.data == NULL)
-    {
-      printf ("cannot read OCSP response\n");
-      goto done;
-    }
-  tmp.size = s;
-
-  rc = gnutls_ocsp_resp_import (ocspresp, &tmp);
-  free (tmp.data);
-  if (rc < 0)
-    goto done;
-
-  rc = gnutls_ocsp_resp_print (ocspresp, GNUTLS_OCSP_PRINT_FULL, &tmp);
-  if (rc < 0)
-    goto done;
-
-  printf ("ocsp response: %.*s\n", tmp.size, tmp.data);
-
-  gnutls_free (tmp.data);
-
-  if (argc < 3)
-    {
-      printf ("Done...\n");
-      goto done;
-    }
-
-  /* Read X.509 trustlist. */
-
-  rc = gnutls_x509_trust_list_init (&trustlist, 0);
-  if (rc < 0)
-    goto done;
-
-  tmp.data = (void*)read_binary_file (argv[2], &s);
-  if (tmp.data == NULL)
-    {
-      printf ("cannot read OCSP response\n");
-      goto done;
-    }
-  tmp.size = s;
-
-  rc = gnutls_x509_crt_list_import2 (&trustcerts, &ntrustcerts, &tmp,
-                                    GNUTLS_X509_FMT_PEM, 0);
-  free (tmp.data);
-  if (rc < 0)
-    goto done;
-
-  for (i = 0; i < ntrustcerts; i++)
-    {
-      gnutls_datum_t out;
-
-      rc = gnutls_x509_crt_print (trustcerts[i],
-                                 GNUTLS_CRT_PRINT_ONELINE, &out);
-      if (rc < 0)
-       goto done;
-
-      printf ("Trust anchor %d: %.*s\n", i, out.size, out.data);
-      gnutls_free (out.data);
-    }
-
-  rc = gnutls_x509_trust_list_add_cas (trustlist, trustcerts, ntrustcerts, 0);
-  gnutls_free (trustcerts);
-  if (rc < 0)
-    goto done;
-
-  printf ("Loaded %d trust anchors\n", ntrustcerts);
-
-  /* Verify it */
-
-  rc = gnutls_ocsp_resp_verify (ocspresp, trustlist, &verify, 0);
-  if (rc < 0)
-    goto done;
-
-  if (verify == 0)
-    printf ("Verification success!\n");
-  else
-    printf ("Verification error!\n");
-
-  if (verify & GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND)
-    printf ("Signer cert not found\n");
-
-  if (verify & GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR)
-    printf ("Signer cert keyusage error\n");
-
-  if (verify & GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER)
-    printf ("Signer cert is not trusted\n");
-
-  if (verify & GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM)
-    printf ("Insecure algorithm\n");
-
-  if (verify & GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE)
-    printf ("Signature failure\n");
-
-  if (verify & GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED)
-    printf ("Signer cert not yet activated\n");
-
-  if (verify & GNUTLS_OCSP_VERIFY_CERT_EXPIRED)
-    printf ("Signer cert expired\n");
-
-  rc = 0;
-
- done:
-  if (rc != 0)
-    printf ("error (%d): %s\n", rc, gnutls_strerror (rc));
-  gnutls_x509_trust_list_deinit (trustlist, 1);
-  gnutls_ocsp_resp_deinit (ocspresp);
-  gnutls_global_deinit ();
-
-  return rc == 0 ? 0 : 1;
-}
diff --git a/lib/includes/gnutls/ocsp.h b/lib/includes/gnutls/ocsp.h
index f748d75..89eb673 100644
--- a/lib/includes/gnutls/ocsp.h
+++ b/lib/includes/gnutls/ocsp.h
@@ -39,12 +39,14 @@ extern "C"
   /**
    * gnutls_ocsp_print_formats_t:
    * @GNUTLS_OCSP_PRINT_FULL: Full information about OCSP request/response.
+   * @GNUTLS_OCSP_PRINT_COMPACT: More compact information about OCSP 
request/response.
    *
    * Enumeration of different OCSP printing variants.
    */
   typedef enum gnutls_ocsp_print_formats_t
     {
       GNUTLS_OCSP_PRINT_FULL = 0,
+      GNUTLS_OCSP_PRINT_COMPACT = 1,
     } gnutls_ocsp_print_formats_t;
 
   /**
diff --git a/lib/x509/ocsp_output.c b/lib/x509/ocsp_output.c
index e1bdf82..0a0601f 100644
--- a/lib/x509/ocsp_output.c
+++ b/lib/x509/ocsp_output.c
@@ -202,7 +202,8 @@ gnutls_ocsp_req_print (gnutls_ocsp_req_t req,
 }
 
 static void
-print_resp (gnutls_buffer_st * str, gnutls_ocsp_resp_t resp)
+print_resp (gnutls_buffer_st * str, gnutls_ocsp_resp_t resp,
+            gnutls_ocsp_print_formats_t format)
 {
   int ret;
   unsigned indx;
@@ -497,7 +498,8 @@ print_resp (gnutls_buffer_st * str, gnutls_ocsp_resp_t resp)
     }
 
   /* Signature. */
-  {
+  if (format == GNUTLS_OCSP_PRINT_FULL) 
+    {
     gnutls_datum_t sig;
 
     ret = gnutls_ocsp_resp_get_signature_algorithm (resp);
@@ -527,10 +529,11 @@ print_resp (gnutls_buffer_st * str, gnutls_ocsp_resp_t 
resp)
 
        gnutls_free (sig.data);
       }
-  }
+    }
 
   /* certs */
-  {
+  if (format == GNUTLS_OCSP_PRINT_FULL) 
+    {
     gnutls_x509_crt_t *certs;
     size_t ncerts, i;
     gnutls_datum_t out;
@@ -578,7 +581,7 @@ print_resp (gnutls_buffer_st * str, gnutls_ocsp_resp_t resp)
          }
        gnutls_free (certs);
       }
-  }
+    }
 }
 
 /**
@@ -606,17 +609,11 @@ gnutls_ocsp_resp_print (gnutls_ocsp_resp_t resp,
   gnutls_buffer_st str;
   int rc;
 
-  if (format != GNUTLS_OCSP_PRINT_FULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
   _gnutls_buffer_init (&str);
 
   _gnutls_buffer_append_str (&str, _("OCSP Response Information:\n"));
 
-  print_resp (&str, resp);
+  print_resp (&str, resp, format);
 
   _gnutls_buffer_append_data (&str, "\0", 1);
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 5335b1b..136484d 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 ac0a02f..27885c5 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 dcaf421..40aa5b0 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 f8254cf..dd6d569 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 70182b6..7f4fb3a 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 c90e6a9..9810f0d 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 351df98..151ee30 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 0000000..3dc722b
--- /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 0000000..4846465
--- /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 efef925..2ba714d 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;


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]