Skip to content

Bad certificate with UTFSTRING fields #3985

@ahmet2mir

Description

@ahmet2mir

Hello,

We have an internal PKI creating certificates for sensu mTLS, but by default certificate is defined as:

Country:             printablestring
State/County/Region: utf8string
Organization:        utf8string
CommonName:          utf8string
City/Locality:       utf8string
Organizational Unit: utf8string
emailAddress:        ia5string

And when starting sensu agent we got remote error: tls: bad certificate

If we force all fields to printablestring

Country:             printablestring
State/County/Region: printablestring
Organization:        printablestring
CommonName:          printablestring
City/Locality:       printablestring
Organizational Unit: printablestring
emailAddress:        ia5string

Sensu start normally.

Expected Behavior

Sensu must accept utf8string according to rfc5280

X520CommonName ::= CHOICE {
      teletexString     TeletexString   (SIZE (1..ub-common-name)),
      printableString   PrintableString (SIZE (1..ub-common-name)),
      universalString   UniversalString (SIZE (1..ub-common-name)),
      utf8String        UTF8String      (SIZE (1..ub-common-name)),
      bmpString         BMPString       (SIZE (1..ub-common-name)) }


X520LocalityName ::= CHOICE {
      teletexString     TeletexString   (SIZE (1..ub-locality-name)),
      printableString   PrintableString (SIZE (1..ub-locality-name)),
      universalString   UniversalString (SIZE (1..ub-locality-name)),
      utf8String        UTF8String      (SIZE (1..ub-locality-name)),
      bmpString         BMPString       (SIZE (1..ub-locality-name)) }

X520StateOrProvinceName ::= CHOICE {
      teletexString     TeletexString   (SIZE (1..ub-state-name)),
      printableString   PrintableString (SIZE (1..ub-state-name)),
      universalString   UniversalString (SIZE (1..ub-state-name)),
      utf8String        UTF8String      (SIZE (1..ub-state-name)),
      bmpString         BMPString       (SIZE (1..ub-state-name)) }

X520OrganizationName ::= CHOICE {
      teletexString     TeletexString
                          (SIZE (1..ub-organization-name)),
      printableString   PrintableString
                          (SIZE (1..ub-organization-name)),
      universalString   UniversalString
                          (SIZE (1..ub-organization-name)),
      utf8String        UTF8String
                          (SIZE (1..ub-organization-name)),
      bmpString         BMPString
                          (SIZE (1..ub-organization-name))  }


X520OrganizationalUnitName ::= CHOICE {
      teletexString     TeletexString
                          (SIZE (1..ub-organizational-unit-name)),
      printableString   PrintableString
                          (SIZE (1..ub-organizational-unit-name)),
      universalString   UniversalString
                          (SIZE (1..ub-organizational-unit-name)),
      utf8String        UTF8String
                          (SIZE (1..ub-organizational-unit-name)),
      bmpString         BMPString
                          (SIZE (1..ub-organizational-unit-name)) }

X520countryName ::=     PrintableString (SIZE (2))

Extensions are all in OCTET STRING.

Current Behavior

Sensu refuse to start

Possible Solution

Issue is probably on CommonName.

Steps to Reproduce (for bugs)

Example in ruby to set fields

require 'openssl'

def print_asn_strings(obj, depth = 0)
  if obj.respond_to? :each
    obj.each do |item|
      print_asn_strings(item, depth + 1)
    end
  else
    printf("%-40s %s\n", obj.value, obj.class) if (
      obj.class.to_s.match(/String/) &&
      obj.class != OpenSSL::ASN1::BitString
    )
  end
  nil
end

key = OpenSSL::PKey::RSA.new(4096)

subject = "/C=FR/ST=IDF/L=PARIS/O=Company/CN=myhost.example"

cert = OpenSSL::X509::Certificate.new

fields = []
OpenSSL::X509::Name.parse(subject).to_a.each do |field|
    fields << [field[0], field[1], OpenSSL::ASN1::UTF8STRING] # or OpenSSL::ASN1::PRINTABLESTRING
end

subject_x509 = OpenSSL::X509::Name.new(fields)

cert.subject = cert.issuer = subject_x509

cert.not_before = Time.now
cert.not_after = Time.now + 365*24*60*60
cert.public_key = key.public_key
cert.serial = 0x0
cert.version = 2

ef = OpenSSL::X509::ExtensionFactory.new
ef.subject_certificate = ef.issuer_certificate = cert

cert.add_extension ef.create_extension('basicConstraints', 'CA:FALSE', true)
cert.add_extension ef.create_extension('keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
cert.add_extension ef.create_extension('subjectKeyIdentifier', 'hash')
cert.add_extension ef.create_extension('authorityKeyIdentifier', 'keyid:always,issuer:always')

cert.sign key, OpenSSL::Digest::SHA256.new

asn1 = OpenSSL::ASN1.decode(cert.to_der)

print_asn_strings(asn1)

Context

Logs aren't very detailed, only "bad certificate" is shown.

Your Environment

  • sensuctl version 5.20.2+ee, enterprise edition, build c8d4472e852f36136536faf8b9fc4415d30a6137, built 2020-05-26T13:19:19Z, built with go1.13.7
  • sensu-backend version 5.20.2+ee, enterprise edition, build c8d4472e852f36136536faf8b9fc4415d30a6137, built 2020-05-26T13:14:34Z, built with go1.13.7
  • sensu-agent version 5.20.2+ee, enterprise edition, build c8d4472e852f36136536faf8b9fc4415d30a6137, built 2020-05-26T13:15:16Z, built with go1.13.7
  • CentOS Linux release 7.8.2003 (Core)
  • installation via RPM

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions