<commit_before>/*
 * This file is part of the Sofia-SIP package
 *
 * Copyright (C) 2005 Nokia Corporation.
 *
 * Contact: <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

/**@CFILE tport_tls.c
 * @brief TLS interface
 * 
 * @author <NAME> <<EMAIL>>
 * @author <NAME> <<EMAIL>>
 *
 * Copyright 2001, 2002 Nokia Research Center.  All rights reserved.
 *
 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

#define OPENSSL_NO_KRB5 oh-no

#include <openssl/lhash.h>
#include <openssl/bn.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#include <openssl/opensslv.h>

#include <poll.h>

#include "tport_tls.h"

char const tls_version[] = OPENSSL_VERSION_TEXT;

enum  { tls_master, tls_slave };

struct tls_s {
  SSL_CTX *ctx;
  SSL *con;
  BIO *bio_con;
  BIO *bio_err;
  int type;
  int verified;

  /* Receiving */
  int read_events;
  void *read_buffer;
  int read_buffer_len;

  /* Sending */
  int   write_events;
  void *write_buffer;
  int   write_buffer_len;

  /* Host names */
  char *hosts[TLS_MAX_HOSTS + 1];
};

enum { tls_buffer_size = 16384 };

static
tls_t *tls_create(int type)
{
  tls_t *tls = calloc(1, sizeof(*tls));

  if (tls)
    tls->type = type;

  return tls;
}

static
void tls_set_default(tls_issues_t *i)
{
  i->verify_depth = i->verify_depth == 0 ? 2 : i->verify_depth;
  i->cert = i->cert ? i->cert : "agent.pem";
  i->key = i->key ? i->key : i->cert;
  i->randFile = i->randFile ? i->randFile : "tls_seed.dat";
  i->CAfile = i->CAfile ? i->CAfile : "cafile.pem";
  i->cipher = i->cipher ? i->cipher : "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
    //"RSA-WITH-AES-128-CBC-SHA";
}

static
int tls_verify_cb(int ok, X509_STORE_CTX *store)
{
  char data[256];

  X509 *cert = X509_STORE_CTX_get_current_cert(store);
  int  depth = X509_STORE_CTX_get_error_depth(store);
  int  err = X509_STORE_CTX_get_error(store);
 
  //X509_NAME_oneline(X509_get_subject_name(cert), data, 256);
  //fprintf(stderr,"depth=%d %s\n",depth,data);

  if (!ok)
  {
    fprintf(stderr, "-Error with certificate at depth: %i\n", depth);
    X509_NAME_oneline(X509_get_issuer_name(cert), data, 256);
    fprintf(stderr, "  issuer   = %s\n", data);
    X509_NAME_oneline(X509_get_subject_name(cert), data, 256);
    fprintf(stderr, "  subject  = %s\n", data);
    fprintf(stderr, "  err %i:%s\n", err, X509_verify_cert_error_string(err));
  }
 
  return ok;
}

