Ticket #737: 0001-Check-ncp-ciphers-list-on-startup.patch

File 0001-Check-ncp-ciphers-list-on-startup.patch, 6.2 KB (added by Steffan Karger, 4 years ago)
  • src/openvpn/crypto.c

    From f8978f6e151f4fd84d67f2d87f763c71ef170eac Mon Sep 17 00:00:00 2001
    From: Steffan Karger <steffan@karger.me>
    Date: Wed, 28 Sep 2016 11:20:47 +0200
    Subject: [PATCH] Check --ncp-ciphers list on startup
    
    Currently, if --ncp-ciphers contains an invalid cipher, OpenVPN will only
    error out when that cipher is selected by negotiation.  That's not very
    friendly to the user, so check the list on startup, and give a clear error
    message immediately.
    
    This patches changes the cipher_kt_get() to let the caller decide what
    action to take if no valid cipher was found.  This enables us to print all
    invalid ciphers in the list, instead of just the first invalid cipher.
    
    This should fix trac #737.
    
    Signed-off-by: Steffan Karger <steffan@karger.me>
    ---
     src/openvpn/crypto.c         |  5 +++++
     src/openvpn/crypto_backend.h |  3 ++-
     src/openvpn/crypto_mbedtls.c | 15 ++++++++++-----
     src/openvpn/crypto_openssl.c | 17 ++++++++++++-----
     src/openvpn/options.c        |  5 +++++
     src/openvpn/ssl.c            | 21 +++++++++++++++++++++
     src/openvpn/ssl.h            |  9 +++++++++
     7 files changed, 64 insertions(+), 11 deletions(-)
    
    diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
    index 6f57841..1b17f9d 100644
    a b init_key_type (struct key_type *kt, const char *ciphername, 
    763763  if (ciphername)
    764764    {
    765765      kt->cipher = cipher_kt_get (translate_cipher_name_from_openvpn(ciphername));
     766      if (!kt->cipher)
     767        {
     768          msg (M_FATAL, "Cipher %s not supported", ciphername);
     769        }
     770
    766771      kt->cipher_length = cipher_kt_key_size (kt->cipher);
    767772      if (keysize > 0 && keysize <= MAX_CIPHER_KEY_LENGTH)
    768773        kt->cipher_length = keysize;
  • src/openvpn/crypto_backend.h

    diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h
    index a699673..bf7d78c 100644
    a b void cipher_des_encrypt_ecb (const unsigned char key[DES_KEY_LENGTH], 
    195195 *                      \c AES-128-CBC).
    196196 *
    197197 * @return              A statically allocated structure containing parameters
    198  *                      for the given cipher.
     198 *                      for the given cipher, or NULL if no matching parameters
     199 *                      were found.
    199200 */
    200201const cipher_kt_t * cipher_kt_get (const char *ciphername);
    201202
  • src/openvpn/crypto_mbedtls.c

    diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c
    index 92cba49..6ad5924 100644
    a b cipher_kt_get (const char *ciphername) 
    384384  cipher = mbedtls_cipher_info_from_string(ciphername);
    385385
    386386  if (NULL == cipher)
    387     msg (M_FATAL, "Cipher algorithm '%s' not found", ciphername);
     387    {
     388      msg (D_LOW, "Cipher algorithm '%s' not found", ciphername);
     389      return NULL;
     390    }
    388391
    389392  if (cipher->key_bitlen/8 > MAX_CIPHER_KEY_LENGTH)
    390     msg (M_FATAL, "Cipher algorithm '%s' uses a default key size (%d bytes) which is larger than " PACKAGE_NAME "'s current maximum key size (%d bytes)",
    391          ciphername,
    392          cipher->key_bitlen/8,
    393          MAX_CIPHER_KEY_LENGTH);
     393    {
     394      msg (D_LOW, "Cipher algorithm '%s' uses a default key size (%d bytes) "
     395          "which is larger than " PACKAGE_NAME "'s current maximum key size "
     396          "(%d bytes)", ciphername, cipher->key_bitlen/8, MAX_CIPHER_KEY_LENGTH);
     397      return NULL;
     398    }
    394399
    395400  return cipher;
    396401}
  • src/openvpn/crypto_openssl.c

    diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c
    index 3484c77..1ea06bb 100644
    a b cipher_kt_get (const char *ciphername) 
    504504  cipher = EVP_get_cipherbyname (ciphername);
    505505
    506506  if (NULL == cipher)
    507     crypto_msg (M_FATAL, "Cipher algorithm '%s' not found", ciphername);
     507    {
     508      crypto_msg (D_LOW, "Cipher algorithm '%s' not found", ciphername);
     509      return NULL;
     510    }
     511
    508512
    509513  if (EVP_CIPHER_key_length (cipher) > MAX_CIPHER_KEY_LENGTH)
    510     msg (M_FATAL, "Cipher algorithm '%s' uses a default key size (%d bytes) which is larger than " PACKAGE_NAME "'s current maximum key size (%d bytes)",
    511          ciphername,
    512          EVP_CIPHER_key_length (cipher),
    513          MAX_CIPHER_KEY_LENGTH);
     514    {
     515      msg (D_LOW, "Cipher algorithm '%s' uses a default key size (%d bytes) "
     516          "which is larger than " PACKAGE_NAME "'s current maximum key size "
     517          "(%d bytes)", ciphername, EVP_CIPHER_key_length (cipher),
     518          MAX_CIPHER_KEY_LENGTH);
     519      return NULL;
     520    }
    514521
    515522  return cipher;
    516523}
  • src/openvpn/options.c

    diff --git a/src/openvpn/options.c b/src/openvpn/options.c
    index 98ae930..1358237 100644
    a b options_postprocess_verify_ce (const struct options *options, const struct conne 
    22082208
    22092209#ifdef ENABLE_CRYPTO
    22102210
     2211  if (options->ncp_enabled && !tls_check_ncp_cipher_list(options->ncp_ciphers))
     2212    {
     2213      msg (M_USAGE, "NCP cipher list contains unsupported ciphers.");
     2214    }
     2215
    22112216  /*
    22122217   * Check consistency of replay options
    22132218   */
  • src/openvpn/ssl.c

    diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
    index caf3b1f..a078ce2 100644
    a b tls_peer_info_ncp_ver(const char *peer_info) 
    37153715  return 0;
    37163716}
    37173717
     3718bool
     3719tls_check_ncp_cipher_list(const char *list) {
     3720  char *tmp_ciphers = string_alloc (list, NULL);
     3721  char *tmp_ciphers_orig = tmp_ciphers;
     3722  bool unsupported_cipher_found = false;
     3723
     3724  const char *token = strtok (tmp_ciphers, ":");
     3725  while (token)
     3726    {
     3727      if (!cipher_kt_get (translate_cipher_name_from_openvpn (token)))
     3728        {
     3729          msg (M_WARN, "Unsupported cipher in --ncp-ciphers: %s", token);
     3730          unsupported_cipher_found = true;
     3731        }
     3732      token = strtok (NULL, ":");
     3733    }
     3734  free (tmp_ciphers_orig);
     3735
     3736  return list && 0 < strlen(list) && !unsupported_cipher_found;
     3737}
     3738
    37183739/*
    37193740 * Dump a human-readable rendition of an openvpn packet
    37203741 * into a garbage collectable string which is returned.
  • src/openvpn/ssl.h

    diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h
    index de68b69..e6963a4 100644
    a b tls_get_peer_info(const struct tls_multi *multi) 
    503503 */
    504504int tls_peer_info_ncp_ver(const char *peer_info);
    505505
     506/**
     507 * Check whether the ciphers in the supplied list are supported.
     508 *
     509 * @param list          Colon-separated list of ciphers
     510 *
     511 * @returns true iff all ciphers in list are supported.
     512 */
     513bool tls_check_ncp_cipher_list(const char *list);
     514
    506515/*
    507516 * inline functions
    508517 */