Hi,
there was an small mistake in the error handling from the first patch.

This is working now correct :-)

cu thomas
/* SSL support.
   Copyright (C) 2000 Free Software Foundation, Inc.
   Contributed by Christian Fraenkel.

This file is part of GNU Wget.

GNU Wget 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 2 of the License, or
(at your option) any later version.

GNU Wget 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 Wget; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

In addition, as a special exception, the Free Software Foundation
gives permission to link the code of its release of Wget with the
OpenSSL project's "OpenSSL" library (or with modified versions of it
that use the same license as the "OpenSSL" library), and distribute
the linked executables.  You must obey the GNU General Public License
in all respects for all of the code used other than "OpenSSL".  If you
modify this file, you may extend this exception to your version of the
file, but you are not obligated to do so.  If you do not wish to do
so, delete this exception statement from your version.  */

#include <config.h>

#ifdef HAVE_SSL

#include <assert.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif

#include <gnutls.h>

#include "wget.h"
#include "utils.h"
#include "connect.h"
#include "url.h"

#ifndef errno
extern int errno;
#endif



void
ssl_init_prng (void)
{
    return;
}

/* pass all ssl errors to DEBUGP
   returns the number of printed errors 

TODO:
- save in static int last error
 */
int
ssl_printerrors (void) 
{
  return 0;
}

/* GNUTLS_CERTIFICATE_CLIENT_CREDENTIALS is already an pointer */
typedef void SSL_CTX;
typedef void SSL;


/* Creates a SSL Context and sets some defaults for it */
uerr_t
init_ssl (SSL_CTX **ctx)
{{{
  GNUTLS_CERTIFICATE_CREDENTIALS *xcred = (GNUTLS_CERTIFICATE_CREDENTIALS*)ctx;
  int x509ctype;
  if (!opt.sslcerttype)
    x509ctype = GNUTLS_X509_FMT_PEM;
  else
    x509ctype = GNUTLS_X509_FMT_DER;

  if (gnutls_global_init() < 0)
    {
       xcred = NULL;
       return -1;
    }
    if (gnutls_certificate_allocate_sc(xcred) < 0)
      {
       xcred = NULL;
       return -1;
      }

    if (opt.sslcafile)
      {
        if (0 > gnutls_certificate_set_x509_trust_file(*xcred, opt.sslcafile, 
x509ctype))
          {
            return -1;
          }
      }
    if (opt.sslcertkey != NULL && opt.sslcertkey != NULL)
      {
        if (0 > gnutls_certificate_set_x509_key_file(*xcred, opt.sslcertfile, 
opt.sslcertkey, x509ctype))
          {
            if (0 > gnutls_anon_allocate_client_sc(xcred))
              {
                return -1;
              }
          }
      }
 //  switch (opt.sslprotocol)
 //  if (!opt.sslcheckcert)
  return 0; /* Succeded */
}}}

void
shutdown_ssl (SSL* con)
{{{
  int ret;
  GNUTLS_STATE state = (GNUTLS_STATE)con;
  if (con == NULL)
    return;
  do
    ret = gnutls_bye(state, GNUTLS_SHUT_RDWR);
  while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
  gnutls_deinit(state);
}}}

static int cipher_priority[16] = { GNUTLS_CIPHER_RIJNDAEL_128_CBC,
       GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR,
       GNUTLS_CIPHER_TWOFISH_128_CBC, 0 };
int kx_priority[16] = { GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA,
       GNUTLS_KX_SRP, GNUTLS_KX_ANON_DH, 0 };
int comp_priority[16]      = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL  , 0 };
int protocol_priority[16]  = { GNUTLS_TLS1     , GNUTLS_SSL3       , 0 };
int mac_priority[16]       = { GNUTLS_MAC_SHA  , GNUTLS_MAC_MD5    , 0 };
/* GNUTLS_CRT_OPENPGP unused in wget currently */
int cert_type_priority[16] = { GNUTLS_CRT_X509 , GNUTLS_CRT_OPENPGP, 0 };