static
int tls_init_context(tls_t *tls, tls_issues_t const *ti)
{
  static int initialized = 0;

  if (!initialized) {
    initialized = 1;
    SSL_library_init();
    SSL_load_error_strings();

    if (ti->randFile &&
	!RAND_load_file(ti->randFile, 1024 * 1024)) {
      if (ti->configured > 1) {
	BIO_printf(tls->bio_err, "%s: cannot open randFile %s\n", 
		   "tls_init_context", ti->randFile);
	ERR_print_errors(tls->bio_err);
      }
      /* errno = EIO; */
      /* return -1; */
    }
  }

  /* Avoid possible SIGPIPE when sending close_notify */
  signal(SIGPIPE, SIG_IGN);

  if (tls->bio_err == NULL)
    tls->bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);

  if (tls->ctx == NULL) {
    SSL_METHOD *meth;
    // meth = SSLv3_method();
    // meth = SSLv23_method();

    if (ti->version)
      meth = TLSv1_method();
    else
      meth = SSLv23_method();

    tls->ctx = SSL_CTX_new(meth);
  }

  if (tls->ctx == NULL) {
    ERR_print_errors(tls->bio_err);
    errno = EIO;
    return -1;
  }

  if (!SSL_CTX_use_certificate_file(tls->ctx, 
				    ti->cert,
				    SSL_FILETYPE_PEM)) {
    if (ti->configured > 0) {
      BIO_printf(tls->bio_err, "%s: invalid certificate: %s\n",
		 "tls_init_context", ti->cert);
      ERR_print_errors(tls->bio_err);
    }
    errno = EIO;
    return -1;
  }

  if (!SSL_CTX_use_PrivateKey_file(tls->ctx, 
                                   ti->key, 
                                   SSL_FILETYPE_PEM)) {
    ERR_print_errors(tls->bio_err);
    errno = EIO;
    return -1;
  }

  if (!SSL_CTX_check_private_key(tls->ctx)) {
    BIO_printf(tls->bio_err,
               "Private key does not match the certificate public key\n");
    errno = EIO;
    return -1;
  }

  if (!SSL_CTX_load_verify_locations(tls->ctx, 
                                     ti->CAfile, 
                                     ti->CApath)) {
    ERR_print_errors(tls->bio_err);
    errno = EIO;
    return -1;
  }

  SSL_CTX_set_verify_depth(tls->ctx, ti->verify_depth);

  SSL_CTX_set_verify(tls->ctx, 
                     SSL_VERIFY_PEER  /* | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */,
                     tls_verify_cb);

  if (!SSL_CTX_set_cipher_list(tls->ctx, ti->cipher)) {
    BIO_printf(tls->bio_err,"error setting cipher list\n");
    ERR_print_errors(tls->bio_err);
    errno = EIO;
    return -1;
  }<commit_msg>Using SSL_VERIFY_NONE - do not ask for client certificate.<commit_after>/*
 * This file is part of the Sofia-SIP package
 *
 * Copyright (C) 2005 Nokia Corporation.
 *
 * Contact: <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

/**@CFILE tport_tls.c
 * @brief TLS interface
 * 
 * @author <NAME> <<EMAIL>>
 * @author <NAME> <<EMAIL>>
 *
 * Copyright 2001, 2002 Nokia Research Center.  All rights reserved.
 *
 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

#define OPENSSL_NO_KRB5 oh-no

#include <openssl/lhash.h>
#include <openssl/bn.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#include <openssl/opensslv.h>

#include <poll.h>

#include "tport_tls.h"

char const tls_version[] = OPENSSL_VERSION_TEXT;

enum  { tls_master, tls_slave };

struct tls_s {
  SSL_CTX *ctx;
  SSL *con;
  BIO *bio_con;
  BIO *bio_err;
  int type;
  int verified;

  /* Receiving */
  int read_events;
  void *read_buffer;
  int read_buffer_len;

  /* Sending */
  int   write_events;
  void *write_buffer;
  int   write_buffer_len;

  /* Host names */
  char *hosts[TLS_MAX_HOSTS + 1];
};

enum { tls_buffer_size = 16384 };

static
tls_t *tls_create(int type)
{
  tls_t *tls = calloc(1, sizeof(*tls));

  if (tls)
    tls->type = type;

  return tls;
}

static
void tls_set_default(tls_issues_t *i)
{
  i->verify_depth = i->verify_depth == 0 ? 2 : i->verify_depth;
  i->cert = i->cert ? i->cert : "agent.pem";
  i->key = i->key ? i->key : i->cert;
  i->randFile = i->randFile ? i->randFile : "tls_seed.dat";
  i->CAfile = i->CAfile ? i->CAfile : "cafile.pem";
  i->cipher = i->cipher ? i->cipher : "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
    //"RSA-WITH-AES-128-CBC-SHA";
}

