Ejemplo n.º 1
0
static int
amqp_ssl_socket_verify_hostname(void *base, const char *host)
{
  struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
  unsigned char *utf8_value = NULL, *cp, ch;
  int pos, utf8_length, status = 0;
  ASN1_STRING *entry_string;
  X509_NAME_ENTRY *entry;
  X509_NAME *name;
  X509 *peer;
  peer = SSL_get_peer_certificate(self->ssl);
  if (!peer) {
    goto error;
  }
  name = X509_get_subject_name(peer);
  if (!name) {
    goto error;
  }
  pos = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
  if (0 > pos) {
    goto error;
  }
  entry = X509_NAME_get_entry(name, pos);
  if (!entry) {
    goto error;
  }
  entry_string = X509_NAME_ENTRY_get_data(entry);
  if (!entry_string) {
    goto error;
  }
  utf8_length = ASN1_STRING_to_UTF8(&utf8_value, entry_string);
  if (0 > utf8_length) {
    goto error;
  }
  while (utf8_length > 0 && utf8_value[utf8_length - 1] == 0) {
    --utf8_length;
  }
  if (utf8_length >= 256) {
    goto error;
  }
  if ((size_t)utf8_length != strlen((char *)utf8_value)) {
    goto error;
  }
  for (cp = utf8_value; (ch = *cp) != '\0'; ++cp) {
    if (isascii(ch) && !isprint(ch)) {
      goto error;
    }
  }
  if (!amqp_hostcheck((char *)utf8_value, host)) {
    goto error;
  }
exit:
  OPENSSL_free(utf8_value);
  return status;
error:
  status = -1;
  goto exit;
}
Ejemplo n.º 2
0
static void hostcheck_fail(const char *match_pattern, const char *url) {
  int ok;

  ok = amqp_hostcheck(match_pattern, url);
  if (ok) {
    fprintf(stderr, "Expected hostname check to fail, but didn't: %s (%s)\n",
            url, match_pattern);
    abort();
  }

  fprintf(stdout, "ok: [fail] %s, %s\n", url, match_pattern);
}
/**
* Tries to find a match for hostname in the certificate's Subject Alternative
* Name extension.
*
* Returns AMQP_HVR_MATCH_FOUND if a match was found.
* Returns AMQP_HVR_MATCH_NOT_FOUND if no matches were found.
* Returns AMQP_HVR_MALFORMED_CERTIFICATE if any of the hostnames had a NUL
* character embedded in it.
* Returns AMQP_HVR_NO_SAN_PRESENT if the SAN extension was not present in the
* certificate.
*/
static amqp_hostname_validation_result amqp_matches_subject_alternative_name(
    const char *hostname, const X509 *server_cert) {
  amqp_hostname_validation_result result = AMQP_HVR_MATCH_NOT_FOUND;
  int i;
  int san_names_nb = -1;
  STACK_OF(GENERAL_NAME) *san_names = NULL;

  // Try to extract the names within the SAN extension from the certificate
  san_names =
      X509_get_ext_d2i((X509 *)server_cert, NID_subject_alt_name, NULL, NULL);
  if (san_names == NULL) {
    return AMQP_HVR_NO_SAN_PRESENT;
  }
  san_names_nb = sk_GENERAL_NAME_num(san_names);

  // Check each name within the extension
  for (i = 0; i < san_names_nb; i++) {
    const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i);

    if (current_name->type == GEN_DNS) {
      // Current name is a DNS name, let's check it
      char *dns_name = (char *)ASN1_STRING_data(current_name->d.dNSName);

      // Make sure there isn't an embedded NUL character in the DNS name
      if ((size_t)ASN1_STRING_length(current_name->d.dNSName) !=
          strlen(dns_name)) {
        result = AMQP_HVR_MALFORMED_CERTIFICATE;
        break;
      } else {  // Compare expected hostname with the DNS name
        if (amqp_hostcheck(dns_name, hostname) == AMQP_HCR_MATCH) {
          result = AMQP_HVR_MATCH_FOUND;
          break;
        }
      }
    }
  }
  sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);

  return result;
}
/**
* Tries to find a match for hostname in the certificate's Common Name field.
*
* Returns AMQP_HVR_MATCH_FOUND if a match was found.
* Returns AMQP_HVR_MATCH_NOT_FOUND if no matches were found.
* Returns AMQP_HVR_MALFORMED_CERTIFICATE if the Common Name had a NUL character embedded in it.
* Returns AMQP_HVR_ERROR if the Common Name could not be extracted.
*/
static amqp_hostname_validation_result amqp_matches_common_name(
    const char *hostname, const X509 *server_cert) {
  int common_name_loc = -1;
  X509_NAME_ENTRY *common_name_entry = NULL;
  ASN1_STRING *common_name_asn1 = NULL;
  char *common_name_str = NULL;

  // Find the position of the CN field in the Subject field of the certificate
  common_name_loc = X509_NAME_get_index_by_NID(
      X509_get_subject_name((X509 *)server_cert), NID_commonName, -1);
  if (common_name_loc < 0) {
    return AMQP_HVR_ERROR;
  }

  // Extract the CN field
  common_name_entry = X509_NAME_get_entry(
      X509_get_subject_name((X509 *)server_cert), common_name_loc);
  if (common_name_entry == NULL) {
    return AMQP_HVR_ERROR;
  }

  // Convert the CN field to a C string
  common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
  if (common_name_asn1 == NULL) {
    return AMQP_HVR_ERROR;
  }
  common_name_str = (char *)ASN1_STRING_data(common_name_asn1);

  // Make sure there isn't an embedded NUL character in the CN
  if ((size_t)ASN1_STRING_length(common_name_asn1) != strlen(common_name_str)) {
    return AMQP_HVR_MALFORMED_CERTIFICATE;
  }

  // Compare expected hostname with the CN
  if (amqp_hostcheck(common_name_str, hostname) == AMQP_HCR_MATCH) {
    return AMQP_HVR_MATCH_FOUND;
  } else {
    return AMQP_HVR_MATCH_NOT_FOUND;
  }
}