/* Sets up a SSL structure and performs the handshake on fd 
   Returns 0 if everything went right
   Returns 1 if something went wrong ----- TODO: More exit codes
*/
int
connect_ssl (SSL **con, SSL_CTX *ctx, int fd) 
{{{
  int ret;
  int alert;
  GNUTLS_CERTIFICATE_CREDENTIALS xcred = (GNUTLS_CERTIFICATE_CREDENTIALS)ctx;
  GNUTLS_CERTIFICATE_CREDENTIALS anon_cred;
  GNUTLS_STATE *state = (GNUTLS_STATE*)con;
  gnutls_init                       ( state, GNUTLS_CLIENT);
  gnutls_cipher_set_priority        (*state, cipher_priority);
  gnutls_compression_set_priority   (*state, comp_priority);
  gnutls_kx_set_priority            (*state, kx_priority);
  gnutls_kx_set_priority            (*state, kx_priority);
  gnutls_protocol_set_priority      (*state, protocol_priority);
  gnutls_mac_set_priority           (*state, mac_priority);
  gnutls_cert_type_set_priority     (*state, cert_type_priority);
  gnutls_dh_set_prime_bits          (*state, 1024);
  gnutls_cred_set                   (*state, GNUTLS_CRD_CERTIFICATE , xcred);

  gnutls_anon_allocate_client_sc    ( &anon_cred);
  gnutls_cred_set                   (*state, GNUTLS_CRD_ANON        , anon_cred);
//gnutls_openpgp_send_key           (*state, GNUTLS_OPENPGP_KEY_FINGERPRINT);
  gnutls_transport_set_ptr          (*state, fd);
  do
    ret = gnutls_handshake          (*state);
  while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
  if (ret < 0)
    {
      if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == 
GNUTLS_E_FATAL_ALERT_RECEIVED)
        {
          alert = gnutls_alert_get (*state);
//        printf("*** Received alert [%d]: %s\n", alert, gnutls_alert_get_name(alert));
        }
//      const char* gnutls_strerror( int error);
    gnutls_deinit (*state);
    *state = NULL;
    return -1;
    }
  return 0;
}}}

void
free_ssl_ctx (SSL_CTX * ctx)
{
}

/* SSL version of iread.  Only exchanged read for SSL_read Read at
   most LEN bytes from FD, storing them to BUF. */

int
ssl_iread (SSL *con, char *buf, int len)
{{{
  GNUTLS_STATE state = (GNUTLS_STATE)con;
  int fd = gnutls_transport_get_ptr (state);
  int ret;
  int alert;
  if (fd < 0)
    return 0;
  if (len == 0)
    return 0;
#ifdef HAVE_SELECT
  if (opt.timeout)
    if ( select_fd (fd, opt.timeout, 0) <= 0)
      return -1;
#endif
  while (1)
    {
      ret = gnutls_record_recv (state, buf, len);
      if (gnutls_error_is_fatal (ret) == 1)
        {
          DEBUGP (("fatal error"));
          return -1;
        }
      switch (ret)
        {
          case GNUTLS_E_AGAIN:
          case GNUTLS_E_INTERRUPTED:
                continue;
          case GNUTLS_E_WARNING_ALERT_RECEIVED:
          case GNUTLS_E_FATAL_ALERT_RECEIVED:
            alert = gnutls_alert_get (state);
            DEBUGP (("* Received alert [%d]: %s\n", alert, 
gnutls_alert_get_name(alert)));
            return -1;
          case GNUTLS_E_REHANDSHAKE:
            /* 
              There is a race condition here. If application data is sent
              after the rehandshake request, the server thinks we ignored
              his request. This is a bad design of this client.
            */
            do
              ret = gnutls_handshake (state);
            while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
            if (ret == 0)       /* re handshake ok */
              continue;
            DEBUGP (("re-handshake failed\n"));
            return -1;
          default:
            if (ret < 0)        /* Unhandeld error */
              {
                DEBUGP (("unhandled error in ssl read\n"));
                return -1;
              }
            return ret;
        }
    }
  return -1;
}}}

/* SSL version of iwrite.  Only exchanged write for SSL_write Write
   LEN bytes from BUF to FD.  */

int
ssl_iwrite (SSL *con, char *buf, int len)
{{{
  GNUTLS_STATE state = (GNUTLS_STATE)con;
  int fd = gnutls_transport_get_ptr (state);
  int ret;
  if (fd < 0)
    return 0;
  while (len > 0)
    {
#ifdef HAVE_SELECT
      if (opt.timeout)
        if (select_fd (fd, opt.timeout, 1) <= 0)
          return -1;
#endif
      do
        ret = gnutls_record_send(state, buf, len);
      while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
      if (ret <= 0);
      buf += ret;
      len -= ret;
      }
  return ret;
}}}
#endif /* HAVE_SSL */

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to