Example #1
0
static int
setenv(const char * name, const char * val, int overwrite)
{
uschar * s;
if (Ustrchr(name, '=')) return -1;
if (overwrite || !getenv(name))
  putenv(CS string_copy_malloc(string_sprintf("%s=%s", name, val)));
return 0;
}
Example #2
0
File: tls-gnu.c Project: fanf2/exim
static BOOL
verify_certificate(gnutls_session session, const char **error)
{
int verify;
uschar *dn_string = US"";
const gnutls_datum *cert;
unsigned int cert_size = 0;

*error = NULL;

/* Get the peer's certificate. If it sent one, extract it's DN, and then
attempt to verify the certificate. If no certificate is supplied, verification
is forced to fail. */

cert = gnutls_certificate_get_peers(session, &cert_size);
if (cert != NULL)
  {
  uschar buff[1024];
  gnutls_x509_crt gcert;

  gnutls_x509_crt_init(&gcert);
  dn_string = US"unknown";

  if (gnutls_x509_crt_import(gcert, cert, GNUTLS_X509_FMT_DER) == 0)
    {
    size_t bufsize = sizeof(buff);
    if (gnutls_x509_crt_get_dn(gcert, CS buff, &bufsize) >= 0)
      dn_string = string_copy_malloc(buff);
    }

  verify = gnutls_certificate_verify_peers(session);
  }
else
  {
  DEBUG(D_tls) debug_printf("no peer certificate supplied\n");
  verify = GNUTLS_CERT_INVALID;
  *error = "not supplied";
  }

/* Handle the result of verification. INVALID seems to be set as well
as REVOKED, but leave the test for both. */

if ((verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED)) != 0)
  {
  tls_certificate_verified = FALSE;
  if (*error == NULL) *error = ((verify & GNUTLS_CERT_REVOKED) != 0)?
    "revoked" : "invalid";
  if (verify_requirement == VERIFY_REQUIRED)
    {
    DEBUG(D_tls) debug_printf("TLS certificate verification failed (%s): "
      "peerdn=%s\n", *error, dn_string);
    gnutls_alert_send(session, GNUTLS_AL_FATAL, GNUTLS_A_BAD_CERTIFICATE);
    return FALSE;                       /* reject */
    }
  DEBUG(D_tls) debug_printf("TLS certificate verify failure (%s) overridden "
      "(host in tls_try_verify_hosts): peerdn=%s\n", *error, dn_string);
  }
else
  {
  tls_certificate_verified = TRUE;
  DEBUG(D_tls) debug_printf("TLS certificate verified: peerdn=%s\n",
    dn_string);
  }

tls_peerdn = dn_string;
return TRUE;                            /* accept */
}
Example #3
0
File: tls-gnu.c Project: fanf2/exim
int
tls_client_start(int fd, host_item *host, address_item *addr, uschar *dhparam,
  uschar *certificate, uschar *privatekey, uschar *verify_certs,
  uschar *verify_crl, uschar *require_ciphers, uschar *require_mac,
  uschar *require_kx, uschar *require_proto, int timeout)
{
const gnutls_datum *server_certs;
uschar *expciphers = NULL;
uschar *expmac = NULL;
uschar *expkx = NULL;
uschar *expproto = NULL;
const char *error;
unsigned int server_certs_size;
int rc;

DEBUG(D_tls) debug_printf("initializing GnuTLS as a client\n");

verify_requirement = (verify_certs == NULL)? VERIFY_NONE : VERIFY_REQUIRED;
rc = tls_init(host, certificate, privatekey, verify_certs, verify_crl);
if (rc != OK) return rc;

if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers) ||
    !expand_check(require_mac, US"gnutls_require_mac", &expmac) ||
    !expand_check(require_kx, US"gnutls_require_kx", &expkx) ||
    !expand_check(require_proto, US"gnutls_require_proto", &expproto))
  return FAIL;

tls_session = tls_session_init(GNUTLS_CLIENT, expciphers, expmac, expkx,
  expproto);

if (tls_session == NULL)
  return tls_error(US "tls_session_init", host,
    gnutls_strerror(GNUTLS_E_MEMORY_ERROR));

gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr)fd);

/* There doesn't seem to be a built-in timeout on connection. */

sigalrm_seen = FALSE;
alarm(timeout);
rc = gnutls_handshake(tls_session);
alarm(0);

if (rc < 0)
  return tls_error(US "gnutls_handshake", host,
    sigalrm_seen ? "timed out" : gnutls_strerror(rc));

server_certs = gnutls_certificate_get_peers(tls_session, &server_certs_size);

if (server_certs != NULL)
  {
  uschar buff[1024];
  gnutls_x509_crt gcert;

  gnutls_x509_crt_init(&gcert);
  tls_peerdn = US"unknown";

  if (gnutls_x509_crt_import(gcert, server_certs, GNUTLS_X509_FMT_DER) == 0)
    {
    size_t bufsize = sizeof(buff);
    if (gnutls_x509_crt_get_dn(gcert, CS buff, &bufsize) >= 0)
      tls_peerdn = string_copy_malloc(buff);
    }
  }

/* Should we also verify the hostname here? */

if (verify_requirement != VERIFY_NONE &&
      !verify_certificate(tls_session, &error))
  return tls_error(US"certificate verification failed", host, error);

construct_cipher_name(tls_session);    /* Sets tls_cipher */
tls_active = fd;
return OK;
}