static
int tls_verify_cb(int ok, X509_STORE_CTX *store)
{
  char data[256];

  X509 *cert = X509_STORE_CTX_get_current_cert(store);
  int  depth = X509_STORE_CTX_get_error_depth(store);
  int  err = X509_STORE_CTX_get_error(store);
 
  //X509_NAME_oneline(X509_get_subject_name(cert), data, 256);
  //fprintf(stderr,"depth=%d %s\n",depth,data);

  if (!ok)
  {
    fprintf(stderr, "-Error with certificate at depth: %i\n", depth);
    X509_NAME_oneline(X509_get_issuer_name(cert), data, 256);
    fprintf(stderr, "  issuer   = %s\n", data);
    X509_NAME_oneline(X509_get_subject_name(cert), data, 256);
    fprintf(stderr, "  subject  = %s\n", data);
    fprintf(stderr, "  err %i:%s\n", err, X509_verify_cert_error_string(err));
  }
 
  return ok;
}

static
int tls_init_context(tls_t *tls, tls_issues_t const *ti)
{
  static int initialized = 0;

  if (!initialized) {
    initialized = 1;
    SSL_library_init();
    SSL_load_error_strings();

    if (ti->randFile &&
	!RAND_load_file(ti->randFile, 1024 * 1024)) {
      if (ti->configured > 1) {
	BIO_printf(tls->bio_err, "%s: cannot open randFile %s\n", 
		   "tls_init_context", ti->randFile);
	ERR_print_errors(tls->bio_err);
      }
      /* errno = EIO; */
      /* return -1; */
    }
  }

  /* Avoid possible SIGPIPE when sending close_notify */
  signal(SIGPIPE, SIG_IGN);

  if (tls->bio_err == NULL)
    tls->bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);

  if (tls->ctx == NULL) {
    SSL_METHOD *meth;
    // meth = SSLv3_method();
    // meth = SSLv23_method();

    if (ti->version)
      meth = TLSv1_method();
    else
      meth = SSLv23_method();

    tls->ctx = SSL_CTX_new(meth);
  }

  if (tls->ctx == NULL) {
    ERR_print_errors(tls->bio_err);
    errno = EIO;
    return -1;
  }

  if (!SSL_CTX_use_certificate_file(tls->ctx, 
				    ti->cert,
				    SSL_FILETYPE_PEM)) {
    if (ti->configured > 0) {
      BIO_printf(tls->bio_err, "%s: invalid certificate: %s\n",
		 "tls_init_context", ti->cert);
      ERR_print_errors(tls->bio_err);
    }
    errno = EIO;
    return -1;
  }

  if (!SSL_CTX_use_PrivateKey_file(tls->ctx, 
                                   ti->key, 
                                   SSL_FILETYPE_PEM)) {
    ERR_print_errors(tls->bio_err);
    errno = EIO;
    return -1;
  }

  if (!SSL_CTX_check_private_key(tls->ctx)) {
    BIO_printf(tls->bio_err,
               "Private key does not match the certificate public key\n");
    errno = EIO;
    return -1;
  }

  if (!SSL_CTX_load_verify_locations(tls->ctx, 
                                     ti->CAfile, 
                                     ti->CApath)) {
    ERR_print_errors(tls->bio_err);
    errno = EIO;
    return -1;
  }

  SSL_CTX_set_verify_depth(tls->ctx, ti->verify_depth);

  SSL_CTX_set_verify(tls->ctx, 
                     SSL_VERIFY_NONE 
		     /* SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */,
                     tls_verify_cb);

  if (!SSL_CTX_set_cipher_list(tls->ctx, ti->cipher)) {
    BIO_printf(tls->bio_err,"error setting cipher list\n");
    ERR_print_errors(tls->bio_err);
    errno = EIO;
    return -1;
  }
{'fraction_non_alphanumeric': 0.13859649122807016, 'fraction_numerical': 0.02087719298245614, 'mean_word_length': 2.990549527476374, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 173, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7129200', 'n_tokens_mistral': 4524, 'n_tokens_neox': 4160, 'n_words': 980}