]> sjero.net Git - wget/blobdiff - src/gnutls.c
mass change: update copyright years.
[wget] / src / gnutls.c
index 3c4c5b4cf6f8383e9be5a13fa30b988343c4217c..9e5c733b4c90c536ac46e4b6e3dfe0d5180220f0 100644 (file)
@@ -1,5 +1,5 @@
 /* SSL support via GnuTLS library.
-   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
    Foundation, Inc.
 
 This file is part of GNU Wget.
@@ -32,11 +32,10 @@ as that of the covered work.  */
 
 #include <assert.h>
 #include <errno.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
+#include <unistd.h>
 #include <string.h>
 #include <stdio.h>
+#include <dirent.h>
 #include <stdlib.h>
 
 #include <gnutls/gnutls.h>
@@ -61,15 +60,50 @@ static gnutls_certificate_credentials credentials;
 bool
 ssl_init ()
 {
+  const char *ca_directory;
+  DIR *dir;
+
   gnutls_global_init ();
   gnutls_certificate_allocate_credentials (&credentials);
+
+  ca_directory = opt.ca_directory ? opt.ca_directory : "/etc/ssl/certs";
+
+  dir = opendir (ca_directory);
+  if (dir == NULL)
+    {
+      if (opt.ca_directory)
+        logprintf (LOG_NOTQUIET, _("ERROR: Cannot open directory %s.\n"),
+                   opt.ca_directory);
+    }
+  else
+    {
+      struct dirent *dent;
+      while ((dent = readdir (dir)) != NULL)
+        {
+          struct stat st;
+          char *ca_file;
+          asprintf (&ca_file, "%s/%s", ca_directory, dent->d_name);
+
+          stat (ca_file, &st);
+
+          if (S_ISREG (st.st_mode))
+            gnutls_certificate_set_x509_trust_file (credentials, ca_file,
+                                                    GNUTLS_X509_FMT_PEM);
+
+          free (ca_file);
+        }
+
+      closedir (dir);
+    }
+
   if (opt.ca_cert)
     gnutls_certificate_set_x509_trust_file (credentials, opt.ca_cert,
                                             GNUTLS_X509_FMT_PEM);
   return true;
 }
 
-struct wgnutls_transport_context {
+struct wgnutls_transport_context
+{
   gnutls_session session;       /* GnuTLS session handle */
   int last_error;               /* last error returned by read/write/... */
 
@@ -109,6 +143,7 @@ wgnutls_read (int fd, char *buf, int bufsize, void *arg)
 
   if (ret < 0)
     ctx->last_error = ret;
+
   return ret;
 }
 
@@ -138,28 +173,39 @@ wgnutls_peek (int fd, char *buf, int bufsize, void *arg)
 {
   int ret = 0;
   struct wgnutls_transport_context *ctx = arg;
-  int offset = ctx->peeklen;
-
+  int offset = MIN (bufsize, ctx->peeklen);
   if (bufsize > sizeof ctx->peekbuf)
     bufsize = sizeof ctx->peekbuf;
 
-  if (offset)
+  if (ctx->peeklen)
     memcpy (buf, ctx->peekbuf, offset);
 
-  do
+  if (bufsize > offset)
     {
-      if (gnutls_record_check_pending (ctx->session)
-          || select_fd (fd, 0, WAIT_FOR_READ))
-        ret = gnutls_record_recv (ctx->session, buf + offset, bufsize - offset);
-    }
-  while (ret == GNUTLS_E_INTERRUPTED);
+      do
+        {
+          ret = gnutls_record_recv (ctx->session, buf + offset,
+                                    bufsize - offset);
+        }
+      while (ret == GNUTLS_E_INTERRUPTED);
 
-  if (ret > 0)
-    {
-      memcpy (ctx->peekbuf + offset, buf + offset, ret);
-      ctx->peeklen += ret;
+      if (ret < 0)
+        {
+          if (offset)
+            ret = 0;
+          else
+            return ret;
+        }
+
+      if (ret > 0)
+        {
+          memcpy (ctx->peekbuf + offset, buf + offset,
+                  ret);
+          ctx->peeklen += ret;
+        }
     }
-  return ctx->peeklen;
+
+  return offset + ret;
 }
 
 static const char *
@@ -182,7 +228,8 @@ wgnutls_close (int fd, void *arg)
 /* gnutls_transport is the singleton that describes the SSL transport
    methods provided by this file.  */
 
-static struct transport_implementation wgnutls_transport = {
+static struct transport_implementation wgnutls_transport =
+{
   wgnutls_read, wgnutls_write, wgnutls_poll,
   wgnutls_peek, wgnutls_errstr, wgnutls_close
 };