├── .gitignore ├── .rubocop.yml ├── lib ├── certlint.rb └── certlint │ ├── extensions │ ├── freshestcrl.rb │ ├── qcstatements.rb │ ├── inhibitanypolicy.rb │ ├── logotypeextn.rb │ ├── policyconstraints.rb │ ├── subjectkeyidentifier.rb │ ├── privatekeyusageperiod.rb │ ├── issueraltname.rb │ ├── policymappings.rb │ ├── smimecapabilities.rb │ ├── subjectdirectoryattributes.rb │ ├── subjectinfoaccesssyntax.rb │ ├── authorityinfoaccesssyntax.rb │ ├── crldistributionpoints.rb │ ├── signedcertificatetimestamplist.rb │ ├── ctpoison.rb │ ├── ocspnocheck.rb │ ├── asn1ext.rb │ ├── extkeyusagesyntax.rb │ ├── authoritykeyidentifier.rb │ ├── basicconstraints.rb │ ├── subjectaltname.rb │ ├── nameconstraints.rb │ ├── certificatepolicies.rb │ └── keyusage.rb │ ├── certextlint.rb │ ├── pemlint.rb │ ├── iananames.rb │ ├── ct.rb │ ├── generalnames.rb │ ├── namelint.rb │ ├── cablint.rb │ ├── certlint.rb │ └── dn_attrs.rb ├── update-data.sh ├── bin ├── certlint ├── cablint └── cablint-ct ├── make-names.rb ├── data ├── special-use-domain.csv └── ldap-names.csv ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | build-x509helper/asn1c 2 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | Metrics/LineLength: 2 | Enabled: false 3 | -------------------------------------------------------------------------------- /lib/certlint.rb: -------------------------------------------------------------------------------- 1 | require 'certlint/certlint' 2 | require 'certlint/cablint' 3 | require 'certlint/pemlint' 4 | require 'certlint/namelint' 5 | require 'certlint/generalnames' 6 | -------------------------------------------------------------------------------- /update-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -o data/newgtlds.csv https://newgtlds.icann.org/newgtlds.csv 3 | curl -o data/root.zone http://www.internic.net/domain/root.zone 4 | curl -o data/special-use-domain.csv http://www.iana.org/assignments/special-use-domain-names/special-use-domain.csv 5 | curl -o data/public_suffix_list.dat https://publicsuffix.org/list/public_suffix_list.dat 6 | curl -o data/ldap-names.csv http://www.iana.org/assignments/ldap-parameters/ldap-parameters-3.csv 7 | -------------------------------------------------------------------------------- /bin/certlint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require 'certlint' 16 | 17 | fn = File.basename(ARGV[0]) 18 | raw = File.read(ARGV[0]) 19 | if raw.include? '-BEGIN CERTIFICATE-' 20 | puts 'PEM!!!' 21 | exit 1 22 | end 23 | der = raw 24 | 25 | m = CertLint.lint(der) 26 | m.each do |msg| 27 | puts "#{msg}\t#{fn}" 28 | end 29 | -------------------------------------------------------------------------------- /lib/certlint/extensions/freshestcrl.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class FreshestCRL < ASN1Ext 20 | @pdu = :CRLDistributionPoints 21 | @critical_req = false 22 | end 23 | end 24 | end 25 | 26 | CertLint::CertExtLint.register_handler('2.5.29.46', CertLint::ASN1Ext::FreshestCRL) 27 | -------------------------------------------------------------------------------- /lib/certlint/extensions/qcstatements.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class QCStatements < ASN1Ext 20 | @pdu = :QCStatements 21 | @critical_req = :optional 22 | end 23 | end 24 | end 25 | 26 | CertLint::CertExtLint.register_handler('1.3.6.1.5.5.7.1.3', CertLint::ASN1Ext::QCStatements) 27 | -------------------------------------------------------------------------------- /lib/certlint/extensions/inhibitanypolicy.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class InhibitAnyPolicy < ASN1Ext 20 | @pdu = :InhibitAnyPolicy 21 | @critical_req = true 22 | end 23 | end 24 | end 25 | 26 | CertLint::CertExtLint.register_handler('2.5.29.54', CertLint::ASN1Ext::InhibitAnyPolicy) 27 | -------------------------------------------------------------------------------- /lib/certlint/extensions/logotypeextn.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class LogotypeExtn < ASN1Ext 20 | @pdu = :LogotypeExtn 21 | @critical_req = :optional 22 | end 23 | end 24 | end 25 | 26 | CertLint::CertExtLint.register_handler('1.3.6.1.5.5.7.1.12', CertLint::ASN1Ext::LogotypeExtn) 27 | -------------------------------------------------------------------------------- /lib/certlint/extensions/policyconstraints.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class PolicyConstraints < ASN1Ext 20 | @pdu = :PolicyConstraints 21 | @critical_req = true 22 | end 23 | end 24 | end 25 | 26 | CertLint::CertExtLint.register_handler('2.5.29.36', CertLint::ASN1Ext::PolicyConstraints) 27 | -------------------------------------------------------------------------------- /lib/certlint/extensions/subjectkeyidentifier.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class SubjectKeyIdentifier < ASN1Ext 20 | @pdu = :SubjectKeyIdentifier 21 | @critical_req = false 22 | end 23 | end 24 | end 25 | 26 | CertLint::CertExtLint.register_handler('2.5.29.14', CertLint::ASN1Ext::SubjectKeyIdentifier) 27 | -------------------------------------------------------------------------------- /lib/certlint/extensions/privatekeyusageperiod.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class PrivateKeyUsagePeriod < ASN1Ext 20 | @pdu = :PrivateKeyUsagePeriod 21 | @critical_req = :false 22 | end 23 | end 24 | end 25 | 26 | CertLint::CertExtLint.register_handler('2.5.29.16', CertLint::ASN1Ext::PrivateKeyUsagePeriod) 27 | -------------------------------------------------------------------------------- /lib/certlint/extensions/issueraltname.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class IssuerAltName < ASN1Ext 20 | @pdu = :IssuerAltName 21 | @critical_req = :optional 22 | @critical_should = false 23 | end 24 | end 25 | end 26 | 27 | CertLint::CertExtLint.register_handler('2.5.29.18', CertLint::ASN1Ext::IssuerAltName) 28 | -------------------------------------------------------------------------------- /lib/certlint/extensions/policymappings.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class PolicyMappings < ASN1Ext 20 | @pdu = :PolicyMappings 21 | @critical_req = :optional 22 | @critical_should = true 23 | end 24 | end 25 | end 26 | 27 | CertLint::CertExtLint.register_handler('2.5.29.33', CertLint::ASN1Ext::PolicyMappings) 28 | -------------------------------------------------------------------------------- /lib/certlint/extensions/smimecapabilities.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class SmimeCapabilities < ASN1Ext 20 | # RFC 4262 21 | @pdu = :SMIMECapabilities 22 | @critical_req = false 23 | end 24 | end 25 | end 26 | 27 | CertLint::CertExtLint.register_handler('1.2.840.113549.1.9.15', CertLint::ASN1Ext::SmimeCapabilities) 28 | -------------------------------------------------------------------------------- /lib/certlint/extensions/subjectdirectoryattributes.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class SubjectDirectoryAttributes < ASN1Ext 20 | @pdu = :SubjectDirectoryAttributes 21 | @critical_req = false 22 | end 23 | end 24 | end 25 | 26 | CertLint::CertExtLint.register_handler('2.5.29.9', CertLint::ASN1Ext::SubjectDirectoryAttributes) 27 | -------------------------------------------------------------------------------- /lib/certlint/extensions/subjectinfoaccesssyntax.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class SubjectInfoAccessSyntax < ASN1Ext 20 | @pdu = :SubjectInfoAccessSyntax 21 | @critical_req = false 22 | end 23 | end 24 | end 25 | 26 | CertLint::CertExtLint.register_handler('1.3.6.1.5.5.7.1.11', CertLint::ASN1Ext::SubjectInfoAccessSyntax) 27 | -------------------------------------------------------------------------------- /lib/certlint/extensions/authorityinfoaccesssyntax.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class AuthorityInfoAccessSyntax < ASN1Ext 20 | @pdu = :AuthorityInfoAccessSyntax 21 | @critical_req = false 22 | end 23 | end 24 | end 25 | 26 | CertLint::CertExtLint.register_handler('1.3.6.1.5.5.7.1.1', CertLint::ASN1Ext::AuthorityInfoAccessSyntax) 27 | -------------------------------------------------------------------------------- /lib/certlint/extensions/crldistributionpoints.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class CRLDistributionPoints < ASN1Ext 20 | @pdu = :CRLDistributionPoints 21 | @critical_req = :optional 22 | @critical_should = false 23 | end 24 | end 25 | end 26 | 27 | CertLint::CertExtLint.register_handler('2.5.29.31', CertLint::ASN1Ext::CRLDistributionPoints) 28 | -------------------------------------------------------------------------------- /bin/cablint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require 'certlint' 16 | 17 | ARGV.each do |file| 18 | fn = File.basename(file) 19 | raw = File.read(file) 20 | 21 | if raw.include? '-BEGIN CERTIFICATE-' 22 | m, der = CertLint::PEMLint.lint(raw, 'CERTIFICATE') 23 | else 24 | m = [] 25 | der = raw 26 | end 27 | 28 | m += CertLint::CABLint.lint(der) 29 | m.each do |msg| 30 | puts "#{msg}\t#{fn}" 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /make-names.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | # Prefill with the CA/B Forum attributes 4 | attrs = { 5 | '1.3.6.1.4.1.311.60.2.1.1' => 'jurisdictionLocalityName', 6 | '1.3.6.1.4.1.311.60.2.1.2' => 'jurisdictionStateOrProvinceName', 7 | '1.3.6.1.4.1.311.60.2.1.3' => 'jurisdictionCountryName' 8 | } 9 | 10 | IO.foreach(ARGV[0]) do |line| 11 | p = line.strip.split(',') 12 | next unless p[1] == 'A' && p[2] =~ /^[0-2]/ 13 | oid = p[2].strip.split('.').map(&:strip).join('.') 14 | name = p[0] 15 | if !attrs.key? oid 16 | attrs[oid] = name 17 | elsif attrs[oid].length < name.length 18 | attrs[oid] = name 19 | end 20 | end 21 | 22 | def sort_oid(ao, bo) 23 | a = ao.split('.').map(&:to_i) 24 | b = bo.split('.').map(&:to_i) 25 | p = 0 26 | a.each do |seg| 27 | return 1 if b[p].nil? 28 | return 1 if seg > b[p] 29 | return -1 if seg < b[p] 30 | p += 1 31 | end 32 | if !b[p].nil? 33 | return -1 34 | end 35 | 0 36 | end 37 | 38 | 39 | attrs.keys.sort{|a,b|sort_oid(a,b)}.each do |oid| 40 | puts "'#{oid}' => '#{attrs[oid]}'," 41 | end 42 | -------------------------------------------------------------------------------- /data/special-use-domain.csv: -------------------------------------------------------------------------------- 1 | Name,Reference 2 | 10.in-addr.arpa.,[RFC6761] 3 | 16.172.in-addr.arpa.,[RFC6761] 4 | 17.172.in-addr.arpa.,[RFC6761] 5 | 18.172.in-addr.arpa.,[RFC6761] 6 | 19.172.in-addr.arpa.,[RFC6761] 7 | 20.172.in-addr.arpa.,[RFC6761] 8 | 21.172.in-addr.arpa.,[RFC6761] 9 | 22.172.in-addr.arpa.,[RFC6761] 10 | 23.172.in-addr.arpa.,[RFC6761] 11 | 24.172.in-addr.arpa.,[RFC6761] 12 | 25.172.in-addr.arpa.,[RFC6761] 13 | 26.172.in-addr.arpa.,[RFC6761] 14 | 27.172.in-addr.arpa.,[RFC6761] 15 | 28.172.in-addr.arpa.,[RFC6761] 16 | 29.172.in-addr.arpa.,[RFC6761] 17 | 30.172.in-addr.arpa.,[RFC6761] 18 | 31.172.in-addr.arpa.,[RFC6761] 19 | 168.192.in-addr.arpa.,[RFC6761] 20 | 254.169.in-addr.arpa.,[RFC6762] 21 | 8.e.f.ip6.arpa.,[RFC6762] 22 | 9.e.f.ip6.arpa.,[RFC6762] 23 | a.e.f.ip6.arpa.,[RFC6762] 24 | b.e.f.ip6.arpa.,[RFC6762] 25 | example.,[RFC6761] 26 | example.com.,[RFC6761] 27 | example.net.,[RFC6761] 28 | example.org.,[RFC6761] 29 | invalid.,[RFC6761] 30 | local.,[RFC6762] 31 | localhost.,[RFC6761] 32 | onion.,[RFC7686] 33 | test.,[RFC6761] 34 | -------------------------------------------------------------------------------- /lib/certlint/extensions/signedcertificatetimestamplist.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class SignedCertificateTimestampList < ASN1Ext 20 | def self.lint(content, cert, critical = false) 21 | messages = [] 22 | if critical 23 | messages << 'E: SignedCertificateTimestampList must not be critical' 24 | end 25 | messages 26 | end 27 | end 28 | end 29 | end 30 | 31 | CertLint::CertExtLint.register_handler('1.3.6.1.4.1.11129.2.4.2', CertLint::ASN1Ext::SignedCertificateTimestampList) 32 | -------------------------------------------------------------------------------- /lib/certlint/extensions/ctpoison.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class CTPoison < ASN1Ext 20 | def self.lint(content, cert, critical = false) 21 | messages = [] 22 | messages << 'I: Certificate Transparency Precertificate identified' 23 | unless critical 24 | messages << 'E: CT Poison must be critical' 25 | end 26 | unless content.bytes == [5, 0] 27 | messages << 'E: CT Poison must contain a single null' 28 | end 29 | messages 30 | end 31 | end 32 | end 33 | end 34 | 35 | CertLint::CertExtLint.register_handler('1.3.6.1.4.1.11129.2.4.3', CertLint::ASN1Ext::CTPoison) 36 | -------------------------------------------------------------------------------- /lib/certlint/extensions/ocspnocheck.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class OcspNocheck < ASN1Ext 20 | @pdu = nil 21 | @critical_req = :optional 22 | @critical_should = false 23 | 24 | def self.lint(content, cert, critical = false) 25 | messages = [] 26 | if content != "\x05\x00" 27 | messages << 'E: OCSP NoCheck extension must be null' 28 | end 29 | if critical != false 30 | messages << "W: Extension should not be critical for #{self}" 31 | end 32 | messages 33 | end 34 | end 35 | end 36 | end 37 | 38 | CertLint::CertExtLint.register_handler('1.3.6.1.5.5.7.48.1.5', CertLint::ASN1Ext::OcspNocheck) 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # certlint 2 | X.509 certificate linter 3 | 4 | certlint is currently at version 0.1.0. It does not yet build as a gem. For now, execute by running: 5 | 6 | `ruby -I lib bin/certlint` or `ruby -I lib bin/cablint` 7 | 8 | ## Required gems 9 | 10 | * public_suffix 11 | * open4 12 | * simpleidn 13 | 14 | If using less than Ruby 2.3, you also need the `unf` gem. 15 | 16 | ## Building certlint-x509helper 17 | 18 | certlint requires that the program certlint-x509helper be in your path and executable. 19 | 20 | See build-x509helper/README for instructions on building it. 21 | 22 | ## Output 23 | 24 | Messages will be output one per line. Each line will start with a single capital letter, a colon, and a space. The letters indicate the type of message: 25 | 26 | B: Bug. Your certificate has a feature not handled by certlint. 27 | I: Information. These are purely informational; no action is needed. 28 | N: Notice. These are items known to cause issues with one or more implementations of certificate processing but are not errors according to the standard. 29 | W: Warning. These are issues where a standard recommends differently but the standard uses terms such as "SHUOLD" or "MAY". 30 | E: Error. These are issues where the certificate is not compliant with the standard. 31 | F: Fatal Error. These errors are fatal to the checks and prevent most further checks from being executed. These are extremely bad errors. 32 | -------------------------------------------------------------------------------- /lib/certlint/extensions/asn1ext.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require 'rubygems' 16 | require 'openssl' 17 | 18 | module CertLint 19 | class ASN1Ext 20 | def self.lint(content, _cert, critical = false) 21 | messages = [] 22 | 23 | if !@pdu.nil? 24 | messages += CertLint.check_pdu(@pdu, content) 25 | else 26 | messages << 'E: No PDU defined' 27 | end 28 | if @critical_req != :optional 29 | if @critical_req != critical 30 | messages << "E: Extension criticality not allowed for #{self.to_s.split(':').last}" 31 | end 32 | end 33 | unless @critical_should.nil? 34 | if @critical_should != critical 35 | messages << "W: Extension should#{@critical_should ? '' : ' not'} be critical for #{self.to_s.split(':').last}" 36 | end 37 | end 38 | 39 | messages 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/certlint/extensions/extkeyusagesyntax.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class ExtKeyUsageSyntax < ASN1Ext 20 | @pdu = :ExtKeyUsageSyntax 21 | @critical_req = :optional 22 | 23 | def self.lint(content, cert, critical = false) 24 | messages = [] 25 | messages += super(content, cert, critical) 26 | 27 | e = OpenSSL::X509::Extension.new('2.5.29.37', content, critical) 28 | v = e.value 29 | 30 | if v.split(',').any? { |s| s.strip == 'Any Extended Key Usage' } 31 | if critical 32 | messages << 'W: extendedKeyUsage should not be critical if Any Extended Key Usage is present' 33 | end 34 | end 35 | 36 | messages 37 | end 38 | end 39 | end 40 | end 41 | 42 | CertLint::CertExtLint.register_handler('2.5.29.37', CertLint::ASN1Ext::ExtKeyUsageSyntax) 43 | -------------------------------------------------------------------------------- /lib/certlint/extensions/authoritykeyidentifier.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class AuthorityKeyIdentifier < ASN1Ext 20 | @pdu = :AuthorityKeyIdentifier 21 | @critical_req = false 22 | 23 | def self.lint(content, cert, critical = false) 24 | messages = [] 25 | messages += super(content, cert, critical) 26 | e = OpenSSL::X509::Extension.new('2.5.29.35', content, critical) 27 | keys = e.value.split(/\n/).map { |s| s.split(':').first } 28 | if keys.include? 'DirName' 29 | unless keys.include? 'serial' 30 | messages << 'E: AuthorityKeyIdentifier must include serial number if issuer is present' 31 | end 32 | elsif keys.include? 'serial' 33 | messages << 'E: AuthorityKeyIdentifier must include issuer if serial number is present' 34 | end 35 | 36 | messages 37 | end 38 | end 39 | end 40 | end 41 | 42 | CertLint::CertExtLint.register_handler('2.5.29.35', CertLint::ASN1Ext::AuthorityKeyIdentifier) 43 | -------------------------------------------------------------------------------- /bin/cablint-ct: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require 'certlint' 16 | require 'certlint/ct' 17 | 18 | LOGS = { 19 | 'pilot' => 'https://ct.googleapis.com/pilot', 20 | 'aviator' => 'https://ct.googleapis.com/aviator', 21 | 'rocketeer' => 'https://ct.googleapis.com/rocketeer', 22 | 'certly' => 'https://log.certly.io', 23 | 'digicert' => 'https://ct1.digicert-ct.com/log', 24 | 'symantec' => 'https://ct.ws.symantec.com', 25 | 'izenpe' => 'https://ct.izenpe.com', 26 | 'wosign' => 'https://ct.wosign.com', 27 | 'venafi' => 'https://ctlog.api.venafi.com', 28 | 'akamai' => 'https://ct.akamai.com', 29 | 'vega' => 'https://vega.ws.symantec.com' 30 | } 31 | 32 | log_url = ARGV[0] 33 | unless log_url.include? '://' 34 | log_url = LOGS[log_url] 35 | end 36 | 37 | entry = ARGV[1].to_i 38 | 39 | ct = CertLint::CT.new(log_url) 40 | ct.get_entries(entry, entry).each do |e| 41 | if e['leaf_input'].entry_type == 0 42 | der = e['leaf_input'].raw_certificate 43 | else 44 | der = e['extra_data'].pre_certificate.raw_certificate 45 | end 46 | m = CertLint::CABLint.lint(der) 47 | m.each do |msg| 48 | puts "#{msg}\tCT:#{entry}" 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/certlint/extensions/basicconstraints.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class BasicConstraints < ASN1Ext 20 | @pdu = :BasicConstraints 21 | @critical_req = :optional 22 | 23 | def self.lint(content, cert, critical = false) 24 | messages = [] 25 | messages += super(content, cert, critical) 26 | if messages.any? { |m| m.start_with? 'F:' } 27 | return messages 28 | end 29 | a = OpenSSL::ASN1.decode(content) 30 | is_ca = false 31 | if a.value.first.is_a? OpenSSL::ASN1::Boolean 32 | if a.value.first.value # True 33 | is_ca = true 34 | unless critical 35 | messages << 'E: basicConstraints must be critical in CA certificates' 36 | end 37 | else 38 | messages << 'E: CA:FALSE must not be explicitly encoded in basicConstraints' 39 | end 40 | end 41 | if !is_ca && a.value.last.is_a?(OpenSSL::ASN1::Integer) 42 | messages << 'E: Must not include pathLenConstraint on certificates that are not CA:TRUE' 43 | end 44 | messages 45 | end 46 | end 47 | end 48 | end 49 | 50 | CertLint::CertExtLint.register_handler('2.5.29.19', CertLint::ASN1Ext::BasicConstraints) 51 | -------------------------------------------------------------------------------- /lib/certlint/extensions/subjectaltname.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class SubjectAltName < ASN1Ext 20 | @pdu = :SubjectAltName 21 | @critical_req = :optional 22 | 23 | def self.lint(content, cert, critical = false) 24 | messages = [] 25 | messages += super(content, cert, critical) 26 | if cert.subject.to_a.empty? 27 | unless critical 28 | messages << 'E: subjectAltName must be critical if subject is empty' 29 | end 30 | else 31 | if critical 32 | messages << 'W: subjectAltName should not be critical' 33 | end 34 | end 35 | # If we are busted, don't continue 36 | if messages.any? { |m| m.start_with? 'F:' } 37 | return messages 38 | end 39 | # Content is a SEQUENCE of GeneralName (which is explicitly tagged) 40 | at_least_one = false 41 | OpenSSL::ASN1.decode(content).value.each do |genname| 42 | at_least_one = true 43 | messages += CertLint::GeneralNames.lint(genname) 44 | end 45 | unless at_least_one 46 | messages << 'E: subjectAltName extension must include at least one name' 47 | end 48 | messages 49 | end 50 | end 51 | end 52 | end 53 | 54 | CertLint::CertExtLint.register_handler('2.5.29.17', CertLint::ASN1Ext::SubjectAltName) 55 | -------------------------------------------------------------------------------- /lib/certlint/extensions/nameconstraints.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class NameConstraints < ASN1Ext 20 | @pdu = :NameConstraints 21 | # Explicitly violating RFC 5280 sect. 4.2.1.10 22 | @critical_req = :optional 23 | 24 | def self.lint(content, cert, critical = false) 25 | messages = [] 26 | messages += super(content, cert, critical) 27 | # If we are busted, don't continue 28 | if messages.any? { |m| m.start_with? 'F:' } 29 | return messages 30 | end 31 | # Content is a SEQUENCE of GeneralSubtrees which is tagged 32 | # X.509 says "At least one of permittedSubtrees and excludedSubtrees components shall be present." 33 | subtree_count = 0 34 | OpenSSL::ASN1.decode(content).value.each do |subtree_parent| 35 | subtree_count += 1 36 | at_least_one = false 37 | subtrees = subtree_parent.value 38 | subtrees.each do |subtree| 39 | at_least_one = true 40 | genname = subtree.value.first 41 | messages += CertLint::GeneralNames.lint(genname, false) 42 | end 43 | unless at_least_one 44 | messages << 'E: NameConstriants must contain at least one subtree' 45 | end 46 | end 47 | if subtree_count == 0 48 | messages << 'E: NameConstraints must include either permitted or excluded Subtrees' 49 | end 50 | messages 51 | end 52 | end 53 | end 54 | end 55 | 56 | CertLint::CertExtLint.register_handler('2.5.29.30', CertLint::ASN1Ext::NameConstraints) 57 | -------------------------------------------------------------------------------- /lib/certlint/certextlint.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require 'rubygems' 16 | require 'openssl' 17 | 18 | module CertLint 19 | class CertExtLint 20 | UNSUPPORTED_EXTENSIONS = [ 21 | '1.2.156.1.8888', 22 | '1.2.840.113533.7.65.0', 23 | '1.3.6.1.4.1.18332.19.1', 24 | '1.3.6.1.4.1.18332.42.6', 25 | '2.5.29.1', 26 | '2.5.29.10', 27 | '2.16.840.1.113732.4', 28 | '2.23.42.7.0' 29 | ] 30 | 31 | @@extension_handlers = {} 32 | 33 | def self.register_handler(oid, klass) 34 | if @@extension_handlers.key? oid 35 | fail 'Duplicate Extension registration' 36 | end 37 | @@extension_handlers[oid] = klass 38 | end 39 | 40 | # oid as string, critical as boolean, value as der, cert as OpenSSL::X509::Certificate 41 | def self.lint(oid, value, cert, critical = false) 42 | messages = [] 43 | 44 | if @@extension_handlers.key? oid 45 | messages += @@extension_handlers[oid].lint(value, cert, critical) 46 | return messages 47 | end 48 | 49 | if critical 50 | messages << "E: Opaque or unknown extension (#{oid}) marked as critical" 51 | end 52 | 53 | if UNSUPPORTED_EXTENSIONS.include? oid 54 | messages << "W: Extension #{oid} is treated as opaque extension" 55 | return messages 56 | end 57 | 58 | if oid.start_with? '2.16.840.1.113730.' 59 | messages << "W: Deprecated Netscape extension #{oid} treated as opaque extension" 60 | return messages 61 | end 62 | if oid.start_with? '1.3.6.1.4.1.311.' 63 | messages << "W: Microsoft extension #{oid} treated as opaque extension" 64 | return messages 65 | end 66 | 67 | messages << "E: Unknown Extension: #{oid}" 68 | 69 | messages 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /lib/certlint/pemlint.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require 'base64' 16 | 17 | module CertLint 18 | class PEMLint 19 | def self.lint(pem, type) 20 | messages = [] 21 | in_body = false 22 | last_line = false 23 | b64 = '' 24 | type.upcase! 25 | pem.force_encoding('BINARY') 26 | pem.split(/\n/).each do |line| 27 | line.strip! 28 | if in_body 29 | if line =~ /-END #{type}-/i 30 | if line !~ /^-/ 31 | messages << 'W: PEM boundaries should not have whitespace or characters before the boundary start' 32 | end 33 | if line !~ /^-----END /i 34 | messages << "W: PEM boundaries should start with five '-' characters" 35 | end 36 | m = /(-+)(END #{type})(-+)/i.match(line) 37 | if m[1] != m[3] 38 | messages << 'E: PEM boundary must have same number of - at start and end' 39 | end 40 | if m[2].upcase != m[2] 41 | messages << 'W: PEM boundary should be in all caps' 42 | end 43 | if line != m[0] 44 | messages << 'E: PEM boundary should be alone on line' 45 | end 46 | break 47 | end 48 | 49 | # Not boundary 50 | if last_line 51 | messages << 'W: Only the last PEM encoded line may be less than 64 characters' 52 | last_line = false 53 | end 54 | if line.length > 64 55 | messages << 'W: PEM encoded lines must be 64 characters or less' 56 | end 57 | if line.length < 64 58 | last_line = true 59 | end 60 | if line !~ %r{\A[A-Za-z0-9/+=]+\z} 61 | messages << 'E: PEM encoded lines may only contain base64 characters' 62 | end 63 | b64 += line 64 | next 65 | end 66 | if line =~ /-BEGIN #{type}-/i 67 | in_body = true 68 | if line !~ /^-/ 69 | messages << 'W: PEM boundaries should not have whitespace or characters before the boundary start' 70 | end 71 | if line !~ /^-----BEGIN /i 72 | messages << "W: PEM boundaries should start with five '-' characters" 73 | end 74 | m = /(-+)(BEGIN #{type})(-+)/i.match(line) 75 | if m[1] != m[3] 76 | messages << 'E: PEM boundary must have same number of - at start and end' 77 | end 78 | if m[2].upcase != m[2] 79 | messages << 'W: PEM boundary should be in all caps' 80 | end 81 | if line != m[0] 82 | messages << 'E: PEM boundary should be alone on line' 83 | end 84 | end 85 | end 86 | der = nil 87 | begin 88 | der = Base64.strict_decode64(b64) 89 | rescue ArgumentError 90 | messages << 'E: Incorrect base64 encoding' 91 | end 92 | [messages, der] 93 | end 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /lib/certlint/extensions/certificatepolicies.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | # Load unf if we don't have native methods 18 | unless String.method_defined?(:unicode_normalize) || String.method_defined?(:to_nfc) 19 | require 'unf' 20 | end 21 | 22 | module CertLint 23 | class ASN1Ext 24 | class CertificatePolicies < ASN1Ext 25 | @pdu = :CertificatePolicies 26 | @critical_req = :optional 27 | 28 | def self.lint(content, cert, critical = false) 29 | messages = [] 30 | messages += super(content, cert, critical) 31 | 32 | # If we are busted, don't continue 33 | if messages.any? { |m| m.start_with? 'F:' } 34 | return messages 35 | end 36 | 37 | # the qualifier in PolicyQualifierInfo is 38 | # defined as ANY, so we have to manually check 39 | OpenSSL::ASN1.decode(content).value.each do |policy_information| 40 | # policiyQualifiers are optional 41 | pq = policy_information.value[1] 42 | if pq.nil? 43 | next 44 | end 45 | # policiyQualifiers is a sequence of 46 | # PolicyQualifier Info 47 | pq.value.each do |pqi| 48 | qualid = pqi.value[0].oid 49 | q = pqi.value[1].to_der 50 | case qualid 51 | when '1.3.6.1.5.5.7.2.1' 52 | messages += CertLint.check_pdu(:CPSuri, q) 53 | when '1.3.6.1.5.5.7.2.2' 54 | new_messages = CertLint.check_pdu(:UserNotice, q) 55 | messages += new_messages 56 | if new_messages.any? { |m| m.start_with? 'F:' } 57 | next 58 | end 59 | user_notice = pqi.value[1].value 60 | if user_notice[0].is_a? OpenSSL::ASN1::Sequence 61 | # noticeRef 62 | messages << 'W: Certificate Policies should not contain notice references' 63 | user_notice.shift 64 | end 65 | if user_notice[0].nil? 66 | next 67 | end 68 | # See RFC 6818 section 3 which updates RFC 5280 69 | # user_notice[0] is explicitText 70 | if user_notice[0].tag == 12 || user_notice[0].tag == 30 # UTF8String || BMPString 71 | if user_notice[0].tag == 12 72 | txt = user_notice[0].value.force_encoding('UTF-8') 73 | else 74 | txt = user_notice[0].value.force_encoding('UTF-16BE').encode('UTF-8') 75 | end 76 | txt_nfc = nil 77 | if txt.respond_to? :unicode_normalize 78 | txt_nfc = txt.unicode_normalize(:nfc) 79 | else 80 | txt_nfc = txt.to_nfc 81 | end 82 | if txt != txt_nfc 83 | messages << 'W: Certificate policy explicit text should be in unicode normalization form C' 84 | end 85 | if txt.codepoints.any? { |c| (c >= 0x00 && c <= 0x1f) || (c >= 0x7f && c <= 0x9f) } 86 | messages << 'W: Certificate policy explicit text should not contain control characters' 87 | end 88 | elsif user_notice[0].tag == 22 # IA5String 89 | messages << 'E: Certificate Policy explicit text must not be IA5String' 90 | end 91 | else 92 | messages << 'E: Bad policy qualifier id' 93 | end 94 | end 95 | end 96 | messages 97 | end 98 | end 99 | end 100 | end 101 | 102 | CertLint::CertExtLint.register_handler('2.5.29.32', CertLint::ASN1Ext::CertificatePolicies) 103 | -------------------------------------------------------------------------------- /lib/certlint/extensions/keyusage.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require_relative 'asn1ext' 16 | 17 | module CertLint 18 | class ASN1Ext 19 | class KeyUsage < ASN1Ext 20 | @pdu = :KeyUsage 21 | @critical_req = :optional 22 | @critical_should = true 23 | 24 | def self.lint(content, cert, critical = false) 25 | messages = [] 26 | messages += super(content, cert, critical) 27 | 28 | v = OpenSSL::X509::Extension.new('2.5.29.15', content, critical).value.split(',').map(&:strip) 29 | 30 | pk = nil 31 | begin 32 | pk = cert.public_key 33 | rescue OpenSSL::PKey::PKeyError 34 | rescue OpenSSL::X509::CertificateError 35 | # Do nothing; will error below 36 | end 37 | 38 | if pk.nil? 39 | messages << 'E: Unable to parse public key' 40 | elsif pk.is_a? OpenSSL::PKey::RSA 41 | allowed = [ 42 | 'Digital Signature', 43 | 'Non Repudiation', 44 | 'Key Encipherment', 45 | 'Data Encipherment', 46 | 'Certificate Sign', 47 | 'CRL Sign' 48 | ] 49 | if v.any? { |u| !allowed.include? u } 50 | messages << 'E: Unallowed key usage for RSA public key' 51 | end 52 | if (v.include? 'Certificate Sign') || (v.include? 'CRL Sign') 53 | if (v.include? 'Key Encipherment') || (v.include? 'Data Encipherment') 54 | messages << 'W: Encipherment usage should not be mixed with Certificate/CRL signing' 55 | end 56 | end 57 | elsif pk.is_a? OpenSSL::PKey::DSA 58 | allowed = [ 59 | 'Digital Signature', 60 | 'Non Repudiation', 61 | 'Certificate Sign', 62 | 'CRL Sign' 63 | ] 64 | if v.any? { |u| !allowed.include? u } 65 | messages << 'E: Unallowed key usage for DSA public key' 66 | end 67 | elsif pk.is_a? OpenSSL::PKey::EC 68 | # A little complex as this can be either for ECDSA or ECDH 69 | allowed = [ 70 | 'Digital Signature', 71 | 'Non Repudiation', 72 | 'Key Agreement', 73 | 'Certificate Sign', 74 | 'CRL Sign', 75 | 'Encipher Only', 76 | 'Decipher Only' 77 | ] 78 | if v.any? { |u| !allowed.include? u } 79 | messages << 'E: Unallowed key usage for EC public key' 80 | end 81 | 82 | if (v.include? 'Encipher Only') || (v.include? 'Decipher Only') 83 | unless v.include? 'Key Agreement' 84 | messages << 'E: Key agreement required with encipher only or decipher only' 85 | end 86 | end 87 | if (v.include? 'Encipher Only') && (v.include? 'Decipher Only') 88 | messages << 'E: Encipher Only and Decipher Only must not both be set' 89 | end 90 | 91 | if (v.include? 'Certificate Sign') || (v.include? 'CRL Sign') 92 | if (v.include? 'Encipher Only') || (v.include? 'Decipher Only') || (v.include? 'Key Agreement') 93 | messages << 'W: Key agreement should not be included with Certificate/CRL Signing' 94 | end 95 | end 96 | elsif pk.is_a? OpenSSL::PKey::DH 97 | allowed = [ 98 | 'Key Agreement', 99 | 'Encipher Only', 100 | 'Decipher Only' 101 | ] 102 | if v.any? { |u| !allowed.include? u } 103 | messages << 'E: Unallowed key usage for DH public key' 104 | end 105 | unless v.include? 'Key Agreement' 106 | messages << 'E: Key Agreement must be included for DH public keys' 107 | end 108 | if (v.include? 'Encipher Only') && (v.include? 'Decipher Only') 109 | messages << 'E: Encipher Only and Decipher Only must not both be set' 110 | end 111 | else 112 | messages << "I: Key usages not checked for #{cert.public_key.class}" 113 | end 114 | messages 115 | end 116 | end 117 | end 118 | end 119 | 120 | CertLint::CertExtLint.register_handler('2.5.29.15', CertLint::ASN1Ext::KeyUsage) 121 | -------------------------------------------------------------------------------- /lib/certlint/iananames.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require 'rubygems' 16 | require 'simpleidn' 17 | require 'public_suffix' 18 | PublicSuffix::List.private_domains = false 19 | PublicSuffix::List.default_definition = File.new( 20 | File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'data', 'public_suffix_list.dat')), 21 | "r:utf-8") 22 | 23 | module CertLint 24 | class IANANames 25 | @iana_tlds = nil 26 | @special_domains = nil 27 | def self.load_domains 28 | @iana_tlds = {} 29 | @special_domains = [] 30 | spec_domains = {} 31 | 32 | # Load public domains from current root zone and from 33 | # ICANN's new gtlds list (some new gtlds are approved 34 | # but not yet in the root zone) 35 | 36 | datadir = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'data')) 37 | 38 | # from https://newgtlds.icann.org/newgtlds.csv 39 | File.open(File.join(datadir,'newgtlds.csv'), 'r:utf-8') do |f| 40 | lineno = 0 41 | f.each_line do |l| 42 | lineno += 1 43 | if lineno < 3 44 | next 45 | end 46 | @iana_tlds[l.split(',').first.downcase] = :public 47 | end 48 | end 49 | 50 | # from http://www.internic.net/domain/root.zone 51 | File.open(File.join(datadir,'root.zone')) do |f| 52 | f.each_line do |l| 53 | owner = l.split(/\s+/).first.downcase 54 | tld = owner.split('.').last 55 | next if tld.nil? 56 | @iana_tlds[tld] = :public 57 | end 58 | end 59 | 60 | # from http://www.iana.org/assignments/special-use-domain-names/special-use-domain.csv 61 | File.open(File.join(datadir, 'special-use-domain.csv')) do |f| 62 | lineno = 0 63 | f.each_line do |l| 64 | lineno += 1 65 | if lineno < 2 66 | next 67 | end 68 | dom = l.split(',').first.chomp('.') 69 | unless dom.include? '.' 70 | @iana_tlds[dom] = :special 71 | end 72 | spec_domains[dom] = true 73 | end 74 | end 75 | @special_domains = spec_domains.keys.sort.map { |d| '.' + d } 76 | end 77 | 78 | def self.lint(fqdn) 79 | if @iana_tlds.nil? 80 | load_domains 81 | end 82 | messages = [] 83 | 84 | # FQDNs are case insensitive 85 | # Normalize to lower case 86 | fqdn.downcase! 87 | 88 | # We can't do much with domains that are not fqdns 89 | unless fqdn.include? '.' 90 | messages << 'E: Unqualified domain name' 91 | return messages 92 | end 93 | 94 | tld = fqdn.split('.').last 95 | tld_type = @iana_tlds[tld] 96 | if tld_type.nil? 97 | messages << 'E: Unknown TLD' 98 | return messages 99 | elsif tld_type == :special 100 | if tld == 'onion' 101 | messages << 'I: Tor Service Descriptor in SAN' 102 | else 103 | messages << 'W: Special name' 104 | end 105 | return messages 106 | elsif tld_type != :public 107 | messages << 'E: Unknown type of TLD' 108 | end 109 | 110 | if ('.' + fqdn).end_with?(*@special_domains) 111 | messages << 'E: FQDN under reserved or special domain' 112 | end 113 | 114 | if fqdn.include? 'xn--' 115 | u = SimpleIDN.to_unicode(fqdn) 116 | else 117 | u = fqdn 118 | end 119 | 120 | d = nil 121 | begin 122 | d = PublicSuffix.parse(u) 123 | rescue PublicSuffix::DomainInvalid 124 | # We got this far, so assume this is a new tld 125 | # Check for wildcard rule 126 | parts = fqdn.split('.') 127 | if parts.count == 2 && (parts[0].include? '*') 128 | messages << 'E: Wildcard to immediate left of public suffix' 129 | end 130 | rescue PublicSuffix::DomainNotAllowed 131 | messages << 'W: Domain is bare public suffix' 132 | end 133 | unless d.nil? 134 | if !d.sld.nil? && d.sld.include?('*') 135 | messages << 'E: Wildcard to immediate left of public suffix' 136 | end 137 | if !d.domain.nil? && d.domain.include?('_') 138 | messages << 'W: Underscore in base domain' 139 | end 140 | end 141 | messages 142 | end 143 | end 144 | end 145 | -------------------------------------------------------------------------------- /lib/certlint/ct.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require 'rubygems' 16 | require 'net/http' 17 | require 'uri' 18 | require 'json' 19 | require 'bindata' 20 | require 'base64' 21 | require 'openssl' 22 | 23 | module CertLint 24 | class CT 25 | class PreCertificate < OpenSSL::X509::Certificate 26 | DER_SIG = OpenSSL::ASN1::BitString.new('0000').to_der 27 | 28 | attr_reader :raw 29 | 30 | def initialize(tbs_der) 31 | asn = OpenSSL::ASN1.decode(tbs_der) 32 | # tbsCertificate.version is optional, so we don't have a fixed 33 | # offset. Check if the first item is a pure ASN1Data, which 34 | # is a strong hint that it is an EXPLICIT wrapper for the first 35 | # element in the struct. If so, this is the version, so everything 36 | # is offset by one. 37 | skip = asn.value[0].instance_of?(OpenSSL::ASN1::ASN1Data) ? 1 : 0 38 | sig_alg_der = asn.value[1 + skip].to_der 39 | @raw = OpenSSL::ASN1::Sequence.new([tbs_der, sig_alg_der, DER_SIG]).to_der 40 | super(@raw) 41 | end 42 | end 43 | 44 | class ASN1Cert < BinData::Primitive 45 | endian :big 46 | uint24 :len, :value => lambda { data.length } 47 | string :data, :read_length => :len 48 | 49 | def get 50 | data 51 | end 52 | 53 | def set(v) 54 | data = v 55 | end 56 | 57 | def certificate 58 | OpenSSL::X509::Certificate.new(data) 59 | end 60 | 61 | def raw_certificate 62 | data 63 | end 64 | end 65 | 66 | class PreCert < BinData::Record 67 | endian :big 68 | string :issuer_key_hash, :read_length => 32 69 | ASN1Cert :tbs_certificate 70 | 71 | def certificate 72 | PreCertificate.new(tbs_certificate.data) 73 | end 74 | 75 | def raw_certificate 76 | PreCertificate.new(tbs_certificate.data).raw 77 | end 78 | end 79 | 80 | class MerkleTreeLeaf < BinData::Record 81 | hide :zero, :extensions_len 82 | endian :big 83 | uint8 :version, :assert => 0 # v1 84 | uint8 :leaf_type, :assert => 0 # timestamped_entry 85 | uint64 :timestamp # Unix timestamp in ms 86 | uint16 :entry_type 87 | choice :signed_entry, :selection => :entry_type do 88 | ASN1Cert 0 89 | PreCert 1 90 | end 91 | uint16 :extensions_len, :assert => 0 92 | string :extensions, :read_length => :extensions_len 93 | count_bytes_remaining :zero 94 | virtual :assert => lambda { zero == 0 } 95 | 96 | def self.read_base64(b64) 97 | read(Base64.decode64(b64)) 98 | end 99 | 100 | def raw_certificate 101 | signed_entry.raw_certificate 102 | end 103 | 104 | def certificate 105 | signed_entry.certificate 106 | end 107 | end 108 | 109 | class CertChain < BinData::Record 110 | hide :zero 111 | endian :big 112 | uint24 :chain_len 113 | array :chain, :type => ASN1Cert, :read_until => lambda { array.num_bytes == chain_len } 114 | count_bytes_remaining :zero 115 | virtual :assert => lambda { zero == 0 } 116 | 117 | def self.read_base64(b64) 118 | if b64 == 'AAAA' 119 | # Empty 120 | return CertChain.new 121 | end 122 | read(Base64.decode64(b64)) 123 | end 124 | 125 | def chain_certificates 126 | chain.map(&:certificate) 127 | end 128 | end 129 | 130 | class PrecertChainEntry < BinData::Record 131 | endian :big 132 | ASN1Cert :pre_certificate 133 | CertChain :precertificate_chain 134 | 135 | def self.read_base64(b64) 136 | if b64 == 'AAAA' 137 | # Empty 138 | return PrecertChainEntry.new 139 | end 140 | read(Base64.decode64(b64)) 141 | end 142 | 143 | def chain_certificates 144 | precertificate_chain.chain_certificates 145 | end 146 | end 147 | 148 | def initialize(log) 149 | @log = URI.parse(log + '/').normalize 150 | end 151 | 152 | def get_sth 153 | url = @log + 'ct/v1/get-sth' 154 | _call url 155 | end 156 | 157 | def get_entries(min = 0, max = 0) 158 | url = @log + 'ct/v1/get-entries' 159 | url.query = _qstr({ :start => min, :end => max }) 160 | j = _call(url) 161 | if j['entries'].nil? 162 | return [] 163 | end 164 | j['entries'].map do |x| 165 | e = {} 166 | e['leaf_input'] = MerkleTreeLeaf.read_base64(x['leaf_input']) 167 | if e['leaf_input'].entry_type == 0 168 | e['extra_data'] = CertChain.read_base64(x['extra_data']) 169 | else 170 | e['extra_data'] = PrecertChainEntry.read_base64(x['extra_data']) 171 | end 172 | e 173 | end 174 | end 175 | 176 | private 177 | 178 | def _qstr(h) 179 | h.map { |k, v| "#{k}=#{v}" }.join('&') 180 | end 181 | 182 | def _call(url) 183 | resp = Net::HTTP.get_response url 184 | JSON.parse(resp.body) 185 | end 186 | end 187 | end 188 | -------------------------------------------------------------------------------- /lib/certlint/generalnames.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | 16 | module CertLint 17 | class GeneralNames 18 | # Allow RFC defying '*' and '_' 19 | DLABEL = '((?!-)[A-Za-z0-9*_-]{1,63}(? 253 114 | messages << 'E: FQDN in DNSName is too long' 115 | end 116 | unless is_san 117 | if fqdn.include?('*') 118 | messages << 'E: Wildcard in FQDN' 119 | end 120 | end 121 | if fqdn.include?('_') 122 | messages << 'W: Underscore should not appear in DNS names' 123 | end 124 | when 3 # X400Address 125 | orig = genname.value 126 | if orig.nil? || orig.empty? 127 | messages << "E: X400Address is empty" 128 | return messages # Fatal to this entry 129 | end 130 | messages << "I: No checks for X400Address" 131 | when 4 # DirectoryName 132 | orig = genname.value 133 | if orig.nil? || orig.empty? 134 | messages << "E: DirectoryName is empty" 135 | return messages # Fatal to this entry 136 | end 137 | messages << "I: No checks for DirectoryName" 138 | when 5 # EDIPartyName 139 | orig = genname.value 140 | if orig.nil? || orig.empty? 141 | messages << "E: EDIPartyName is empty" 142 | return messages # Fatal to this entry 143 | end 144 | messages << "I: No checks for EDIPartyName" 145 | when 6 # URI 146 | orig = genname.value 147 | if orig.nil? || orig.empty? 148 | messages << "E: URI is empty" 149 | return messages # Fatal to this entry 150 | end 151 | messages << "I: No checks for URI" 152 | # No checks 153 | when 7 # IPAddress 154 | len = genname.value.length 155 | if is_san 156 | unless len == 4 || len == 16 157 | messages << 'E: Invalid IP address in SAN' 158 | end 159 | else # constraint 160 | unless len == 8 || len == 32 161 | messages << 'E: Invalid IP address in constraint' 162 | end 163 | end 164 | when 8 # RegisteredId 165 | orig = genname.value 166 | if orig.nil? || orig.empty? 167 | messages << 'E: RegisteredId is empty' 168 | return messages # Fatal to this entry 169 | end 170 | messages << "I: No checks for RegisteredId" 171 | # No checks 172 | else 173 | messages << 'E: Unknown type of name in subjectAltName' 174 | end 175 | messages 176 | end 177 | end 178 | end 179 | -------------------------------------------------------------------------------- /lib/certlint/namelint.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require 'rubygems' 16 | require 'openssl' 17 | require_relative 'dn_attrs' 18 | 19 | module CertLint 20 | # Validate DirectoryNames 21 | class NameLint 22 | # ISO 3166-1 alpha-2 countries plus 'XX' 23 | COUNTRIES = [ 24 | 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AN', 'AO', 'AQ', 'AR', 25 | 'AS', 'AT', 'AU', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 26 | 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS', 'BT', 'BV', 27 | 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 28 | 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ', 'DE', 'DJ', 29 | 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET', 'FI', 30 | 'FJ', 'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF', 'GG', 'GH', 31 | 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY', 32 | 'HK', 'HM', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 33 | 'IQ', 'IR', 'IS', 'IT', 'JE', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 34 | 'KM', 'KN', 'KP', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 35 | 'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 36 | 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 37 | 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NF', 'NG', 'NI', 'NL', 38 | 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 39 | 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY', 'QA', 'RE', 'RO', 'RS', 40 | 'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 41 | 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX', 'SY', 'SZ', 'TC', 42 | 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 43 | 'TV', 'TW', 'TZ', 'UA', 'UG', 'UM', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 44 | 'VG', 'VI', 'VN', 'VU', 'WF', 'WS', 'YE', 'YT', 'ZA', 'ZM', 'ZW', 'XX' 45 | ] 46 | 47 | RDN_ATTRIBUTES = { 48 | # COSINE / RFC 4524 49 | '0.9.2342.19200300.100.1.1' => [:DirectoryString, 256], # UID 50 | '0.9.2342.19200300.100.1.4' => [:DirectoryString, 2048], # info 51 | '0.9.2342.19200300.100.1.25' => [:DomainComponent, :DNS], # DC 52 | # PKCS#9 / RFC 2985 53 | '1.2.840.113549.1.9.1' => :EmailAddress, # emailAddress 54 | '1.2.840.113549.1.9.2' => [:PKCS9String, :PKCS9], # unstructuredName 55 | '1.2.840.113549.1.9.8' => [:DirectoryString, 255], # unstructuredAddress 56 | # CA/Browser Forum EV Gudelines 57 | '1.3.6.1.4.1.311.60.2.1.1' => :X520LocalityName, # jurisdictionOfIncorporationLocalityName 58 | '1.3.6.1.4.1.311.60.2.1.2' => :X520StateOrProvinceName, # jurisdictionOfIncorporationStateOrProvinceName 59 | '1.3.6.1.4.1.311.60.2.1.3' => [:X520countryName, :Country], # jurisdictionOfIncorporationCountryName 60 | # Attributes are taken from RFC 5280 if possible 61 | # Otherwise from X.520 using Annex C for upper bounds 62 | '2.5.4.3' => :X520CommonName, # CN 63 | '2.5.4.4' => :X520name, # SN 64 | '2.5.4.5' => :X520SerialNumber, # serialNumber 65 | '2.5.4.6' => [:X520countryName, :Country], # C 66 | '2.5.4.7' => :X520LocalityName, # L 67 | '2.5.4.8' => :X520StateOrProvinceName, # ST 68 | '2.5.4.9' => :X520StateOrProvinceName, # streetAddress 69 | '2.5.4.10' => :X520OrganizationName, # O 70 | '2.5.4.11' => :X520OrganizationalUnitName, # OU 71 | '2.5.4.12' => :X520Title, # title 72 | '2.5.4.13' => [:DirectoryString, 1024], # description 73 | '2.5.4.15' => :X520LocalityName, # businessCategory 74 | '2.5.4.16' => :PostalAddress, # postalAddress 75 | '2.5.4.17' => [:DirectoryString, 40], # postalCode 76 | '2.5.4.18' => [:DirectoryString, 40], # postOfficeBox 77 | '2.5.4.20' => :OrganizationalUnitName, # telephoneNumber 78 | '2.5.4.41' => :X520name, # name 79 | '2.5.4.42' => :X520name, # GN 80 | '2.5.4.43' => :X520name, # initials 81 | '2.5.4.45' => :UniqueIdentifier, 82 | '2.5.4.46' => :PrintableString, # dnQualifier 83 | '2.5.4.51' => :DirectoryString, # houseIdentifier 84 | '2.5.4.54' => :DirectoryString, # dmdName 85 | } 86 | 87 | # List of attributes that are known deprecated 88 | DEPRECATED_ATTRIBUTES = [ 89 | '1.2.840.113549.1.9.1' # EmailAddress, Per RFC 5280 section 4.1.2.6 90 | ] 91 | 92 | DLABEL = /\A((?!-)[A-Za-z0-9-]{1,63}(? 1 115 | messages << 'W: Multiple attributes in a single RDN in the subject Name' 116 | end 117 | rdn.value.each do |attr| 118 | attr_messages = [] 119 | 120 | type = attr.value[0].oid 121 | attr_types << type 122 | value = attr.value[1] 123 | attrname = attr_name(type) 124 | 125 | validator = nil 126 | pdu = RDN_ATTRIBUTES[type] 127 | if pdu.nil? 128 | attr_messages << "W: Name has unknown attribute #{attrname}" 129 | messages += attr_messages 130 | next 131 | end 132 | if pdu.is_a? Array 133 | validator = pdu[1] 134 | pdu = pdu[0] 135 | end 136 | 137 | if DEPRECATED_ATTRIBUTES.include? type 138 | attr_messages << "W: Name has deprecated attribute #{attrname}" 139 | end 140 | 141 | attr_messages += CertLint.check_pdu(pdu, value.to_der) 142 | if attr_messages.any? { |m| m.start_with? 'F:' } 143 | messages += attr_messages 144 | next 145 | end 146 | 147 | # If expliclty tagged, then nothing we can really check 148 | # (no known attributes use explicitly tagged values) 149 | if value.tag_class != :UNIVERSAL 150 | messages += attr_messages 151 | next 152 | end 153 | 154 | # Warn about strings that allow escape sequences and 155 | # Unicode strings that are not UTF-8 156 | check_padding = false 157 | tag = value.tag 158 | case tag 159 | when 12 # UTF8 160 | value = value.value 161 | check_padding = true 162 | when 18 # Numeric (7-bit) 163 | value = value.value 164 | check_padding = true 165 | when 19 # Printable (7-bit) 166 | value = value.value 167 | check_padding = true 168 | when 20 # Teletex (7-bit) 169 | value = value.value 170 | check_padding = true 171 | attr_messages << "W: #{attrname} is using deprecated TeletexString" 172 | when 21 # Videotex 173 | value = value.value 174 | check_padding = true 175 | attr_messages << "W: #{attrname} is using deprecated VideoexString" 176 | when 22 # IA5 177 | value = value.value 178 | check_padding = true 179 | when 25 # Graphic 180 | value = value.value 181 | check_padding = true 182 | attr_messages << "W: #{attrname} is using deprecated GraphicString" 183 | when 26 # Visible 184 | value = value.value 185 | check_padding = true 186 | when 27 # General 187 | value = value.value 188 | check_padding = true 189 | attr_messages << "W: #{attrname} is using deprecated GeneralString" 190 | when 28 # Universal 191 | check_padding = true 192 | attr_messages << "W: Unicode #{attrname} is using deprecated UniversalString" 193 | value = value.value.force_encoding('UTF-32BE').encode('UTF-8') 194 | when 30 # BMP 195 | check_padding = true 196 | attr_messages << "W: Unicode #{attrname} is using deprecated BMPString" 197 | value = value.value.force_encoding('UTF-16BE').encode('UTF-8') 198 | end 199 | 200 | if check_padding 201 | if value =~ /\A\s+/ 202 | attr_messages << "W: Leading whitepsace in #{attrname}" 203 | end 204 | if value =~ /\s+\z/ 205 | attr_messages << "W: Trailing whitespace in #{attrname}" 206 | end 207 | end 208 | 209 | case validator 210 | when Integer 211 | # Measured in characters not octets 212 | if value.length > validator 213 | attr_messages << "E: #{attrname} is too long" 214 | end 215 | when :Country 216 | unless COUNTRIES.include? value.upcase 217 | attr_messages << "E: Invalid country in #{attrname}" 218 | end 219 | when :DNS 220 | unless value =~ DLABEL 221 | attr_messages << "E: Invalid label in #{attrname}" 222 | end 223 | when :PKCS9 224 | if value.length > 255 225 | attr_messages << "E: #{attrname} is too long" 226 | end 227 | if value.codepoints.all? { |c| c <= 0x7e } 228 | unless tag == 22 229 | attr_messages << "W: #{attrname} should be encoded as IA5String" 230 | end 231 | else 232 | unless tag == 12 233 | attr_messages << "W: #{attrname} should be encoded as UF8String" 234 | end 235 | end 236 | end 237 | messages += attr_messages 238 | end 239 | end 240 | 241 | dup = attr_types.select { |el| attr_types.count(el) > 1 }.uniq 242 | # OU and DC can reasonably appear multiple times 243 | dup.delete('2.5.4.11') 244 | dup.delete('0.9.2342.19200300.100.1.25') 245 | dup.each do |type| 246 | attrname = attr_name(type) 247 | messages << "W: Name has multiple #{attrname} attributes" 248 | end 249 | 250 | # Can OpenSSL handle the name? 251 | begin 252 | name.to_s(OpenSSL::X509::Name::RFC2253 & ~4) 253 | rescue OpenSSL::X509::NameError => e 254 | messages << "E: Unparsable name: #{e.message}" 255 | end 256 | 257 | messages 258 | end 259 | end 260 | end 261 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /lib/certlint/cablint.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require 'rubygems' 16 | require 'openssl' 17 | require 'ipaddr' 18 | require 'simpleidn' 19 | require_relative 'certlint' 20 | require_relative 'iananames' 21 | require_relative 'pemlint' 22 | 23 | module CertLint 24 | class CABLint 25 | BR_EFFECTIVE = Time.new(2012, 7, 1) 26 | MONTHS_39 = Time.new(2015, 4, 1) 27 | NO_SHA1 = Time.new(2016, 1, 1) 28 | 29 | # Allowed algorithms 30 | SIGNATURE_ALGORITHMS = { 31 | 'sha1WithRSAEncryption' => :weak, 32 | 'sha256WithRSAEncryption' => :good, 33 | 'sha384WithRSAEncryption' => :good, 34 | 'sha512WithRSAEncryption' => :good, 35 | 'rsassaPss' => :pss, 36 | 'dsaWithSHA1' => :weak, 37 | 'dsa_with_SHA256' => :good, 38 | 'ecdsa-with-SHA1' => :weak, 39 | 'ecdsa-with-SHA256' => :good, 40 | 'ecdsa-with-SHA384' => :good, 41 | 'ecdsa-with-SHA512' => :good 42 | } 43 | 44 | def self.lint(der) 45 | messages = [] 46 | messages += CertLint.lint(der) 47 | 48 | if messages.any? { |m| m.start_with? 'F:' } 49 | messages << 'W: Cowardly refusing to run CAB check due to previous errors' 50 | return messages 51 | end 52 | 53 | begin 54 | c = OpenSSL::X509::Certificate.new(der) 55 | rescue 56 | # Catch anything and move along 57 | # CertLint will already be full of errors 58 | messages << 'E: Skipping CAB checks due to previous errors' 59 | return messages 60 | end 61 | 62 | sa = SIGNATURE_ALGORITHMS[c.signature_algorithm] 63 | if sa.nil? 64 | messages << "E: #{c.signature_algorithm} is not allowed for signing certificates" 65 | else 66 | if sa == :weak && c.not_before >= NO_SHA1 67 | messages << 'E: SHA-1 not allowed for signing certificates' 68 | end 69 | if sa == :weak && c.serial.num_bytes < 8 70 | messages << 'W: Serial numbers for certificates using weaker hashes should have at least 64 bits of entropy' 71 | elsif sa == :pss 72 | messages << 'W: PSS is not suppported by most browsers' 73 | end 74 | end 75 | 76 | if sa != :weak && c.serial.num_bits < 20 77 | messages << 'W: Serial numbers should have at least 20 bits of entropy' 78 | end 79 | 80 | begin 81 | key = c.public_key 82 | rescue OpenSSL::PKey::PKeyError 83 | messages << 'E: Invalid subject public key' 84 | key = nil 85 | rescue OpenSSL::X509::CertificateError 86 | messages << 'E: Invalid subject public key' 87 | key = nil 88 | end 89 | if key.is_a? OpenSSL::PKey::RSA 90 | if key.n.num_bits < 2048 91 | messages << 'E: RSA subject key modulus must be at least 2048 bits' 92 | end 93 | unless key.e.odd? 94 | messages << 'E: RSA subject key exponent must be odd' 95 | end 96 | elsif key.is_a? OpenSSL::PKey::DSA 97 | l = key.p.num_bits 98 | n = key.q.num_bits 99 | if l < 2048 100 | messages << 'E: DSA subject key p must be at least 2048 bits' 101 | elsif !( 102 | (l == 2048 && n == 224) || 103 | (l == 2048 && n == 256) || 104 | (l == 3072 && n == 256) 105 | ) 106 | messages << 'E: DSA subject key must have FIPS 186-4 compliant parameters' 107 | end 108 | elsif key.is_a? OpenSSL::PKey::EC 109 | curve = key.group.curve_name 110 | unless ['prime256v1', 'secp384r1', 'secp521r1'].include? curve 111 | messages << 'E: EC subject key is not on allowed curve' 112 | end 113 | elsif !key.nil? 114 | messages << 'E: Subject key must be RSA, DSA, or EC' 115 | end 116 | 117 | is_ca = false 118 | bc = c.extensions.find { |ex| ex.oid == 'basicConstraints' } 119 | unless bc.nil? 120 | is_ca = (bc.value.include? 'CA:TRUE') 121 | end 122 | 123 | # First check CA certs 124 | if is_ca 125 | messages << 'I: CA certificate identified' 126 | unless c.subject.to_a.any? { |d| d[0] == 'C' } 127 | messages << 'E: CA certificates must include countryName in subject' 128 | end 129 | unless c.subject.to_a.any? { |d| d[0] == 'O' } 130 | messages << 'E: CA certificates must include organizationName in subject' 131 | end 132 | unless c.subject.to_a.any? { |d| d[0] == 'CN' } 133 | messages << 'E: CA certificates must include commonName in subject' 134 | end 135 | if (c.not_after.year - c.not_before.year) > 25 136 | messages << 'W: CA certificates should not have a validity period greater than 25 years' 137 | elsif (c.not_after.year - c.not_before.year) == 25 138 | if c.not_after.month > c.not_before.month 139 | messages << 'W: CA certificates should not have a validity period greater than 25 years' 140 | elsif c.not_after.month == c.not_before.month 141 | if c.not_after.day > c.not_before.day 142 | messages << 'W: CA certificates should not have a validity period greater than 25 years' 143 | end 144 | end 145 | end 146 | 147 | ku = c.extensions.find { |ex| ex.oid == 'keyUsage' } 148 | if ku.nil? 149 | messages << 'E: CA certificates must include keyUsage extension' 150 | ku = [] 151 | else 152 | unless ku.critical? 153 | messages << 'E: CA certificates must set keyUsage extension as critical' 154 | end 155 | ku = ku.value.split(',').map(&:strip) 156 | end 157 | 158 | unless ku.include? 'CRL Sign' 159 | messages << 'E: CA certificates must include CRL Signing' 160 | end 161 | unless ku.include? 'Digital Signature' 162 | messages << 'N: CA certificates without Digital Signature do not allow direct signing of OCSP responses' 163 | end 164 | 165 | if c.extensions.find { |ex| ex.oid == 'subjectAltName' } 166 | messages << 'W: CA certificates should not include subject alternative names' 167 | end 168 | 169 | return messages 170 | end 171 | 172 | # Things left are subscriber certificates 173 | cert_type_identified = false 174 | 175 | # Use EKUs and Subject attribute types to guess the cert type 176 | eku = c.extensions.find { |ex| ex.oid == 'extendedKeyUsage' } 177 | if eku.nil? 178 | eku = [] 179 | else 180 | eku = eku.value.split(',').map(&:strip).sort 181 | end 182 | subjattrs = c.subject.to_a.map { |a| a[0] }.uniq 183 | 184 | if subjattrs.include?('1.3.6.1.4.1.311.60.2.1.3') || subjattrs.include?('jurisdictionC') 185 | # EV 186 | messages << 'I: EV certificate identified' 187 | cert_type_identified = true 188 | unless subjattrs.include? 'O' 189 | messages << 'E: EV certificates must include organizationName in subject' 190 | end 191 | unless subjattrs.include? 'businessCategory' 192 | messages << 'E: EV certificates must include businessCategory in subject' 193 | end 194 | unless subjattrs.include? 'serialNumber' 195 | messages << 'E: EV certificates must include serialNumber in subject' 196 | end 197 | unless subjattrs.include? 'L' 198 | messages << 'E: EV certificates must include localityName in subject' 199 | end 200 | unless subjattrs.include? 'C' 201 | messages << 'E: EV certificates must include countryName in subject' 202 | end 203 | end 204 | 205 | # So many ways to indicate an in-scope certificate 206 | if eku.empty? || \ 207 | eku.include?('TLS Web Server Authentication') || \ 208 | eku.include?('Any Extended Key Usage') || \ 209 | eku.include?('Netscape Server Gated Crypto') || \ 210 | eku.include?('Microsoft Server Gated Crypto') 211 | messages << 'I: TLS Server certificate identified' 212 | cert_type_identified = true 213 | # OK, we have a "SSL" certificate 214 | # Allowed to contain these three EKUs 215 | eku.delete('TLS Web Server Authentication') 216 | eku.delete('TLS Web Client Authentication') 217 | eku.delete('E-mail Protection') 218 | # Also implicitly allowed 219 | eku.delete('Any Extended Key Usage') 220 | # Intel AMT/vPro: https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/default.htm?turl=WordDocuments%2Facquiringanintelvprocertificate.htm 221 | if eku.include?('2.16.840.1.113741.1.2.3') 222 | messages << 'I: Intel AMT/vPro certificate identified' 223 | eku.delete('2.16.840.1.113741.1.2.3') 224 | end 225 | eku.each do |e| 226 | messages << "W: TLS Server auth certificates should not contain #{e} usage" 227 | end 228 | 229 | months = (c.not_after.year - c.not_before.year) * 12 230 | months += (c.not_after.month - c.not_before.month) 231 | if c.not_after.day > c.not_before.day 232 | months += 1 233 | end 234 | 235 | if subjattrs.include?('1.3.6.1.4.1.311.60.2.1.3') || subjattrs.include?('jurisdictionC') 236 | # EV 237 | if months > 27 238 | messages << 'E: EV certificates must be 27 months in validity or less' 239 | end 240 | elsif c.not_before < BR_EFFECTIVE 241 | if months > 120 242 | messages << 'W: Pre-BR certificates should not be more than 120 months in validity' 243 | end 244 | elsif (c.not_before < MONTHS_39) && (c.not_before >= BR_EFFECTIVE) 245 | if months > 60 246 | messages << 'E: BR certificates must be 60 months in validity or less' 247 | end 248 | elsif c.not_before >= MONTHS_39 249 | if months > 39 250 | messages << 'E: BR certificates must be 39 months in validity or less' 251 | end 252 | end 253 | if subjattrs.include? 'O' 254 | if !(subjattrs.include? 'L') && !(subjattrs.include? 'ST') 255 | messages << 'E: BR certificates with organizationName must include either localityName or stateOrProvinceName' 256 | end 257 | unless subjattrs.include? 'C' 258 | messages << 'E: BR certificates with organizationName must include countryName' 259 | end 260 | else 261 | if subjattrs.include? 'L' 262 | messages << 'E: BR certificates without organizationName must not include localityName' 263 | end 264 | if subjattrs.include? 'ST' 265 | messages << 'E: BR certificates without organizationName must not include stateOrProvinceName' 266 | end 267 | if subjattrs.include? 'street' 268 | messages << 'E: BR certificates without organizationName must not include streetAddress' 269 | end 270 | if subjattrs.include? 'postalCode' 271 | messages << 'E: BR certificates without organizationName must not include postalCode' 272 | end 273 | end 274 | 275 | aia = c.extensions.find { |ex| ex.oid == 'authorityInfoAccess' } 276 | if aia.nil? 277 | messages << 'E: BR certificates must include authorityInformationAccess' 278 | else 279 | aia_info = aia.value.split(/\n/) 280 | unless aia_info.any? { |i| i.start_with? 'OCSP - URI:http://' } 281 | messages << 'E: BR certificates must include a HTTP URL of the OCSP responder' 282 | end 283 | unless aia_info.any? { |i| i.start_with? 'CA Issuers - URI:http://' } 284 | messages << 'W: BR certificates should include a HTTP URL of the issuing CA\'s certificate' 285 | end 286 | end 287 | 288 | certpolicies = c.extensions.find { |ex| ex.oid == 'certificatePolicies' } 289 | if certpolicies.nil? 290 | messages << 'E: BR certificates must include certificatePolicies' 291 | else 292 | unless certpolicies.value.start_with? 'Policy: ' 293 | messages << 'E: BR certificates must contain at least one policy' 294 | end 295 | end 296 | 297 | ku = c.extensions.find { |ex| ex.oid == 'keyUsage' } 298 | unless ku.nil? 299 | ku = ku.value.split(',').map(&:strip) 300 | if ku.include? 'CRL Sign' 301 | messages << 'E: BR certificates must not include CRL Signing' 302 | end 303 | if ku.include? 'Certificate Sign' 304 | messages << 'E: BR certificates must not include Certificate Signing' 305 | end 306 | end 307 | 308 | san = c.extensions.find { |ex| ex.oid == 'subjectAltName' } 309 | names = [] 310 | if san.nil? 311 | messages << 'E: BR certificates must have subject alternative names extension' 312 | else 313 | # See certlint.rb and asn1ext.rb to sort out the next two lines 314 | # This gets the extnValue (which is DER) 315 | der = OpenSSL::ASN1.decode(san.to_der).value.last.value 316 | # Now decode the extnValue to get a sequence of general names 317 | OpenSSL::ASN1.decode(der).each do |genname| 318 | nameval = nil 319 | case genname.tag 320 | when 0 321 | messages << 'E: BR certificates must not contain otherName type alternative name' 322 | next 323 | when 1 324 | messages << 'E: BR certificates must not contain rfc822Name type alternative name' 325 | next 326 | when 2 327 | val = genname.value 328 | if val.include? '*' 329 | x = val.split('.', 2) 330 | if (x.length > 1) && (x[1].include? '*') 331 | messages << 'E: Wildcard not in first label of FQDN' 332 | elsif x.length == 1 333 | messages << 'E: Bare wildcard' 334 | end 335 | unless val.start_with? '*.' 336 | messages << 'W: Wildcard other than *. in SAN' 337 | end 338 | end 339 | messages += CertLint::IANANames.lint(val).map { |m| m + ' in SAN' } 340 | nameval = val.downcase.force_encoding('US-ASCII') # A-label 341 | when 3 342 | messages << 'E: BR certificates must not contain x400Address type alternative name' 343 | next 344 | when 4 345 | messages << 'E: BR certificates must not contain directoryName type alternative name' 346 | next 347 | when 5 348 | messages << 'E: BR certificates must not contain ediPartyName type alternative name' 349 | next 350 | when 6 351 | messages << 'E: BR certificates must not contain uniformResourceIdentifier type alternative name' 352 | next 353 | when 7 354 | if genname.value.length == 4 || genname.value.length == 16 355 | n = IPAddr.new_ntoh(genname.value) 356 | nameval = n.to_s.downcase 357 | else 358 | # Certlint already added an error for wrong size, so just skip here 359 | next 360 | end 361 | when 8 362 | messages << 'E: BR certificates must not contain registeredID type alternative name' 363 | next 364 | end 365 | if names.include? nameval 366 | messages << 'E: Duplicate SAN entry' 367 | else 368 | names << nameval 369 | end 370 | end 371 | end 372 | idn_san = names.select{ |s| s.include?('xn--') }.map { |a| SimpleIDN.to_unicode(a) } 373 | c.subject.to_a.select { |rdn| rdn[0] == 'CN' }.map do |rdn| 374 | val = nil 375 | case rdn[2] 376 | when 12 377 | val = rdn[1].force_encoding('UTF-8') 378 | when 28 379 | val = rdn[1].force_encoding('UTF-32BE').encode('UTF-8') 380 | when 30 381 | val = rdn[1].force_encoding('UTF-16BE').encode('UTF-8') 382 | else 383 | val = rdn[1].force_encoding('ISO-8859-1').encode('UTF-8') 384 | end 385 | val 386 | end.each do |val| 387 | unless names.include? val.downcase 388 | if idn_san.include? val 389 | messages << 'W: commonNames in BR certificate contains U-labels' 390 | else 391 | messages << 'E: commonNames in BR certificates must be from SAN entries' 392 | end 393 | end 394 | end 395 | end 396 | 397 | unless cert_type_identified 398 | messages << 'I: No certificate type identified' 399 | end 400 | 401 | messages 402 | end 403 | end 404 | end 405 | 406 | if __FILE__ == $PROGRAM_NAME 407 | ARGV.each do |file| 408 | fn = File.basename(file) 409 | raw = File.read(file) 410 | 411 | if raw.include? '-BEGIN CERTIFICATE-' 412 | m, der = PEMLint.lint(raw, 'CERTIFICATE') 413 | else 414 | m = [] 415 | der = raw 416 | end 417 | 418 | m += CABLint.lint(der) 419 | m.each do |msg| 420 | puts "#{msg}\t#{fn}" 421 | end 422 | end 423 | end 424 | -------------------------------------------------------------------------------- /lib/certlint/certlint.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby -Eutf-8:utf-8 2 | # encoding: UTF-8 3 | # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"). You may not 6 | # use this file except in compliance with the License. A copy of the License 7 | # is located at 8 | # 9 | # http://aws.amazon.com/apache2.0/ 10 | # 11 | # or in the "license" file accompanying this file. This file is distributed on 12 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | # express or implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | require 'rubygems' 16 | require 'open4' 17 | require 'openssl' 18 | 19 | require_relative 'namelint' 20 | require_relative 'certextlint' 21 | require_relative 'extensions/authorityinfoaccesssyntax' 22 | require_relative 'extensions/authoritykeyidentifier' 23 | require_relative 'extensions/basicconstraints' 24 | require_relative 'extensions/certificatepolicies' 25 | require_relative 'extensions/crldistributionpoints' 26 | require_relative 'extensions/ctpoison' 27 | require_relative 'extensions/extkeyusagesyntax' 28 | require_relative 'extensions/freshestcrl' 29 | require_relative 'extensions/inhibitanypolicy' 30 | require_relative 'extensions/issueraltname' 31 | require_relative 'extensions/keyusage' 32 | require_relative 'extensions/logotypeextn' 33 | require_relative 'extensions/nameconstraints' 34 | require_relative 'extensions/ocspnocheck' 35 | require_relative 'extensions/policyconstraints' 36 | require_relative 'extensions/policymappings' 37 | require_relative 'extensions/privatekeyusageperiod' 38 | require_relative 'extensions/qcstatements' 39 | require_relative 'extensions/signedcertificatetimestamplist' 40 | require_relative 'extensions/smimecapabilities' 41 | require_relative 'extensions/subjectaltname' 42 | require_relative 'extensions/subjectdirectoryattributes' 43 | require_relative 'extensions/subjectinfoaccesssyntax' 44 | require_relative 'extensions/subjectkeyidentifier' 45 | 46 | module CertLint 47 | SIG_STRUCTS = { 48 | '1.2.840.113549.1.1.2' => :rsa, 49 | '1.2.840.113549.1.1.3' => :rsa, 50 | '1.2.840.113549.1.1.4' => :rsa, 51 | '1.2.840.113549.1.1.5' => :rsa, 52 | '1.2.840.113549.1.1.11' => :rsa, 53 | '1.2.840.113549.1.1.12' => :rsa, 54 | '1.2.840.113549.1.1.13' => :rsa, 55 | '1.2.840.113549.1.1.10' => :pss, 56 | '1.2.840.10040.4.3' => :dsa, 57 | '2.16.840.1.101.3.4.3.2' => :dsa, 58 | '1.2.840.10045.4.1' => :ecdsa, 59 | '1.2.840.10045.4.3.2' => :ecdsa, 60 | '1.2.840.10045.4.3.3' => :ecdsa, 61 | '1.2.840.10045.4.3.4' => :ecdsa 62 | } 63 | 64 | def self.x509helper(args, passin = nil) 65 | cmd = ['certlint-x509helper'] 66 | cmd += args.split(/\s+/) 67 | out = nil 68 | err = nil 69 | status = Open4.open4(*cmd) do |_pid, stdin, stdout, stderr| 70 | stdin.binmode 71 | stdout.binmode 72 | unless passin.nil? 73 | begin 74 | stdin.write(passin) 75 | rescue Errno::EPIPE 76 | # FIXME: Do something smart here 77 | end 78 | stdin.close 79 | end 80 | out = stdout.read 81 | err = stderr.read 82 | end 83 | [status.exitstatus, out, err] 84 | end 85 | 86 | def self.check_pdu(pdu, content) 87 | messages = [] 88 | pdu = pdu.to_s 89 | unless pdu =~ /\A[A-Z][^ ]+\z/ 90 | fail 'BadPDU' 91 | end 92 | content.force_encoding('BINARY') 93 | 94 | x, der, _e = x509helper("-c -p #{pdu} -oder -", content) 95 | if x == 0 96 | der.force_encoding('BINARY') 97 | unless der == content 98 | messages << "W: NotDER in #{pdu}" 99 | end 100 | else 101 | messages << "F: ASN.1 Error in #{pdu}" 102 | return messages # ASN.1 error is fatal 103 | end 104 | 105 | # Check strings for things that asn1c does not cover in constraints 106 | # This includes: 107 | # - Null bytes 108 | # - Escape sequences in restricted character strings 109 | begin 110 | OpenSSL::ASN1.traverse(der) do |_depth, offset, header_len, length, _constructed, tag_class, tag| 111 | start_c = offset + header_len 112 | end_c = start_c + length 113 | value = der[start_c..end_c - 1] 114 | if (tag_class == :UNIVERSAL) && (tag == 12) # UTF8String 115 | unless value.force_encoding('UTF-8').valid_encoding? 116 | messages << "F: Incorrectly encoded UTF8String in #{pdu}"# at offset #{offset}" 117 | end 118 | if value.bytes.include? 0 119 | messages << "E: Null byte found in UTF8String in #{pdu}"# at offset #{offset}" 120 | end 121 | elsif (tag_class == :UNIVERSAL) && ([22, 26].include? tag) 122 | # IA5, Visible 123 | if value.bytes.any? { |b| b < 0x20 || b > 0x7E } 124 | messages << "E: Control character found in String in #{pdu}"# at offset #{offset}" 125 | end 126 | elsif (tag_class == :UNIVERSAL) && ([20, 21, 25, 27].include? tag) 127 | # Teletex, Videotex, Graphic, General String 128 | if value.bytes.include? 0 129 | messages << "E: Null byte found in String in #{pdu}"# at offset #{offset}" 130 | end 131 | escape = false 132 | if value.bytes.include? 27 133 | escape = true 134 | messages << "B: Unhandled escape found in String in #{pdu}"# at offset #{offset}" 135 | end 136 | if tag == 20 137 | unless escape || value.force_encoding('BINARY').bytes.all? { |b| (b >= 0x20 && b <= 0x5B) || b == 0x5D || b == 0x5F || (b >= 0x61 && b <= 0x7A) || b == 0x7C } 138 | messages << "E: Incorrectly encoded TeletexString in #{pdu}"# at offset #{offset}" 139 | end 140 | else 141 | messages << "B: No checks for String type #{tag} in #{pdu}"# at offset #{offset}" 142 | end 143 | end 144 | end 145 | rescue OpenSSL::ASN1::ASN1Error => e 146 | messages << "F: ASN.1 Error during traverse: #{e.message} in #{pdu}" 147 | return messages # ASN.1 error is fatal 148 | rescue TypeError => e 149 | # OpenSSL throws an error for certain GeneralTimes 150 | # that it cannot parse (they are valid ASN.1) 151 | messages << "F: Type Error during traverse: #{e.message} in #{pdu}" 152 | return messages # ASN.1 error is fatal 153 | end 154 | messages 155 | end 156 | 157 | # Takes a SubjectPublicKeyInfo in DER 158 | def self.check_spki(spki_der) 159 | messages = [] 160 | spki = OpenSSL::ASN1.decode(spki_der) 161 | type = spki.value[0].value[0].oid 162 | params = spki.value[0].value[1] # May be nil, as is optional 163 | key_der = spki.value[1].value 164 | 165 | case type 166 | when '1.2.840.113549.1.1.1' # RSA 167 | # parameters field MUST have ASN.1 type NULL 168 | # public key MUST be encoded using the ASN.1 type RSAPublicKey 169 | if params.nil? 170 | messages << 'E: RSA keys must have a parameter specified' 171 | elsif !params.instance_of? OpenSSL::ASN1::Null 172 | messages << 'E: RSA keys must have a null parameter' 173 | end 174 | messages += check_pdu(:RSAPublicKey, key_der) 175 | if messages.any? { |m| m.start_with? 'F:' } 176 | return messages 177 | end 178 | # Section 3.1 of RFC 3447 requires n and e to both be positive 179 | # and e must be in the range 3 .. n-1 180 | rsa_asn = OpenSSL::ASN1.decode(key_der) 181 | positive = 0 182 | if rsa_asn.value[0].value > 0 183 | positive += 1 184 | else 185 | messages << 'E: RSA public key modulus must be positive' 186 | end 187 | if rsa_asn.value[1].value > 0 188 | positive += 1 189 | else 190 | messages << 'E: RSA public key exponent must be positive' 191 | end 192 | # Only run this check if both numbers were positive 193 | if positive == 2 194 | unless (rsa_asn.value[1].value >= 3) && (rsa_asn.value[1].value < rsa_asn.value[0].value) 195 | messages << 'E: RSA public key exponent must be between 3 and n - 1' 196 | end 197 | end 198 | when '1.2.840.10040.4.1' # DSA 199 | # When omitted, the parameters component MUST be omitted 200 | # entirely. If the DSA domain parameters are present, the 201 | # parameters are included using the Dss-Parms structure 202 | unless params.nil? 203 | messages += check_pdu(:'Dss-Parms', params.to_der) 204 | end 205 | messages += check_pdu(:DSAPublicKey, key_der) 206 | when '1.2.840.10046.2.1' # DH 207 | # parameters field have the ASN.1 type DomainParameters 208 | if params.nil? 209 | messages << 'E: DH keys must have parameters' 210 | else 211 | messages += check_pdu(:DomainParameters, params.to_der) 212 | end 213 | messages += check_pdu(:DHPublicKey, key_der) 214 | when '1.2.840.10045.2.1' # EC 215 | # parameters field is EcpkParameters 216 | if params.nil? 217 | messages << 'E: EC keys must have parameters' 218 | else 219 | messages += check_pdu(:EcpkParameters, params.to_der) 220 | end 221 | # EC keys are stored slightly oddly 222 | # They are raw mapped to the BIT STRING 223 | # rather than having their DER put into the 224 | # bit string; they native are an OctetString 225 | # This check is fairly pointless, but here for 226 | # consistency 227 | k = OpenSSL::ASN1::OctetString.new('key_der') 228 | messages += check_pdu(:ECPoint, k.to_der) 229 | begin 230 | okey = OpenSSL::PKey::EC.new(spki_der) 231 | rescue ArgumentError => e 232 | messages << "E: EC public key #{e.message}" 233 | end 234 | if !okey.nil? && okey.public_key.infinity? 235 | messages << 'E: EC Public key is infinity' 236 | end 237 | if !okey.nil? && !okey.public_key.on_curve? 238 | messages << 'E: EC Public key is not on curve' 239 | end 240 | else 241 | messages << 'W: Unknown public key type' 242 | end 243 | messages 244 | end 245 | 246 | def self.lint(der) 247 | messages = [] 248 | # First, check overall ASN.1 encoding and details that are not 249 | # visible once parsed into a certificate object 250 | messages += check_pdu(:Certificate, der) 251 | 252 | # Ensure that we bail on fatal errors 253 | if messages.any? { |m| m.start_with? 'F:' } 254 | return messages 255 | end 256 | 257 | # Check time fields 258 | OpenSSL::ASN1.traverse(der) do |_depth, offset, header_len, length, _constructed, tag_class, tag| 259 | start_c = offset + header_len 260 | end_c = start_c + length 261 | value = der[start_c..end_c - 1] 262 | if (tag_class == :UNIVERSAL) && (tag == 23) # UTCTimee 263 | # RFC 5280 4.1.2.5: times must be in Z (GMT) 264 | unless value =~ /Z\z/ 265 | messages << 'E: Time not in Zulu/GMT' 266 | end 267 | if (value[0..1] >= '50') && (value[0..1] < '69') 268 | # Ruby uses (x < 69)?2000:1900, but 269 | # RFC 5280 says (x < 50)?2000:1900 270 | messages << 'N: Ruby may incorrectly interpret UTCTimes between 1950 and 1969' 271 | end 272 | # RFC 5280 4.1.2.5.1: UTCTime MUST include seconds, even when 00 273 | if value !~ /\A([0-9]{2})([01][0-9])([0-3][0-9])([012][0-9])([0-5][0-9]){2}Z\z/ 274 | messages << 'E: UTCTime without seconds' 275 | end 276 | elsif (tag_class == :UNIVERSAL) && (tag == 24) # Generalized Time 277 | # RFC 5280 4.1.2.5: times must be in Z (GMT) 278 | unless value =~ /Z\z/ 279 | messages << 'E: Time not in Zulu/GMT' 280 | end 281 | if value[0..3] < '2050' 282 | messages << 'E: Generalized Time before 2050' 283 | end 284 | if value !~ /\A([0-9]{4})([01][0-9])([0-3][0-9])([012][0-9])([0-5][0-9]){2}Z\z/ 285 | messages << 'E: Generalized Time without seconds or with fractional seconds' 286 | end 287 | end 288 | end 289 | 290 | begin 291 | asn = OpenSSL::ASN1.decode(der) 292 | rescue OpenSSL::ASN1::ASN1Error 293 | messages << 'E: Certificate ASN.1 is broken' 294 | return messages 295 | end 296 | # tbsCertificate.version is optional, so we don't have a fixed 297 | # offset. Check if the first item is a pure ASN1Data, which 298 | # is a strong hint that it is an EXPLICIT wrapper for the first 299 | # element in the struct. If so, this is the version, so everything 300 | # is offset by one. 301 | skip = 0 302 | if asn.value[0].value[0].instance_of? OpenSSL::ASN1::ASN1Data 303 | skip = 1 304 | end 305 | tbs_sign_alg = asn.value[0].value[1 + skip].to_der 306 | # The Certificate sequence always has three members, so no 307 | # need to use find or other heuristics 308 | cert_sign_alg = asn.value[1].to_der 309 | if tbs_sign_alg != cert_sign_alg 310 | messages << 'E: Certificate signature algorithm does not match TBS signature algorithm' 311 | end 312 | sig_oid = asn.value[1].value[0].oid 313 | sig_type = SIG_STRUCTS[sig_oid] 314 | sig_params = asn.value[1].value[1] 315 | case sig_type 316 | when nil 317 | messages << "W: Certificate signature algorithm type is unknown: #{sig_oid}" 318 | when :pss 319 | messages << 'I: No checks for PSS yet' 320 | when :rsa 321 | if sig_params.nil? 322 | messages << 'E: RSA signatures must have a parameter specified' 323 | elsif !sig_params.instance_of? OpenSSL::ASN1::Null 324 | messages << 'E: RSA signatures must have a null parameter' 325 | end 326 | when :dsa 327 | unless sig_params.nil? 328 | messages << 'E: DSA signatures must not have a parameter specified' 329 | end 330 | messages += check_pdu(:'Dss-Sig-Value', asn.value[2].value) 331 | when :ecdsa 332 | unless sig_params.nil? 333 | messages << 'E: ECDSA signatures must not have a parameter specified' 334 | end 335 | messages += check_pdu(:'ECDSA-Sig-Value', asn.value[2].value) 336 | else 337 | fail 'Unknown signature type' 338 | end 339 | 340 | # Check the SubjectPublicKeyInfo 341 | messages += check_spki(asn.value[0].value[5 + skip].to_der) 342 | 343 | cert = OpenSSL::X509::Certificate.new(der) 344 | 345 | if cert.version > 2 346 | messages << 'E: Invalid certificate version' 347 | elsif cert.version < 2 348 | messages << 'E: Old certificate version (not X.509v3)' 349 | end 350 | 351 | if cert.serial.to_s =~ /^-/ 352 | messages << 'E: Negative serial number' 353 | elsif cert.serial.zero? 354 | messages << 'E: Serial number must be positive' 355 | end 356 | if cert.serial.num_bytes > 20 357 | messages << 'E: Serial numbers must be 20 octets or less' 358 | end 359 | 360 | ## Note: No checking of Issuer Name, as the most important 361 | # requirement is that it be exactly the same bytes the subject 362 | # of the previous cert in the chain to ensure chaining works. 363 | # Lint that cert if you want to check this Issuer Name. 364 | 365 | if cert.not_after < cert.not_before 366 | messages << 'E: Certificate has negative validity length' 367 | end 368 | 369 | m = NameLint.lint(cert.subject) 370 | unless m.nil? 371 | messages += m 372 | end 373 | 374 | # CAs conforming to this profile MUST NOT generate certificates with unique identifiers. (4.1.2.8) 375 | if asn.value[0].value.any? { |el| el.tag_class == :CONTEXT_SPECIFIC && el.tag == 1 } 376 | messages << 'E: issuerUniqueID is included' 377 | end 378 | if asn.value[0].value.any? { |el| el.tag_class == :CONTEXT_SPECIFIC && el.tag == 2 } 379 | messages << 'E: subjectUniqueID is included' 380 | end 381 | 382 | ext_list = [] 383 | 384 | # Track basic constraints and keyUsage to check X.509 8.2.2.3 385 | bc = nil 386 | ku = nil 387 | 388 | first = true 389 | cert.extensions.each do |ext| 390 | # Do a little dance to get extension object string (der) 391 | e = OpenSSL::ASN1.decode(ext.to_der).value 392 | oid = e.first.oid 393 | 394 | if first 395 | if oid == '2.5.29.17' # SubjectAltName 396 | messages << 'N: Some python versions will not see SAN extension if it is the first extension' 397 | end 398 | first = false 399 | end 400 | 401 | if ext_list.include? oid 402 | messages << "E: Duplicate extension #{oid}" 403 | end 404 | ext_list << oid 405 | # if critical, e[1] is true and e[2] is octet string; otherwise e[1] is octet string 406 | # so use .last to make it universal 407 | extder = e.last 408 | 409 | # Critical has a default value of false, so it should not be encoded in DER 410 | # Double check just to make sure 411 | if e.length == 3 412 | critical = e[1].value 413 | unless critical 414 | messages << "E: #{oid} has critical:FALSE explicitly encoded" 415 | end 416 | else 417 | critical = false 418 | end 419 | messages += CertExtLint.lint(oid, extder.value, cert, critical) 420 | 421 | if oid == '2.5.29.19' # basicConstraints 422 | bc = ext.value 423 | elsif oid == '2.5.29.15' # keyUsage 424 | ku = ext.value 425 | end 426 | end 427 | 428 | # X.509 8.2.2.3 says if keyCertSign is set, then CA:TRUE must be present 429 | if !ku.nil? && ku.split(',').any? { |s| s.strip == 'Certificate Sign' } 430 | if bc.nil? || !(bc.include? 'CA:TRUE') 431 | messages << 'E: keyCertSign without CA:TRUE' 432 | end 433 | end 434 | # RFC 5280 4.2.1.3 435 | # Conforming CAs MUST include this extension in certificates that 436 | # contain public keys that are used to validate digital signatures on 437 | # other public key certificates or CRLs. 438 | if !bc.nil? && (bc.include? 'CA:TRUE') 439 | if ku.nil? || !ku.split(',').any? { |s| s.strip == 'Certificate Sign' } 440 | messages << 'E: CA:TRUE without keyCertSign' 441 | end 442 | end 443 | messages 444 | end 445 | end 446 | 447 | if __FILE__ == $PROGRAM_NAME 448 | fn = File.basename(ARGV[0]) 449 | raw = File.read(ARGV[0]) 450 | if raw.include? '-BEGIN CERTIFICATE-' 451 | puts 'PEM!!!' 452 | exit 1 453 | end 454 | der = raw 455 | 456 | m = CertLint.lint(der) 457 | m.each do |msg| 458 | puts "#{msg}\t#{fn}" 459 | end 460 | end 461 | -------------------------------------------------------------------------------- /lib/certlint/dn_attrs.rb: -------------------------------------------------------------------------------- 1 | module CertLint 2 | module DNAttrs 3 | ATTRS = { 4 | '0.9.2342.19200300.100.1.1' => 'userId', 5 | '0.9.2342.19200300.100.1.2' => 'textEncodedORAddress', 6 | '0.9.2342.19200300.100.1.3' => 'mail', 7 | '0.9.2342.19200300.100.1.4' => 'info', 8 | '0.9.2342.19200300.100.1.5' => 'drink', 9 | '0.9.2342.19200300.100.1.6' => 'roomNumber', 10 | '0.9.2342.19200300.100.1.7' => 'photo', 11 | '0.9.2342.19200300.100.1.8' => 'userClass', 12 | '0.9.2342.19200300.100.1.9' => 'host', 13 | '0.9.2342.19200300.100.1.10' => 'manager', 14 | '0.9.2342.19200300.100.1.11' => 'documentIdentifier', 15 | '0.9.2342.19200300.100.1.12' => 'documentTitle', 16 | '0.9.2342.19200300.100.1.13' => 'documentVersion', 17 | '0.9.2342.19200300.100.1.14' => 'documentAuthor', 18 | '0.9.2342.19200300.100.1.15' => 'documentLocation', 19 | '0.9.2342.19200300.100.1.20' => 'homePhone', 20 | '0.9.2342.19200300.100.1.21' => 'secretary', 21 | '0.9.2342.19200300.100.1.22' => 'otherMailbox', 22 | '0.9.2342.19200300.100.1.23' => 'lastModifiedTime', 23 | '0.9.2342.19200300.100.1.24' => 'lastModifiedBy', 24 | '0.9.2342.19200300.100.1.25' => 'domainComponent', 25 | '0.9.2342.19200300.100.1.26' => 'aRecord', 26 | '0.9.2342.19200300.100.1.27' => 'mDRecord', 27 | '0.9.2342.19200300.100.1.28' => 'mXRecord', 28 | '0.9.2342.19200300.100.1.29' => 'nSRecord', 29 | '0.9.2342.19200300.100.1.30' => 'sOARecord', 30 | '0.9.2342.19200300.100.1.31' => 'cNAMERecord', 31 | '0.9.2342.19200300.100.1.37' => 'associatedDomain', 32 | '0.9.2342.19200300.100.1.38' => 'associatedName', 33 | '0.9.2342.19200300.100.1.39' => 'homePostalAddress', 34 | '0.9.2342.19200300.100.1.40' => 'personalTitle', 35 | '0.9.2342.19200300.100.1.41' => 'mobile', 36 | '0.9.2342.19200300.100.1.42' => 'pager', 37 | '0.9.2342.19200300.100.1.43' => 'co', 38 | '0.9.2342.19200300.100.1.44' => 'uniqueIdentifier', 39 | '0.9.2342.19200300.100.1.45' => 'organizationalStatus', 40 | '0.9.2342.19200300.100.1.46' => 'janetMailbox', 41 | '0.9.2342.19200300.100.1.47' => 'mailPreferenceOption', 42 | '0.9.2342.19200300.100.1.48' => 'buildingName', 43 | '0.9.2342.19200300.100.1.49' => 'dSAQuality', 44 | '0.9.2342.19200300.100.1.50' => 'singleLevelQuality', 45 | '0.9.2342.19200300.100.1.51' => 'subtreeMinimumQuality', 46 | '0.9.2342.19200300.100.1.52' => 'subtreeMaximumQuality', 47 | '0.9.2342.19200300.100.1.53' => 'personalSignature', 48 | '0.9.2342.19200300.100.1.54' => 'dITRedirect', 49 | '0.9.2342.19200300.100.1.55' => 'audio', 50 | '0.9.2342.19200300.100.1.56' => 'documentPublisher', 51 | '0.9.2342.19200300.100.1.60' => 'jpegPhoto', 52 | '1.2.840.113549.1.9.1' => 'emailAddress', 53 | '1.2.840.113556.1.4.478' => 'calCalURI', 54 | '1.2.840.113556.1.4.479' => 'calFBURL', 55 | '1.2.840.113556.1.4.480' => 'calCAPURI', 56 | '1.2.840.113556.1.4.481' => 'calCalAdrURI', 57 | '1.2.840.113556.1.4.482' => 'calOtherCalURIs', 58 | '1.2.840.113556.1.4.483' => 'calOtherFBURLs', 59 | '1.2.840.113556.1.4.484' => 'calOtherCAPURIs', 60 | '1.2.840.113556.1.4.485' => 'calOtherCalAdrURIs', 61 | '1.3.6.1.1.6.2.3' => 'pcimKeywords', 62 | '1.3.6.1.1.6.2.4' => 'pcimGroupName', 63 | '1.3.6.1.1.6.2.5' => 'pcimRuleName', 64 | '1.3.6.1.1.6.2.6' => 'pcimRuleEnabled', 65 | '1.3.6.1.1.6.2.7' => 'pcimRuleConditionListType', 66 | '1.3.6.1.1.6.2.8' => 'pcimRuleConditionList', 67 | '1.3.6.1.1.6.2.9' => 'pcimRuleActionList', 68 | '1.3.6.1.1.6.2.10' => 'pcimRuleValidityPeriodList', 69 | '1.3.6.1.1.6.2.11' => 'pcimRuleUsage', 70 | '1.3.6.1.1.6.2.12' => 'pcimRulePriority', 71 | '1.3.6.1.1.6.2.13' => 'pcimRuleMandatory', 72 | '1.3.6.1.1.6.2.14' => 'pcimRuleSequencedActions', 73 | '1.3.6.1.1.6.2.15' => 'pcimRoles', 74 | '1.3.6.1.1.6.2.16' => 'pcimConditionGroupNumber', 75 | '1.3.6.1.1.6.2.17' => 'pcimConditionNegated', 76 | '1.3.6.1.1.6.2.18' => 'pcimConditionName', 77 | '1.3.6.1.1.6.2.19' => 'pcimConditionDN', 78 | '1.3.6.1.1.6.2.20' => 'pcimValidityConditionName', 79 | '1.3.6.1.1.6.2.21' => 'pcimTimePeriodConditionDN', 80 | '1.3.6.1.1.6.2.22' => 'pcimActionName', 81 | '1.3.6.1.1.6.2.23' => 'pcimActionOrder', 82 | '1.3.6.1.1.6.2.24' => 'pcimActionDN', 83 | '1.3.6.1.1.6.2.25' => 'pcimTPCTime', 84 | '1.3.6.1.1.6.2.26' => 'pcimTPCMonthOfYearMask', 85 | '1.3.6.1.1.6.2.27' => 'pcimTPCDayOfMonthMask', 86 | '1.3.6.1.1.6.2.28' => 'pcimTPCDayOfWeekMask', 87 | '1.3.6.1.1.6.2.29' => 'pcimTPCTimeOfDayMask', 88 | '1.3.6.1.1.6.2.30' => 'pcimTPCLocalOrUtcTime', 89 | '1.3.6.1.1.6.2.31' => 'pcimVendorConstraintData', 90 | '1.3.6.1.1.6.2.32' => 'pcimVendorConstraintEncoding', 91 | '1.3.6.1.1.6.2.33' => 'pcimVendorActionData', 92 | '1.3.6.1.1.6.2.34' => 'pcimVendorActionEncoding', 93 | '1.3.6.1.1.6.2.35' => 'pcimPolicyInstanceName', 94 | '1.3.6.1.1.6.2.36' => 'pcimRepositoryName', 95 | '1.3.6.1.1.6.2.37' => 'pcimSubtreesAuxContainedSet', 96 | '1.3.6.1.1.6.2.38' => 'pcimGroupsAuxContainedSet', 97 | '1.3.6.1.1.6.2.39' => 'pcimRulesAuxContainedSet', 98 | '1.3.6.1.1.9.2.1' => 'pcelsPolicySetName', 99 | '1.3.6.1.1.9.2.2' => 'pcelsDecisionStrategy', 100 | '1.3.6.1.1.9.2.3' => 'pcelsPolicySetList', 101 | '1.3.6.1.1.9.2.4' => 'pcelsPriority', 102 | '1.3.6.1.1.9.2.5' => 'pcelsPolicySetDN', 103 | '1.3.6.1.1.9.2.6' => 'pcelsConditionListType', 104 | '1.3.6.1.1.9.2.7' => 'pcelsConditionList', 105 | '1.3.6.1.1.9.2.8' => 'pcelsActionList', 106 | '1.3.6.1.1.9.2.9' => 'pcelsSequencedActions', 107 | '1.3.6.1.1.9.2.10' => 'pcelsExecutionStrategy', 108 | '1.3.6.1.1.9.2.11' => 'pcelsVariableDN', 109 | '1.3.6.1.1.9.2.12' => 'pcelsValueDN', 110 | '1.3.6.1.1.9.2.13' => 'pcelsIsMirrored', 111 | '1.3.6.1.1.9.2.14' => 'pcelsVariableName', 112 | '1.3.6.1.1.9.2.15' => 'pcelsExpectedValueList', 113 | '1.3.6.1.1.9.2.16' => 'pcelsVariableModelClass', 114 | '1.3.6.1.1.9.2.17' => 'pcelsVariableModelProperty', 115 | '1.3.6.1.1.9.2.18' => 'pcelsExpectedValueTypes', 116 | '1.3.6.1.1.9.2.19' => 'pcelsValueName', 117 | '1.3.6.1.1.9.2.20' => 'pcelsIPv4AddrList', 118 | '1.3.6.1.1.9.2.21' => 'pcelsIPv6AddrList', 119 | '1.3.6.1.1.9.2.22' => 'pcelsMACAddrList', 120 | '1.3.6.1.1.9.2.23' => 'pcelsStringList', 121 | '1.3.6.1.1.9.2.24' => 'pcelsBitStringList', 122 | '1.3.6.1.1.9.2.25' => 'pcelsIntegerList', 123 | '1.3.6.1.1.9.2.26' => 'pcelsBoolean', 124 | '1.3.6.1.1.9.2.27' => 'pcelsReusableContainerName', 125 | '1.3.6.1.1.9.2.28' => 'pcelsReusableContainerList', 126 | '1.3.6.1.1.9.2.29' => 'pcelsRole', 127 | '1.3.6.1.1.9.2.30' => 'pcelsRoleCollectionName', 128 | '1.3.6.1.1.9.2.31' => 'pcelsElementList', 129 | '1.3.6.1.1.9.2.32' => 'pcelsFilterName', 130 | '1.3.6.1.1.9.2.33' => 'pcelsFilterIsNegated', 131 | '1.3.6.1.1.9.2.34' => 'pcelsIPHdrVersion', 132 | '1.3.6.1.1.9.2.35' => 'pcelsIPHdrSourceAddress', 133 | '1.3.6.1.1.9.2.36' => 'pcelsIPHdrSourceAddressEndOfRange', 134 | '1.3.6.1.1.9.2.37' => 'pcelsIPHdrSourceMask', 135 | '1.3.6.1.1.9.2.38' => 'pcelsIPHdrDestAddress', 136 | '1.3.6.1.1.9.2.39' => 'pcelsIPHdrDestAddressEndOfRange', 137 | '1.3.6.1.1.9.2.40' => 'pcelsIPHdrDestMask', 138 | '1.3.6.1.1.9.2.41' => 'pcelsIPHdrProtocolID', 139 | '1.3.6.1.1.9.2.42' => 'pcelsIPHdrSourcePortStart', 140 | '1.3.6.1.1.9.2.43' => 'pcelsIPHdrSourcePortEnd', 141 | '1.3.6.1.1.9.2.44' => 'pcelsIPHdrDestPortStart', 142 | '1.3.6.1.1.9.2.45' => 'pcelsIPHdrDestPortEnd', 143 | '1.3.6.1.1.9.2.46' => 'pcelsIPHdrDSCPList', 144 | '1.3.6.1.1.9.2.47' => 'pcelsIPHdrFlowLabel', 145 | '1.3.6.1.1.9.2.48' => 'pcels8021HdrSourceMACAddress', 146 | '1.3.6.1.1.9.2.49' => 'pcels8021HdrSourceMACMask', 147 | '1.3.6.1.1.9.2.50' => 'pcels8021HdrDestMACAddress', 148 | '1.3.6.1.1.9.2.51' => 'pcels8021HdrDestMACMask', 149 | '1.3.6.1.1.9.2.52' => 'pcels8021HdrProtocolID', 150 | '1.3.6.1.1.9.2.53' => 'pcels8021HdrPriority', 151 | '1.3.6.1.1.9.2.54' => 'pcels8021HdrVLANID', 152 | '1.3.6.1.1.9.2.55' => 'pcelsFilterListName', 153 | '1.3.6.1.1.9.2.56' => 'pcelsFilterDirection', 154 | '1.3.6.1.1.9.2.57' => 'pcelsFilterEntryList', 155 | '1.3.6.1.1.9.2.58' => 'pcelsVendorVariableData', 156 | '1.3.6.1.1.9.2.59' => 'pcelsVendorVariableEncoding', 157 | '1.3.6.1.1.9.2.60' => 'pcelsVendorValueData', 158 | '1.3.6.1.1.9.2.61' => 'pcelsVendorValueEncoding', 159 | '1.3.6.1.1.9.2.62' => 'pcelsRuleValidityPeriodList', 160 | '1.3.6.1.1.10.4.1' => 'uddiBusinessKey', 161 | '1.3.6.1.1.10.4.2' => 'uddiAuthorizedName', 162 | '1.3.6.1.1.10.4.3' => 'uddiOperator', 163 | '1.3.6.1.1.10.4.4' => 'uddiName', 164 | '1.3.6.1.1.10.4.5' => 'uddiDescription', 165 | '1.3.6.1.1.10.4.6' => 'uddiDiscoveryURLs', 166 | '1.3.6.1.1.10.4.7' => 'uddiUseType', 167 | '1.3.6.1.1.10.4.8' => 'uddiPersonName', 168 | '1.3.6.1.1.10.4.9' => 'uddiPhone', 169 | '1.3.6.1.1.10.4.10' => 'uddiEMail', 170 | '1.3.6.1.1.10.4.11' => 'uddiSortCode', 171 | '1.3.6.1.1.10.4.12' => 'uddiTModelKey', 172 | '1.3.6.1.1.10.4.13' => 'uddiAddressLine', 173 | '1.3.6.1.1.10.4.14' => 'uddiIdentifierBag', 174 | '1.3.6.1.1.10.4.15' => 'uddiCategoryBag', 175 | '1.3.6.1.1.10.4.16' => 'uddiKeyedReference', 176 | '1.3.6.1.1.10.4.17' => 'uddiServiceKey', 177 | '1.3.6.1.1.10.4.18' => 'uddiBindingKey', 178 | '1.3.6.1.1.10.4.19' => 'uddiAccessPoint', 179 | '1.3.6.1.1.10.4.20' => 'uddiHostingRedirector', 180 | '1.3.6.1.1.10.4.21' => 'uddiInstanceDescription', 181 | '1.3.6.1.1.10.4.22' => 'uddiInstanceParms', 182 | '1.3.6.1.1.10.4.23' => 'uddiOverviewDescription', 183 | '1.3.6.1.1.10.4.24' => 'uddiOverviewURL', 184 | '1.3.6.1.1.10.4.25' => 'uddiFromKey', 185 | '1.3.6.1.1.10.4.26' => 'uddiToKey', 186 | '1.3.6.1.1.10.4.27' => 'uddiUUID', 187 | '1.3.6.1.1.10.4.28' => 'uddiIsHidden', 188 | '1.3.6.1.1.10.4.29' => 'uddiIsProjection', 189 | '1.3.6.1.1.10.4.30' => 'uddiLang', 190 | '1.3.6.1.1.10.4.31' => 'uddiv3BusinessKey', 191 | '1.3.6.1.1.10.4.32' => 'uddiv3ServiceKey', 192 | '1.3.6.1.1.10.4.33' => 'uddiv3BindingKey', 193 | '1.3.6.1.1.10.4.34' => 'uddiv3TmodelKey', 194 | '1.3.6.1.1.10.4.35' => 'uddiv3DigitalSignature', 195 | '1.3.6.1.1.10.4.36' => 'uddiv3NodeId', 196 | '1.3.6.1.1.10.4.37' => 'uddiv3EntityModificationTime', 197 | '1.3.6.1.1.10.4.38' => 'uddiv3SubscriptionKey', 198 | '1.3.6.1.1.10.4.39' => 'uddiv3SubscriptionFilter', 199 | '1.3.6.1.1.10.4.40' => 'uddiv3NotificationInterval', 200 | '1.3.6.1.1.10.4.41' => 'uddiv3MaxEntities', 201 | '1.3.6.1.1.10.4.42' => 'uddiv3ExpiresAfter', 202 | '1.3.6.1.1.10.4.43' => 'uddiv3BriefResponse', 203 | '1.3.6.1.1.10.4.44' => 'uddiv3EntityKey', 204 | '1.3.6.1.1.10.4.45' => 'uddiv3EntityCreationTime', 205 | '1.3.6.1.1.10.4.46' => 'uddiv3EntityDeletionTime', 206 | '1.3.6.1.1.11.2.1' => 'vPIMTelephoneNumber', 207 | '1.3.6.1.1.11.2.2' => 'vPIMRfc822Mailbox', 208 | '1.3.6.1.1.11.2.3' => 'vPIMSpokenName', 209 | '1.3.6.1.1.11.2.4' => 'vPIMSupportedUABehaviors', 210 | '1.3.6.1.1.11.2.5' => 'vPIMSupportedAudioMediaTypes', 211 | '1.3.6.1.1.11.2.6' => 'vPIMSupportedMessageContext', 212 | '1.3.6.1.1.11.2.7' => 'vPIMTextName', 213 | '1.3.6.1.1.11.2.8' => 'vPIMExtendedAbsenceStatus', 214 | '1.3.6.1.1.11.2.9' => 'vPIMMaxMessageSize', 215 | '1.3.6.1.1.11.2.10' => 'vPIMSubMailboxes', 216 | '1.3.6.1.1.16.4' => 'entryUUID', 217 | '1.3.6.1.1.20' => 'entryDN', 218 | '1.3.6.1.4.1.11.1.3.1.1.0' => 'defaultServerList', 219 | '1.3.6.1.4.1.11.1.3.1.1.1' => 'defaultSearchBase', 220 | '1.3.6.1.4.1.11.1.3.1.1.2' => 'preferredServerList', 221 | '1.3.6.1.4.1.11.1.3.1.1.3' => 'searchTimeLimit', 222 | '1.3.6.1.4.1.11.1.3.1.1.4' => 'bindTimeLimit', 223 | '1.3.6.1.4.1.11.1.3.1.1.5' => 'followReferrals', 224 | '1.3.6.1.4.1.11.1.3.1.1.6' => 'authenticationMethod', 225 | '1.3.6.1.4.1.11.1.3.1.1.7' => 'profileTTL', 226 | '1.3.6.1.4.1.11.1.3.1.1.9' => 'attributeMap', 227 | '1.3.6.1.4.1.11.1.3.1.1.10' => 'credentialLevel', 228 | '1.3.6.1.4.1.11.1.3.1.1.11' => 'objectclassMap', 229 | '1.3.6.1.4.1.11.1.3.1.1.12' => 'defaultSearchScope', 230 | '1.3.6.1.4.1.11.1.3.1.1.13' => 'serviceCredentialLevel', 231 | '1.3.6.1.4.1.11.1.3.1.1.14' => 'serviceSearchDescriptor', 232 | '1.3.6.1.4.1.11.1.3.1.1.15' => 'serviceAuthenticationMethod', 233 | '1.3.6.1.4.1.11.1.3.1.1.16' => 'dereferenceAliases', 234 | '1.3.6.1.4.1.250.1.57' => 'labeledURI', 235 | '1.3.6.1.4.1.311.60.2.1.1' => 'jurisdictionLocalityName', 236 | '1.3.6.1.4.1.311.60.2.1.2' => 'jurisdictionStateOrProvinceName', 237 | '1.3.6.1.4.1.311.60.2.1.3' => 'jurisdictionCountryName', 238 | '1.3.6.1.4.1.453.7.2.1' => 'textTableKey', 239 | '1.3.6.1.4.1.453.7.2.2' => 'textTableValue', 240 | '1.3.6.1.4.1.453.7.2.3' => 'distinguishedNameTableKey', 241 | '1.3.6.1.4.1.453.7.2.6' => 'associatedORAddress', 242 | '1.3.6.1.4.1.453.7.2.7' => 'oRAddressComponentType', 243 | '1.3.6.1.4.1.453.7.2.8' => 'associatedInternetGateway', 244 | '1.3.6.1.4.1.453.7.2.9' => 'mcgamTables', 245 | '1.3.6.1.4.1.1466.101.119.3' => 'entryTtl', 246 | '1.3.6.1.4.1.1466.101.119.4' => 'dynamicSubtrees', 247 | '1.3.6.1.4.1.1466.101.120.1' => 'administratorsAddress', 248 | '1.3.6.1.4.1.1466.101.120.5' => 'namingContexts', 249 | '1.3.6.1.4.1.1466.101.120.6' => 'altServer', 250 | '1.3.6.1.4.1.1466.101.120.7' => 'supportedExtension', 251 | '1.3.6.1.4.1.1466.101.120.13' => 'supportedControl', 252 | '1.3.6.1.4.1.1466.101.120.14' => 'supportedSASLMechanisms', 253 | '1.3.6.1.4.1.1466.101.120.15' => 'supportedLDAPVersion', 254 | '1.3.6.1.4.1.1466.101.120.16' => 'ldapSyntaxes', 255 | '1.3.6.1.4.1.4203.1.3.5' => 'supportedFeatures', 256 | '1.3.6.1.4.1.16572.2.2.1' => 'providerCertificateHash', 257 | '1.3.6.1.4.1.16572.2.2.2' => 'providerCertificate', 258 | '1.3.6.1.4.1.16572.2.2.3' => 'providerName', 259 | '1.3.6.1.4.1.16572.2.2.4' => 'mailReceipt', 260 | '1.3.6.1.4.1.16572.2.2.5' => 'managedDomains', 261 | '1.3.6.1.4.1.16572.2.2.6' => 'LDIFLocationURL', 262 | '1.3.6.1.4.1.16572.2.2.7' => 'providerUnit', 263 | '1.3.6.1.4.1.31103.1.1' => 'fedfsUuid', 264 | '1.3.6.1.4.1.31103.1.4' => 'fedfsFsnUuid', 265 | '1.3.6.1.4.1.31103.1.8' => 'fedfsFslUuid', 266 | '1.3.6.1.4.1.31103.1.12' => 'fedfsAnnotation', 267 | '1.3.6.1.4.1.31103.1.13' => 'fedfsDescr', 268 | '1.3.6.1.4.1.31103.1.14' => 'fedfsNceDN', 269 | '1.3.6.1.4.1.31103.1.15' => 'fedfsFsnTTL', 270 | '1.3.6.1.4.1.31103.1.103' => 'fedfsNfsCurrency', 271 | '1.3.6.1.4.1.31103.1.104' => 'fedfsNfsGenFlagWritable', 272 | '1.3.6.1.4.1.31103.1.105' => 'fedfsNfsGenFlagGoing', 273 | '1.3.6.1.4.1.31103.1.106' => 'fedfsNfsGenFlagSplit', 274 | '1.3.6.1.4.1.31103.1.107' => 'fedfsNfsTransFlagRdma', 275 | '1.3.6.1.4.1.31103.1.108' => 'fedfsNfsClassSimul', 276 | '1.3.6.1.4.1.31103.1.109' => 'fedfsNfsClassHandle', 277 | '1.3.6.1.4.1.31103.1.110' => 'fedfsNfsClassFileid', 278 | '1.3.6.1.4.1.31103.1.111' => 'fedfsNfsClassWritever', 279 | '1.3.6.1.4.1.31103.1.112' => 'fedfsNfsClassChange', 280 | '1.3.6.1.4.1.31103.1.113' => 'fedfsNfsClassReaddir', 281 | '1.3.6.1.4.1.31103.1.114' => 'fedfsNfsReadRank', 282 | '1.3.6.1.4.1.31103.1.115' => 'fedfsNfsReadOrder', 283 | '1.3.6.1.4.1.31103.1.116' => 'fedfsNfsWriteRank', 284 | '1.3.6.1.4.1.31103.1.117' => 'fedfsNfsWriteOrder', 285 | '1.3.6.1.4.1.31103.1.118' => 'fedfsNfsVarSub', 286 | '1.3.6.1.4.1.31103.1.119' => 'fedfsNfsValidFor', 287 | '1.3.6.1.4.1.31103.1.120' => 'fedfsNfsURI', 288 | '1.3.18.0.2.4.1107' => 'printer-xri-supported', 289 | '1.3.18.0.2.4.1108' => 'printer-aliases', 290 | '1.3.18.0.2.4.1109' => 'printer-charset-configured', 291 | '1.3.18.0.2.4.1110' => 'printer-job-priority-supported', 292 | '1.3.18.0.2.4.1111' => 'printer-job-k-octets-supported', 293 | '1.3.18.0.2.4.1112' => 'printer-current-operator', 294 | '1.3.18.0.2.4.1113' => 'printer-service-person', 295 | '1.3.18.0.2.4.1114' => 'printer-delivery-orientation-supported', 296 | '1.3.18.0.2.4.1115' => 'printer-stacking-order-supported', 297 | '1.3.18.0.2.4.1116' => 'printer-output-features-supported', 298 | '1.3.18.0.2.4.1117' => 'printer-media-local-supported', 299 | '1.3.18.0.2.4.1118' => 'printer-copies-supported', 300 | '1.3.18.0.2.4.1119' => 'printer-natural-language-configured', 301 | '1.3.18.0.2.4.1120' => 'printer-print-quality-supported', 302 | '1.3.18.0.2.4.1121' => 'printer-resolution-supported', 303 | '1.3.18.0.2.4.1122' => 'printer-media-supported', 304 | '1.3.18.0.2.4.1123' => 'printer-sides-supported', 305 | '1.3.18.0.2.4.1124' => 'printer-number-up-supported', 306 | '1.3.18.0.2.4.1125' => 'printer-finishings-supported', 307 | '1.3.18.0.2.4.1126' => 'printer-pages-per-minute-color', 308 | '1.3.18.0.2.4.1127' => 'printer-pages-per-minute', 309 | '1.3.18.0.2.4.1128' => 'printer-compression-supported', 310 | '1.3.18.0.2.4.1129' => 'printer-color-supported', 311 | '1.3.18.0.2.4.1130' => 'printer-document-format-supported', 312 | '1.3.18.0.2.4.1131' => 'printer-charset-supported', 313 | '1.3.18.0.2.4.1132' => 'printer-multiple-document-jobs-supported', 314 | '1.3.18.0.2.4.1133' => 'printer-ipp-versions-supported', 315 | '1.3.18.0.2.4.1134' => 'printer-more-info', 316 | '1.3.18.0.2.4.1135' => 'printer-name', 317 | '1.3.18.0.2.4.1136' => 'printer-location', 318 | '1.3.18.0.2.4.1137' => 'printer-generated-natural-language-supported', 319 | '1.3.18.0.2.4.1138' => 'printer-make-and-model', 320 | '1.3.18.0.2.4.1139' => 'printer-info', 321 | '1.3.18.0.2.4.1140' => 'printer-uri', 322 | '1.3.18.0.2.24.46.1.101' => 'printer-device-id', 323 | '1.3.18.0.2.24.46.1.102' => 'printer-device-service-count', 324 | '1.3.18.0.2.24.46.1.104' => 'printer-uuid', 325 | '1.3.18.0.2.24.46.1.105' => 'printer-charge-info', 326 | '1.3.18.0.2.24.46.1.106' => 'printer-charge-info-uri', 327 | '1.3.18.0.2.24.46.1.107' => 'printer-geo-location', 328 | '1.3.18.0.2.24.46.1.108' => 'printer-ipp-features-supported', 329 | '2.5.4.0' => 'objectClass', 330 | '2.5.4.1' => 'aliasedObjectName', 331 | '2.5.4.2' => 'knowledgeInformation', 332 | '2.5.4.3' => 'commonName', 333 | '2.5.4.4' => 'surname', 334 | '2.5.4.5' => 'serialNumber', 335 | '2.5.4.6' => 'countryName', 336 | '2.5.4.7' => 'localityName', 337 | '2.5.4.7.1' => 'c-l', 338 | '2.5.4.8' => 'stateOrProvinceName', 339 | '2.5.4.8.1' => 'c-st', 340 | '2.5.4.9' => 'streetAddress', 341 | '2.5.4.9.1' => 'c-street', 342 | '2.5.4.10' => 'organizationName', 343 | '2.5.4.10.1' => 'c-o', 344 | '2.5.4.11' => 'organizationalUnitName', 345 | '2.5.4.11.1' => 'c-ou', 346 | '2.5.4.12' => 'title', 347 | '2.5.4.13' => 'description', 348 | '2.5.4.14' => 'searchGuide', 349 | '2.5.4.15' => 'businessCategory', 350 | '2.5.4.16' => 'postalAddress', 351 | '2.5.4.16.1' => 'c-PostalAddress', 352 | '2.5.4.17' => 'postalCode', 353 | '2.5.4.17.1' => 'c-PostalCode', 354 | '2.5.4.18' => 'postOfficeBox', 355 | '2.5.4.18.1' => 'c-PostOfficeBox', 356 | '2.5.4.19' => 'physicalDeliveryOfficeName', 357 | '2.5.4.19.1' => 'c-PhysicalDeliveryOffice', 358 | '2.5.4.20' => 'telephoneNumber', 359 | '2.5.4.20.1' => 'c-TelephoneNumber', 360 | '2.5.4.21' => 'telexNumber', 361 | '2.5.4.21.1' => 'c-TelexNumber', 362 | '2.5.4.22' => 'teletexTerminalIdentifier', 363 | '2.5.4.23' => 'facsimileTelephoneNumber', 364 | '2.5.4.23.1' => 'c-FacsimileTelephoneNumber', 365 | '2.5.4.24' => 'x121Address', 366 | '2.5.4.25' => 'internationaliSDNNumber', 367 | '2.5.4.25.1' => 'c-InternationalISDNNumber', 368 | '2.5.4.26' => 'registeredAddress', 369 | '2.5.4.27' => 'destinationIndicator', 370 | '2.5.4.28' => 'preferredDeliveryMethod', 371 | '2.5.4.29' => 'presentationAddress', 372 | '2.5.4.30' => 'supportedApplicationContext', 373 | '2.5.4.31' => 'member', 374 | '2.5.4.32' => 'owner', 375 | '2.5.4.33' => 'roleOccupant', 376 | '2.5.4.34' => 'seeAlso', 377 | '2.5.4.35' => 'userPassword', 378 | '2.5.4.36' => 'userCertificate', 379 | '2.5.4.37' => 'cACertificate', 380 | '2.5.4.38' => 'authorityRevocationList', 381 | '2.5.4.39' => 'certificateRevocationList', 382 | '2.5.4.40' => 'crossCertificatePair', 383 | '2.5.4.41' => 'name', 384 | '2.5.4.42' => 'givenName', 385 | '2.5.4.43' => 'initials', 386 | '2.5.4.44' => 'generationQualifier', 387 | '2.5.4.45' => 'x500UniqueIdentifier', 388 | '2.5.4.46' => 'dnQualifier', 389 | '2.5.4.47' => 'enhancedSearchGuide', 390 | '2.5.4.48' => 'protocolInformation', 391 | '2.5.4.49' => 'distinguishedName', 392 | '2.5.4.50' => 'uniqueMember', 393 | '2.5.4.51' => 'houseIdentifier', 394 | '2.5.4.52' => 'supportedAlgorithms', 395 | '2.5.4.53' => 'deltaRevocationList', 396 | '2.5.4.54' => 'dmdName', 397 | '2.5.4.65' => 'pseudonym', 398 | '2.5.18.1' => 'createTimestamp', 399 | '2.5.18.2' => 'modifyTimestamp', 400 | '2.5.18.3' => 'creatorsName', 401 | '2.5.18.4' => 'modifiersName', 402 | '2.5.18.5' => 'administrativeRole', 403 | '2.5.18.6' => 'subtreeSpecification', 404 | '2.5.18.7' => 'collectiveExclusions', 405 | '2.5.18.10' => 'subschemaSubentry', 406 | '2.5.18.12' => 'collectiveAttributeSubentries', 407 | '2.5.21.1' => 'dITStructureRules', 408 | '2.5.21.2' => 'dITContentRules', 409 | '2.5.21.4' => 'matchingRules', 410 | '2.5.21.5' => 'attributeTypes', 411 | '2.5.21.6' => 'objectClasses', 412 | '2.5.21.7' => 'nameForms', 413 | '2.5.21.8' => 'matchingRuleUse', 414 | '2.5.21.9' => 'structuralObjectClass', 415 | '2.5.21.10' => 'governingStructureRule', 416 | '2.16.840.1.113730.3.1.34' => 'ref' 417 | } 418 | end 419 | end 420 | -------------------------------------------------------------------------------- /data/ldap-names.csv: -------------------------------------------------------------------------------- 1 | Name,Type,OID,Reference 2 | accessControlInnerArea,R,2.5.23.3,[RFC3672] 3 | accessControlSpecificArea,R,2.5.23.2,[RFC3672] 4 | account,O,0.9.2342.19200300.100.4.5,[RFC4524] 5 | add,A,Reserved for LDIF,[RFC2849] 6 | administrativeRole,A,2.5.18.5,[RFC3672] 7 | administratorsAddress,A,1.3.6.1.4.1.1466.101.120.1,[Mark_Wahl] 8 | algorithmIdentifierMatch,M,2.5.13.40,[RFC4523] 9 | alias,O,2.5.6.1,[RFC4512] 10 | aliasedEntryName,A,2.5.4.1,[X.501] 11 | aliasedObjectName,A,2.5.4.1,[RFC4512] 12 | allComponentsMatch,M,1.2.36.79672281.1.13.6,[RFC3687] 13 | altServer,A,1.3.6.1.4.1.1466.101.120.6,[RFC4512] 14 | applicationEntity,O,2.5.6.12,[RFC2256] 15 | applicationProcess,O,2.5.6.11,[RFC4519] 16 | aRecord,A,0.9.2342.19200300.100.1.26,[RFC1274] 17 | associatedDomain,A,0.9.2342.19200300.100.1.37,[RFC4524] 18 | associatedInternetGateway,A,1.3.6.1.4.1.453.7.2.8,[RFC2164] 19 | associatedName,A,0.9.2342.19200300.100.1.38,[RFC4524] 20 | associatedORAddress,A,1.3.6.1.4.1.453.7.2.6,[RFC2164] 21 | associatedX400Gateway,A,1.3.6.1.4.1.453.7.2.3,[RFC2164] 22 | attributeMap,A,1.3.6.1.4.1.11.1.3.1.1.9,[RFC4876] 23 | attributeTypes,A,2.5.21.5,[RFC4512] 24 | audio,A,0.9.2342.19200300.100.1.55,[RFC1274] 25 | authenticationMethod,A,1.3.6.1.4.1.11.1.3.1.1.6,[RFC4876] 26 | authorityRevocationList,A,2.5.4.38,[RFC4523] 27 | autonomousArea,R,2.5.23.1,[RFC3672] 28 | bindTimeLimit,A,1.3.6.1.4.1.11.1.3.1.1.4,[RFC4876] 29 | bitStringMatch,M,2.5.13.16,[RFC4517] 30 | booleanMatch,M,2.5.13.13,[RFC4517] 31 | buildingName,A,0.9.2342.19200300.100.1.48,[RFC4524] 32 | businessCategory,A,2.5.4.15,[RFC4519] 33 | c,A,2.5.4.6,[RFC4519] 34 | c-FacsimileTelephoneNumber,A,2.5.4.23.1,[RFC3671] 35 | c-InternationalISDNNumber,A,2.5.4.25.1,[RFC3671] 36 | c-l,A,2.5.4.7.1,[RFC3671] 37 | c-PhysicalDeliveryOffice,A,2.5.4.19.1,[RFC3671] 38 | c-PostalAddress,A,2.5.4.16.1,[RFC3671] 39 | c-PostalCode,A,2.5.4.17.1,[RFC3671] 40 | c-PostOfficeBox,A,2.5.4.18.1,[RFC3671] 41 | c-o,A,2.5.4.10.1,[RFC3671] 42 | c-ou,A,2.5.4.11.1,[RFC3671] 43 | c-st,A,2.5.4.8.1,[RFC3671] 44 | c-street,A,2.5.4.9.1,[RFC3671] 45 | c-TelephoneNumber,A,2.5.4.20.1,[RFC3671] 46 | c-TelexNumber,A,2.5.4.21.1,[RFC3671] 47 | cACertificate,A,2.5.4.37,[RFC4523] 48 | calCalAdrURI,A,1.2.840.113556.1.4.481,[RFC2739] 49 | calCalURI,A,1.2.840.113556.1.4.478,[RFC2739] 50 | calCAPURI,A,1.2.840.113556.1.4.480,[RFC2739] 51 | calEntry,O,1.2.840.113556.1.5.87,[RFC2739] 52 | calFBURL,A,1.2.840.113556.1.4.479,[RFC2739] 53 | calOtherCalAdrURIs,A,1.2.840.113556.1.4.485,[RFC2739] 54 | calOtherCalURIs,A,1.2.840.113556.1.4.482,[RFC2739] 55 | calOtherCAPURIs,A,1.2.840.113556.1.4.484,[RFC2739] 56 | calOtherFBURLs,A,1.2.840.113556.1.4.483,[RFC2739] 57 | caseExactIA5Match,M,1.3.6.1.4.1.1466.109.114.1,[RFC4517] 58 | caseExactMatch,M,2.5.13.5,[RFC4517] 59 | caseExactOrderingMatch,M,2.5.13.6,[RFC4517] 60 | caseExactSubstringsMatch,M,2.5.13.7,[RFC4517] 61 | caseIgnoreIA5Match,M,1.3.6.1.4.1.1466.109.114.2,[RFC4517] 62 | caseIgnoreIA5SubstringsMatch,M,1.3.6.1.4.1.1466.109.114.3,[RFC4517] 63 | caseIgnoreListMatch,M,2.5.13.11,[RFC4517] 64 | caseIgnoreListSubstringsMatch,M,2.5.13.12,[RFC4517] 65 | caseIgnoreMatch,M,2.5.13.2,[RFC4517] 66 | caseIgnoreOrderingMatch,M,2.5.13.3,[RFC4517] 67 | caseIgnoreSubstringsMatch,M,2.5.13.4,[RFC4517] 68 | certificateExactMatch,M,2.5.13.34,[RFC4523] 69 | certificateListExactMatch,M,2.5.13.38,[RFC4523] 70 | certificateListMatch,M,2.5.13.39,[RFC4523] 71 | certificateMatch,M,2.5.13.35,[RFC4523] 72 | certificatePairExactMatch,M,2.5.13.36,[RFC4523] 73 | certificatePairMatch,M,2.5.13.37,[RFC4523] 74 | certificateRevocationList,A,2.5.4.39,[RFC4523] 75 | certificationAuthority,O,2.5.6.16,[RFC4523] 76 | certificationAuthority-V2,O,2.5.6.16.2,[RFC4523] 77 | changetype,A,Reserved for LDIF,[RFC2849] 78 | cn,A,2.5.4.3,[RFC4519] 79 | cNAMERecord,A,0.9.2342.19200300.100.1.31,[RFC1274] 80 | co,A,0.9.2342.19200300.100.1.43,[RFC4524] 81 | collectiveAttributeInnerArea,R,2.5.23.6,[RFC3672] 82 | collectiveAttributeSpecificArea,R,2.5.23.5,[RFC3672] 83 | collectiveAttributeSubentries,A,2.5.18.12,[RFC3671] 84 | collectiveAttributeSubentry,O,2.5.20.2,[RFC3671] 85 | collectiveExclusions,A,2.5.18.7,[RFC3671] 86 | commonName,A,2.5.4.3,[RFC4519] 87 | componentFilterMatch,M,1.2.36.79672281.1.13.2,[RFC3687] 88 | control,A,Reserved for LDIF,[RFC2849] 89 | country,O,2.5.6.2,[RFC4519] 90 | countryName,A,2.5.4.6,[RFC4519] 91 | createTimestamp,A,2.5.18.1,[RFC4512] 92 | creatorsName,A,2.5.18.3,[RFC4512] 93 | credentialLevel,A,1.3.6.1.4.1.11.1.3.1.1.10,[RFC4876] 94 | cRLDistributionPoint,O,2.5.6.19,[RFC4523] 95 | crossCertificatePair,A,2.5.4.40,[RFC4523] 96 | DC,A,0.9.2342.19200300.100.1.25,[RFC4519] 97 | dcObject,O,1.3.6.1.4.1.1466.344,[RFC4519] 98 | defaultServerList,A,1.3.6.1.4.1.11.1.3.1.1.0,[RFC4876] 99 | defaultSearchBase,A,1.3.6.1.4.1.11.1.3.1.1.1,[RFC4876] 100 | defaultSearchScope,A,1.3.6.1.4.1.11.1.3.1.1.12,[RFC4876] 101 | delete,A,Reserved for LDIF,[RFC2849] 102 | deleteoldrdn,A,Reserved for LDIF,[RFC2849] 103 | deltaCRL,O,2.5.6.23,[RFC4523] 104 | deltaRevocationList,A,2.5.4.53,[RFC4523] 105 | dereferenceAliases,A,1.3.6.1.4.1.11.1.3.1.1.16,[RFC4876] 106 | description,A,2.5.4.13,[RFC4519] 107 | destinationIndicator,A,2.5.4.27,[RFC4519] 108 | device,O,2.5.6.14,[RFC4519] 109 | directoryComponentsMatch,M,1.2.36.79672281.1.13.7,[RFC3687] 110 | directoryStringFirstComponentMatch,M,2.5.13.31,[RFC4517] 111 | distinguishedName,A,2.5.4.49,[RFC4519] 112 | distinguishedNameMatch,M,2.5.13.1,[RFC4517] 113 | distinguishedNameTableEntry,O,1.3.6.1.4.1.453.7.1.5,[RFC2293] 114 | distinguishedNameTableKey,A,1.3.6.1.4.1.453.7.2.3,[RFC2293] 115 | dITContentRules,A,2.5.21.2,[RFC4512] 116 | dITRedirect,A,0.9.2342.19200300.100.1.54,[RFC1274] 117 | dITStructureRules,A,2.5.21.1,[RFC4512] 118 | dmd,O,2.5.6.20,[RFC2256] 119 | dmdName,A,2.5.4.54,[RFC2256] 120 | dn,A,Reserved for LDIF,[RFC2849] 121 | dnQualifier,A,2.5.4.46,[RFC4519] 122 | dNSDomain,O,0.9.2342.19200300.100.4.15,[RFC1274] 123 | document,O,0.9.2342.19200300.100.4.6,[RFC4524] 124 | documentAuthor,A,0.9.2342.19200300.100.1.14,[RFC4524] 125 | documentIdentifier,A,0.9.2342.19200300.100.1.11,[RFC4524] 126 | documentLocation,A,0.9.2342.19200300.100.1.15,[RFC4524] 127 | documentPublisher,A,0.9.2342.19200300.100.1.56,[RFC4524] 128 | documentSeries,O,0.9.2342.19200300.100.4.8,[RFC4524] 129 | documentTitle,A,0.9.2342.19200300.100.1.12,[RFC4524] 130 | documentVersion,A,0.9.2342.19200300.100.1.13,[RFC4524] 131 | domain,O,0.9.2342.19200300.100.4.13,[RFC4524] 132 | domainComponent,A,0.9.2342.19200300.100.1.25,[RFC4519] 133 | domainNameForm,N,1.3.6.1.4.1.1466.345,[RFC2247] 134 | domainRelatedObject,O,0.9.2342.19200300.100.4.17,[RFC4524] 135 | drink,A,0.9.2342.19200300.100.1.5,[RFC4524] 136 | dSA,O,2.5.6.13,[RFC2256] 137 | dSAQuality,A,0.9.2342.19200300.100.1.49,[RFC1274] 138 | DUAConfigProfile,O,1.3.6.1.4.1.11.1.3.1.2.5,[RFC4876] 139 | dynamicObject,O,1.3.6.1.4.1.1466.101.119.2,[RFC2589] 140 | dynamicSubtrees,A,1.3.6.1.4.1.1466.101.119.4,[RFC2589] 141 | e-com-seafreeze-*,F,N/A,[Allen_Williams] 142 | e-com-westjet-*,F,N/A,[Matthew_Key] 143 | email,A,1.2.840.113549.1.9.1,[RFC3280] 144 | emailAddress,A,1.2.840.113549.1.9.1,[RFC3280] 145 | enhancedSearchGuide,A,2.5.4.47,[RFC4519] 146 | entryDN,A,1.3.6.1.1.20,[RFC5020] 147 | entryTtl,A,1.3.6.1.4.1.1466.101.119.3,[RFC2589] 148 | entryUUID,A,1.3.6.1.1.16.4,[RFC4530] 149 | extensibleObject,O,1.3.6.1.4.1.1466.101.120.111,[RFC4512] 150 | facsimileTelephoneNumber,A,2.5.4.23,[RFC4519] 151 | favouriteDrink,A*,0.9.2342.19200300.100.1.5,[RFC4524] 152 | fedfsAnnotation,A,1.3.6.1.4.1.31103.1.12,[RFC7532] 153 | fedfsDescr,A,1.3.6.1.4.1.31103.1.13,[RFC7532] 154 | fedfsFsl,O,1.3.6.1.4.1.31103.1.1003,[RFC7532] 155 | fedfsFslHost,A*,1.3.6.1.4.1.31103.1.9,[RFC7532] 156 | fedfsFslPort,A*,1.3.6.1.4.1.31103.1.10,[RFC7532] 157 | fedfsFslTTL,A*,1.3.6.1.4.1.31103.1.11,[RFC7532] 158 | fedfsFslUuid,A,1.3.6.1.4.1.31103.1.8,[RFC7532] 159 | fedfsFsn,O,1.3.6.1.4.1.31103.1.1002,[RFC7532] 160 | fedfsFsnTTL,A,1.3.6.1.4.1.31103.1.15,[RFC7532] 161 | fedfsFsnUuid,A,1.3.6.1.4.1.31103.1.4,[RFC7532] 162 | fedfsNceDN,A,1.3.6.1.4.1.31103.1.14,[RFC7532] 163 | fedfsNcePrefix,A*,1.3.6.1.4.1.31103.1.7,[RFC7532] 164 | fedfsNetAddr,A*,1.3.6.1.4.1.31103.1.2,[RFC7532] 165 | fedfsNetPort,A*,1.3.6.1.4.1.31103.1.3,[RFC7532] 166 | fedfsNfsClassChange,A,1.3.6.1.4.1.31103.1.112,[RFC7532] 167 | fedfsNfsClassFileid,A,1.3.6.1.4.1.31103.1.110,[RFC7532] 168 | fedfsNfsClassHandle,A,1.3.6.1.4.1.31103.1.109,[RFC7532] 169 | fedfsNfsClassReaddir,A,1.3.6.1.4.1.31103.1.113,[RFC7532] 170 | fedfsNfsClassSimul,A,1.3.6.1.4.1.31103.1.108,[RFC7532] 171 | fedfsNfsClassWritever,A,1.3.6.1.4.1.31103.1.111,[RFC7532] 172 | fedfsNfsCurrency,A,1.3.6.1.4.1.31103.1.103,[RFC7532] 173 | fedfsNfsFsl,O,1.3.6.1.4.1.31103.1.1004,[RFC7532] 174 | fedfsNfsGenFlagGoing,A,1.3.6.1.4.1.31103.1.105,[RFC7532] 175 | fedfsNfsGenFlagSplit,A,1.3.6.1.4.1.31103.1.106,[RFC7532] 176 | fedfsNfsGenFlagWritable,A,1.3.6.1.4.1.31103.1.104,[RFC7532] 177 | fedfsNfsMajorVer,A*,1.3.6.1.4.1.31103.1.101,[RFC7532] 178 | fedfsNfsMinorVer,A*,1.3.6.1.4.1.31103.1.102,[RFC7532] 179 | fedfsNfsPath,A*,1.3.6.1.4.1.31103.1.100,[RFC7532] 180 | fedfsNfsReadOrder,A,1.3.6.1.4.1.31103.1.115,[RFC7532] 181 | fedfsNfsReadRank,A,1.3.6.1.4.1.31103.1.114,[RFC7532] 182 | fedfsNfsTransFlagRdma,A,1.3.6.1.4.1.31103.1.107,[RFC7532] 183 | fedfsNfsURI,A,1.3.6.1.4.1.31103.1.120,[RFC7532] 184 | fedfsNfsValidFor,A,1.3.6.1.4.1.31103.1.119,[RFC7532] 185 | fedfsNfsVarSub,A,1.3.6.1.4.1.31103.1.118,[RFC7532] 186 | fedfsNfsWriteOrder,A,1.3.6.1.4.1.31103.1.117,[RFC7532] 187 | fedfsNfsWriteRank,A,1.3.6.1.4.1.31103.1.116,[RFC7532] 188 | fedfsNsdbContainerInfo,O,1.3.6.1.4.1.31103.1.1001,[RFC7532] 189 | fedfsNsdbName,A*,1.3.6.1.4.1.31103.1.5,[RFC7532] 190 | fedfsNsdbPort,A*,1.3.6.1.4.1.31103.1.6,[RFC7532] 191 | fedfsUuid,A,1.3.6.1.4.1.31103.1.1,[RFC7532] 192 | followReferrals,A,1.3.6.1.4.1.11.1.3.1.1.5,[RFC4876] 193 | friendlyCountry,O,0.9.2342.19200300.100.4.18,[RFC4524] 194 | friendlyCountryName,A*,0.9.2342.19200300.100.1.43,[RFC4524] 195 | generalizedTimeMatch,M,2.5.13.27,[RFC4517] 196 | generalizedTimeOrderingMatch,M,2.5.13.28,[RFC4517] 197 | generationQualifier,A,2.5.4.44,[RFC4519] 198 | givenName,A,2.5.4.42,[RFC4519] 199 | GN,A,RESERVED,[RFC4519] 200 | governingStructureRule,A,2.5.21.10,[RFC4512] 201 | groupOfNames,O,2.5.6.9,[RFC4519] 202 | groupOfUniqueNames,O,2.5.6.17,[RFC4519] 203 | homePhone,A,0.9.2342.19200300.100.1.20,[RFC4524] 204 | homePostalAddress,A,0.9.2342.19200300.100.1.39,[RFC4524] 205 | homeTelephone,A*,0.9.2342.19200300.100.1.20,[RFC4524] 206 | host,A,0.9.2342.19200300.100.1.9,[RFC4524] 207 | houseIdentifier,A,2.5.4.51,[RFC4519] 208 | increment,A,Reserved for LDIF,[RFC4525] 209 | info,A,0.9.2342.19200300.100.1.4,[RFC4524] 210 | initials,A,2.5.4.43,[RFC4519] 211 | integerFirstComponentMatch,M,2.5.13.29,[RFC4517] 212 | integerMatch,M,2.5.13.14,[RFC4517] 213 | integerOrderingMatch,M,2.5.13.15,[RFC4517] 214 | internationaliSDNNumber,A,2.5.4.25,[RFC4519] 215 | janetMailbox,A,0.9.2342.19200300.100.1.46,[RFC1274] 216 | jpegPhoto,A,0.9.2342.19200300.100.1.60,[RFC2798] 217 | keywordMatch,M,2.5.13.33,[RFC4517] 218 | knowledgeInformation,A,2.5.4.2,[RFC2256] 219 | L,A,2.5.4.7,[RFC4519] 220 | labeledURI,A,1.3.6.1.4.1.250.1.57,[RFC2079] 221 | labeledURIObject,O,1.3.6.1.4.1.250.3.15,[RFC2079] 222 | lastModifiedBy,A,0.9.2342.19200300.100.1.24,[RFC1274] 223 | lastModifiedTime,A,0.9.2342.19200300.100.1.23,[RFC1274] 224 | ldapSyntaxes,A,1.3.6.1.4.1.1466.101.120.16,[RFC4512] 225 | LDIFLocationURL,A,1.3.6.1.4.1.16572.2.2.6,[RFC6109] 226 | LDIFLocationURLObject,O,1.3.6.1.4.1.16572.2.1.1,[RFC6109] 227 | locality,O,2.5.6.3,[RFC4519] 228 | localityName,A,2.5.4.7,[RFC4519] 229 | mail,A,0.9.2342.19200300.100.1.3,[RFC4524] 230 | mailPreferenceOption,A,0.9.2342.19200300.100.1.47,[RFC1274] 231 | mailReceipt,A,1.3.6.1.4.1.16572.2.2.4,[RFC6109] 232 | manager,A,0.9.2342.19200300.100.1.10,[RFC4524] 233 | managedDomains,A,1.3.6.1.4.1.16572.2.2.5,[RFC6109] 234 | matchingRules,A,2.5.21.4,[RFC4512] 235 | matchingRuleUse,A,2.5.21.8,[RFC4512] 236 | mcgamTables,A,1.3.6.1.4.1.453.7.2.9,[RFC2164] 237 | mDRecord,A,0.9.2342.19200300.100.1.27,[RFC1274] 238 | member,A,2.5.4.31,[RFC4519] 239 | mixerGateway,O,1.3.6.1.4.1.453.7.1.4,[RFC2164] 240 | mobile,A,0.9.2342.19200300.100.1.41,[RFC4524] 241 | mobileTelephoneNumber,A*,0.9.2342.19200300.100.1.41,[RFC4524] 242 | moddn,A,Reserved for LDIF,[RFC2849] 243 | modifiersName,A,2.5.18.4,[RFC4512] 244 | modify,A,Reserved for LDIF,[RFC2849] 245 | modrdn,A,Reserved for LDIF,[RFC2849] 246 | modifyTimestamp,A,2.5.18.2,[RFC4512] 247 | mXRecord,A,0.9.2342.19200300.100.1.28,[RFC1274] 248 | name,A,2.5.4.41,[RFC4519] 249 | nameForms,A,2.5.21.7,[RFC4512] 250 | namingContexts,A,1.3.6.1.4.1.1466.101.120.5,[RFC4512] 251 | newrdn,A,Reserved for LDIF,[RFC2849] 252 | newsuperior,A,Reserved for LDIF,[RFC2849] 253 | nSRecord,A,0.9.2342.19200300.100.1.29,[RFC1274] 254 | numericStringMatch,M,2.5.13.8,[RFC4517] 255 | numericStringOrderingMatch,M,2.5.13.9,[RFC4517] 256 | numericStringSubstringsMatch,M,2.5.13.10,[RFC4517] 257 | o,A,2.5.4.10,[RFC4519] 258 | objectClass,A,2.5.4.0,[RFC4512] 259 | objectClasses,A,2.5.21.6,[RFC4512] 260 | objectclassMap,A,1.3.6.1.4.1.11.1.3.1.1.11,[RFC4876] 261 | objectIdentifierFirstComponentMatch,M,2.5.13.30,[RFC4517] 262 | objectIdentifierMatch,M,2.5.13.0,[RFC4517] 263 | octetStringMatch,M,2.5.13.17,[RFC4517] 264 | octetStringOrderingMatch,M,2.5.13.18,[RFC4517] 265 | omittedORAddressComponent,O,1.3.6.1.4.1.453.7.1.3,[RFC2164] 266 | oRAddressComponentType,A,1.3.6.1.4.1.453.7.2.7,[RFC2164] 267 | organization,O,2.5.6.4,[RFC4519] 268 | organizationalPerson,O,2.5.6.7,[RFC4519] 269 | organizationalRole,O,2.5.6.8,[RFC4519] 270 | organizationalStatus,A,0.9.2342.19200300.100.1.45,[RFC4524] 271 | organizationalUnit,O,2.5.6.5,[RFC4519] 272 | organizationalUnitName,A,2.5.4.11,[RFC4519] 273 | organizationName,A,2.5.4.10,[RFC4519] 274 | otherMailbox,A,0.9.2342.19200300.100.1.22,[RFC1274] 275 | ou,A,2.5.4.11,[RFC4519] 276 | owner,A,2.5.4.32,[RFC4519] 277 | pager,A,0.9.2342.19200300.100.1.42,[RFC4524] 278 | pagerTelephoneNumber,A*,0.9.2342.19200300.100.1.42,[RFC4524] 279 | pcels8021Filter,O,1.3.6.1.1.9.1.54,[RFC4104] 280 | pcels8021HdrDestMACAddress,A,1.3.6.1.1.9.2.50,[RFC4104] 281 | pcels8021HdrDestMACMask,A,1.3.6.1.1.9.2.51,[RFC4104] 282 | pcels8021HdrPriority,A,1.3.6.1.1.9.2.53,[RFC4104] 283 | pcels8021HdrProtocolID,A,1.3.6.1.1.9.2.52,[RFC4104] 284 | pcels8021HdrSourceMACAddress,A,1.3.6.1.1.9.2.48,[RFC4104] 285 | pcels8021HdrSourceMACMask,A,1.3.6.1.1.9.2.49,[RFC4104] 286 | pcels8021HdrVLANID,A,1.3.6.1.1.9.2.54,[RFC4104] 287 | pcelsActionAssociation,O,1.3.6.1.1.9.1.10,[RFC4104] 288 | pcelsActionList,A,1.3.6.1.1.9.2.8,[RFC4104] 289 | pcelsBitStringList,A,1.3.6.1.1.9.2.24,[RFC4104] 290 | pcelsBitStringValueAuxClass,O,1.3.6.1.1.9.1.45,[RFC4104] 291 | pcelsBoolean,A,1.3.6.1.1.9.2.26,[RFC4104] 292 | pcelsBooleanValueAuxClass,O,1.3.6.1.1.9.1.47,[RFC4104] 293 | pcelsCompoundActionAuxClass,O,1.3.6.1.1.9.1.15,[RFC4104] 294 | pcelsCompoundConditionAuxClass,O,1.3.6.1.1.9.1.12,[RFC4104] 295 | pcelsCompoundFilterConditionAuxClass,O,1.3.6.1.1.9.1.13,[RFC4104] 296 | pcelsConditionAssociation,O,1.3.6.1.1.9.1.9,[RFC4104] 297 | pcelsConditionList,A,1.3.6.1.1.9.2.7,[RFC4104] 298 | pcelsConditionListType,A,1.3.6.1.1.9.2.6,[RFC4104] 299 | pcelsCoSVariableAuxClass,O,1.3.6.1.1.9.1.33,[RFC4104] 300 | pcelsDecisionStrategy,A,1.3.6.1.1.9.2.2,[RFC4104] 301 | pcelsDestinationIPv4VariableAuxClass,O,1.3.6.1.1.9.1.21,[RFC4104] 302 | pcelsDestinationIPv6VariableAuxClass,O,1.3.6.1.1.9.1.22,[RFC4104] 303 | pcelsDestinationMACVariableAuxClass,O,1.3.6.1.1.9.1.31,[RFC4104] 304 | pcelsDestinationPortVariableAuxClass,O,1.3.6.1.1.9.1.24,[RFC4104] 305 | pcelsDestinationSAPVariableAuxClass,O,1.3.6.1.1.9.1.36,[RFC4104] 306 | pcelsDSCPVariableAuxClass,O,1.3.6.1.1.9.1.28,[RFC4104] 307 | pcelsElementList,A,1.3.6.1.1.9.2.31,[RFC4104] 308 | pcelsEthertypeVariableAuxClass,O,1.3.6.1.1.9.1.34,[RFC4104] 309 | pcelsExecutionStrategy,A,1.3.6.1.1.9.2.10,[RFC4104] 310 | pcelsExpectedValueList,A,1.3.6.1.1.9.2.15,[RFC4104] 311 | pcelsExpectedValueTypes,A,1.3.6.1.1.9.2.18,[RFC4104] 312 | pcelsExplicitVariableAuxClass,O,1.3.6.1.1.9.1.17,[RFC4104] 313 | pcelsFilterDirection,A,1.3.6.1.1.9.2.56,[RFC4104] 314 | pcelsFilterEntryBase,O,1.3.6.1.1.9.1.52,[RFC4104] 315 | pcelsFilterEntryList,A,1.3.6.1.1.9.2.57,[RFC4104] 316 | pcelsFilterIsNegated,A,1.3.6.1.1.9.2.33,[RFC4104] 317 | pcelsFilterListAuxClass,O,1.3.6.1.1.9.1.55,[RFC4104] 318 | pcelsFilterListName,A,1.3.6.1.1.9.2.55,[RFC4104] 319 | pcelsFilterName,A,1.3.6.1.1.9.2.32,[RFC4104] 320 | pcelsFlowDirectionVariableAuxClass,O,1.3.6.1.1.9.1.39,[RFC4104] 321 | pcelsFlowIdVariableAuxClass,O,1.3.6.1.1.9.1.29,[RFC4104] 322 | pcelsGroup,O,1.3.6.1.1.9.1.3,[RFC4104] 323 | pcelsGroupAuxClass,O,1.3.6.1.1.9.1.4,[RFC4104] 324 | pcelsGroupInstance,O,1.3.6.1.1.9.1.5,[RFC4104] 325 | pcelsImplicitVariableAuxClass,O,1.3.6.1.1.9.1.18,[RFC4104] 326 | pcelsIntegerList,A,1.3.6.1.1.9.2.25,[RFC4104] 327 | pcelsIntegerValueAuxClass,O,1.3.6.1.1.9.1.46,[RFC4104] 328 | pcelsIPHdrDestAddress,A,1.3.6.1.1.9.2.38,[RFC4104] 329 | pcelsIPHdrDestAddressEndOfRange,A,1.3.6.1.1.9.2.39,[RFC4104] 330 | pcelsIPHdrDestMask,A,1.3.6.1.1.9.2.40,[RFC4104] 331 | pcelsIPHdrDestPortEnd,A,1.3.6.1.1.9.2.45,[RFC4104] 332 | pcelsIPHdrDestPortStart,A,1.3.6.1.1.9.2.44,[RFC4104] 333 | pcelsIPHdrDSCPList,A,1.3.6.1.1.9.2.46,[RFC4104] 334 | pcelsIPHdrFlowLabel,A,1.3.6.1.1.9.2.47,[RFC4104] 335 | pcelsIPHdrProtocolID,A,1.3.6.1.1.9.2.41,[RFC4104] 336 | pcelsIPHdrSourceAddress,A,1.3.6.1.1.9.2.35,[RFC4104] 337 | pcelsIPHdrSourceAddressEndOfRange,A,1.3.6.1.1.9.2.36,[RFC4104] 338 | pcelsIPHdrSourceMask,A,1.3.6.1.1.9.2.37,[RFC4104] 339 | pcelsIPHdrSourcePortEnd,A,1.3.6.1.1.9.2.43,[RFC4104] 340 | pcelsIPHdrSourcePortStart,A,1.3.6.1.1.9.2.42,[RFC4104] 341 | pcelsIPHdrVersion,A,1.3.6.1.1.9.2.34,[RFC4104] 342 | pcelsIPHeadersFilter,O,1.3.6.1.1.9.1.53,[RFC4104] 343 | pcelsIPProtocolVariableAuxClass,O,1.3.6.1.1.9.1.25,[RFC4104] 344 | pcelsIPToSVariableAuxClass,O,1.3.6.1.1.9.1.27,[RFC4104] 345 | pcelsIPv4AddrList,A,1.3.6.1.1.9.2.20,[RFC4104] 346 | pcelsIPv4AddrValueAuxClass,O,1.3.6.1.1.9.1.41,[RFC4104] 347 | pcelsIPv6AddrList,A,1.3.6.1.1.9.2.21,[RFC4104] 348 | pcelsIPv6AddrValueAuxClass,O,1.3.6.1.1.9.1.42,[RFC4104] 349 | pcelsIPVersionVariableAuxClass,O,1.3.6.1.1.9.1.26,[RFC4104] 350 | pcelsIsMirrored,A,1.3.6.1.1.9.2.13,[RFC4104] 351 | pcelsMACAddrList,A,1.3.6.1.1.9.2.22,[RFC4104] 352 | pcelsMACAddrValueAuxClass,O,1.3.6.1.1.9.1.43,[RFC4104] 353 | pcelsPolicySet,O,1.3.6.1.1.9.1.1,[RFC4104] 354 | pcelsPolicySetAssociation,O,1.3.6.1.1.9.1.2,[RFC4104] 355 | pcelsPolicySetDN,A,1.3.6.1.1.9.2.5,[RFC4104] 356 | pcelsPolicySetList,A,1.3.6.1.1.9.2.3,[RFC4104] 357 | pcelsPolicySetName,A,1.3.6.1.1.9.2.1,[RFC4104] 358 | pcelsPriority,A,1.3.6.1.1.9.2.4,[RFC4104] 359 | pcelsReusableContainer,O,1.3.6.1.1.9.1.48,[RFC4104] 360 | pcelsReusableContainerAuxClass,O,1.3.6.1.1.9.1.49,[RFC4104] 361 | pcelsReusableContainerInstance,O,1.3.6.1.1.9.1.50,[RFC4104] 362 | pcelsReusableContainerList,A,1.3.6.1.1.9.2.28,[RFC4104] 363 | pcelsReusableContainerName,A,1.3.6.1.1.9.2.27,[RFC4104] 364 | pcelsRole,A,1.3.6.1.1.9.2.29,[RFC4104] 365 | pcelsRoleCollection,O,1.3.6.1.1.9.1.51,[RFC4104] 366 | pcelsRoleCollectionName,A,1.3.6.1.1.9.2.30,[RFC4104] 367 | pcelsRule,O,1.3.6.1.1.9.1.6,[RFC4104] 368 | pcelsRuleAuxClass,O,1.3.6.1.1.9.1.7,[RFC4104] 369 | pcelsRuleInstance,O,1.3.6.1.1.9.1.8,[RFC4104] 370 | pcelsRuleValidityPeriodList,A,1.3.6.1.1.9.2.62,[RFC4104] 371 | pcelsSequencedActions,A,1.3.6.1.1.9.2.9,[RFC4104] 372 | pcelsSimpleActionAuxClass,O,1.3.6.1.1.9.1.14,[RFC4104] 373 | pcelsSimpleConditionAuxClass,O,1.3.6.1.1.9.1.11,[RFC4104] 374 | pcelsSNAPOUIVariableAuxClass,O,1.3.6.1.1.9.1.37,[RFC4104] 375 | pcelsSNAPTypeVariableAuxClass,O,1.3.6.1.1.9.1.38,[RFC4104] 376 | pcelsSourceIPv4VariableAuxClass,O,1.3.6.1.1.9.1.19,[RFC4104] 377 | pcelsSourceIPv6VariableAuxClass,O,1.3.6.1.1.9.1.20,[RFC4104] 378 | pcelsSourceMACVariableAuxClass,O,1.3.6.1.1.9.1.30,[RFC4104] 379 | pcelsSourcePortVariableAuxClass,O,1.3.6.1.1.9.1.23,[RFC4104] 380 | pcelsSourceSAPVariableAuxClass,O,1.3.6.1.1.9.1.35,[RFC4104] 381 | pcelsStringList,A,1.3.6.1.1.9.2.23,[RFC4104] 382 | pcelsStringValueAuxClass,O,1.3.6.1.1.9.1.44,[RFC4104] 383 | pcelsValueAuxClass,O,1.3.6.1.1.9.1.40,[RFC4104] 384 | pcelsValueDN,A,1.3.6.1.1.9.2.12,[RFC4104] 385 | pcelsValueName,A,1.3.6.1.1.9.2.19,[RFC4104] 386 | pcelsVariable,O,1.3.6.1.1.9.1.16,[RFC4104] 387 | pcelsVariableDN,A,1.3.6.1.1.9.2.11,[RFC4104] 388 | pcelsVariableModelClass,A,1.3.6.1.1.9.2.16,[RFC4104] 389 | pcelsVariableModelProperty,A,1.3.6.1.1.9.2.17,[RFC4104] 390 | pcelsVariableName,A,1.3.6.1.1.9.2.14,[RFC4104] 391 | pcelsVendorValueAuxClass,O,1.3.6.1.1.9.1.57,[RFC4104] 392 | pcelsVendorValueData,A,1.3.6.1.1.9.2.60,[RFC4104] 393 | pcelsVendorValueEncoding,A,1.3.6.1.1.9.2.61,[RFC4104] 394 | pcelsVendorVariableAuxClass,O,1.3.6.1.1.9.1.56,[RFC4104] 395 | pcelsVendorVariableData,A,1.3.6.1.1.9.2.58,[RFC4104] 396 | pcelsVendorVariableEncoding,A,1.3.6.1.1.9.2.59,[RFC4104] 397 | pcelsVLANVariableAuxClass,O,1.3.6.1.1.9.1.32,[RFC4104] 398 | pcimPolicy,O,1.3.6.1.1.6.1.1,[RFC3703] 399 | pcimGroup,O,1.3.6.1.1.6.1.2,[RFC3703] 400 | pcimGroupAuxClass,O,1.3.6.1.1.6.1.3,[RFC3703] 401 | pcimGroupInstance,O,1.3.6.1.1.6.1.4,[RFC3703] 402 | pcimRule,O,1.3.6.1.1.6.1.5,[RFC3703] 403 | pcimRuleAuxClass,O,1.3.6.1.1.6.1.6,[RFC3703] 404 | pcimRuleInstance,O,1.3.6.1.1.6.1.7,[RFC3703] 405 | pcimRuleConditionAssociation,O,1.3.6.1.1.6.1.8,[RFC3703] 406 | pcimRuleValidityAssociation,O,1.3.6.1.1.6.1.9,[RFC3703] 407 | pcimRuleActionAssociation,O,1.3.6.1.1.6.1.10,[RFC3703] 408 | pcimConditionAuxClass,O,1.3.6.1.1.6.1.11,[RFC3703] 409 | pcimTPCAuxClass,O,1.3.6.1.1.6.1.12,[RFC3703] 410 | pcimConditionVendorAuxClass,O,1.3.6.1.1.6.1.13,[RFC3703] 411 | pcimActionAuxClass,O,1.3.6.1.1.6.1.14,[RFC3703] 412 | pcimActionVendorAuxClass,O,1.3.6.1.1.6.1.15,[RFC3703] 413 | pcimPolicyInstance,O,1.3.6.1.1.6.1.16,[RFC3703] 414 | pcimElementAuxClass,O,1.3.6.1.1.6.1.17,[RFC3703] 415 | pcimRepository,O,1.3.6.1.1.6.1.18,[RFC3703] 416 | pcimRepositoryAuxClass,O,1.3.6.1.1.6.1.19,[RFC3703] 417 | pcimRepositoryInstance,O,1.3.6.1.1.6.1.20,[RFC3703] 418 | pcimSubtreesPtrAuxClass,O,1.3.6.1.1.6.1.21,[RFC3703] 419 | pcimGroupContainmentAuxClass,O,1.3.6.1.1.6.1.22,[RFC3703] 420 | pcimRuleContainmentAuxClass,O,1.3.6.1.1.6.1.23,[RFC3703] 421 | pcimKeywords,A,1.3.6.1.1.6.2.3,[RFC3703] 422 | pcimGroupName,A,1.3.6.1.1.6.2.4,[RFC3703] 423 | pcimRuleName,A,1.3.6.1.1.6.2.5,[RFC3703] 424 | pcimRuleEnabled,A,1.3.6.1.1.6.2.6,[RFC3703] 425 | pcimRuleConditionListType,A,1.3.6.1.1.6.2.7,[RFC3703] 426 | pcimRuleConditionList,A,1.3.6.1.1.6.2.8,[RFC3703] 427 | pcimRuleActionList,A,1.3.6.1.1.6.2.9,[RFC3703] 428 | pcimRuleValidityPeriodList,A,1.3.6.1.1.6.2.10,[RFC3703] 429 | pcimRuleUsage,A,1.3.6.1.1.6.2.11,[RFC3703] 430 | pcimRulePriority,A,1.3.6.1.1.6.2.12,[RFC3703] 431 | pcimRuleMandatory,A,1.3.6.1.1.6.2.13,[RFC3703] 432 | pcimRuleSequencedActions,A,1.3.6.1.1.6.2.14,[RFC3703] 433 | pcimRoles,A,1.3.6.1.1.6.2.15,[RFC3703] 434 | pcimConditionGroupNumber,A,1.3.6.1.1.6.2.16,[RFC3703] 435 | pcimConditionNegated,A,1.3.6.1.1.6.2.17,[RFC3703] 436 | pcimConditionName,A,1.3.6.1.1.6.2.18,[RFC3703] 437 | pcimConditionDN,A,1.3.6.1.1.6.2.19,[RFC3703] 438 | pcimValidityConditionName,A,1.3.6.1.1.6.2.20,[RFC3703] 439 | pcimTimePeriodConditionDN,A,1.3.6.1.1.6.2.21,[RFC3703] 440 | pcimActionName,A,1.3.6.1.1.6.2.22,[RFC3703] 441 | pcimActionOrder,A,1.3.6.1.1.6.2.23,[RFC3703] 442 | pcimActionDN,A,1.3.6.1.1.6.2.24,[RFC3703] 443 | pcimTPCTime,A,1.3.6.1.1.6.2.25,[RFC3703] 444 | pcimTPCMonthOfYearMask,A,1.3.6.1.1.6.2.26,[RFC3703] 445 | pcimTPCDayOfMonthMask,A,1.3.6.1.1.6.2.27,[RFC3703] 446 | pcimTPCDayOfWeekMask,A,1.3.6.1.1.6.2.28,[RFC3703] 447 | pcimTPCTimeOfDayMask,A,1.3.6.1.1.6.2.29,[RFC3703] 448 | pcimTPCLocalOrUtcTime,A,1.3.6.1.1.6.2.30,[RFC3703] 449 | pcimVendorConstraintData,A,1.3.6.1.1.6.2.31,[RFC3703] 450 | pcimVendorConstraintEncoding,A,1.3.6.1.1.6.2.32,[RFC3703] 451 | pcimVendorActionData,A,1.3.6.1.1.6.2.33,[RFC3703] 452 | pcimVendorActionEncoding,A,1.3.6.1.1.6.2.34,[RFC3703] 453 | pcimPolicyInstanceName,A,1.3.6.1.1.6.2.35,[RFC3703] 454 | pcimRepositoryName,A,1.3.6.1.1.6.2.36,[RFC3703] 455 | pcimSubtreesAuxContainedSet,A,1.3.6.1.1.6.2.37,[RFC3703] 456 | pcimGroupsAuxContainedSet,A,1.3.6.1.1.6.2.38,[RFC3703] 457 | pcimRulesAuxContainedSet,A,1.3.6.1.1.6.2.39,[RFC3703] 458 | person,O,2.5.6.6,[RFC4519] 459 | personalSignature,A,0.9.2342.19200300.100.1.53,[RFC1274] 460 | personalTitle,A,0.9.2342.19200300.100.1.40,[RFC4524] 461 | photo,A,0.9.2342.19200300.100.1.7,[RFC1274] 462 | physicalDeliveryOfficeName,A,2.5.4.19,[RFC4519] 463 | pilotDSA,O,0.9.2342.19200300.100.4.21,[RFC1274] 464 | pilotObject,O,0.9.2342.19200300.100.4.3,[RFC1274] 465 | pilotOrganization,O,0.9.2342.19200300.100.4.20,[RFC1274] 466 | pilotPerson,O,0.9.2342.19200300.100.4.4,[RFC1274] 467 | pkiCA,O,2.5.6.22,[RFC4523] 468 | pkiUser,O,2.5.6.21,[RFC4523] 469 | postalAddress,A,2.5.4.16,[RFC4519] 470 | postalCode,A,2.5.4.17,[RFC4519] 471 | postOfficeBox,A,2.5.4.18,[RFC4519] 472 | preferredDeliveryMethod,A,2.5.4.28,[RFC4519] 473 | preferredServerList,A,1.3.6.1.4.1.11.1.3.1.1.2,[RFC4876] 474 | presentationAddress,A,2.5.4.29,[RFC2256] 475 | presentationAddressMatch,M,2.5.13.22,[RFC2252] 476 | presentMatch,M,1.2.36.79672281.1.13.5,[RFC3687] 477 | printer-aliases,A,1.3.18.0.2.4.1108,[RFC3712] 478 | printer-charge-info,A,1.3.18.0.2.24.46.1.105,[RFC7612] 479 | printer-charge-info-uri,A,1.3.18.0.2.24.46.1.106,[RFC7612] 480 | printer-charset-configured,A,1.3.18.0.2.4.1109,[RFC3712] 481 | printer-charset-supported,A,1.3.18.0.2.4.1131,[RFC3712] 482 | printer-color-supported,A,1.3.18.0.2.4.1129,[RFC3712] 483 | printer-compression-supported,A,1.3.18.0.2.4.1128,[RFC3712] 484 | printer-copies-supported,A,1.3.18.0.2.4.1118,[RFC3712] 485 | printer-current-operator,A,1.3.18.0.2.4.1112,[RFC3712] 486 | printer-delivery-orientation-supported,A,1.3.18.0.2.4.1114,[RFC3712] 487 | printer-device-id,A,1.3.18.0.2.24.46.1.101,[RFC7612] 488 | printer-device-service-count,A,1.3.18.0.2.24.46.1.102,[RFC7612] 489 | printer-document-format-supported,A,1.3.18.0.2.4.1130,[RFC3712] 490 | printer-finishings-supported,A,1.3.18.0.2.4.1125,[RFC3712] 491 | printer-generated-natural-language-supported,A,1.3.18.0.2.4.1137,[RFC3712] 492 | printer-geo-location,A,1.3.18.0.2.24.46.1.107,[RFC7612] 493 | printer-info,A,1.3.18.0.2.4.1139,[RFC3712] 494 | printer-ipp-features-supported,A,1.3.18.0.2.24.46.1.108,[RFC7612] 495 | printer-ipp-versions-supported,A,1.3.18.0.2.4.1133,[RFC3712] 496 | printer-job-priority-supported,A,1.3.18.0.2.4.1110,[RFC3712] 497 | printer-job-k-octets-supported,A,1.3.18.0.2.4.1111,[RFC3712] 498 | printer-location,A,1.3.18.0.2.4.1136,[RFC3712] 499 | printer-make-and-model,A,1.3.18.0.2.4.1138,[RFC3712] 500 | printer-media-local-supported,A,1.3.18.0.2.4.1117,[RFC3712] 501 | printer-media-supported,A,1.3.18.0.2.4.1122,[RFC3712] 502 | printer-more-info,A,1.3.18.0.2.4.1134,[RFC3712] 503 | printer-multiple-document-jobs-supported,A,1.3.18.0.2.4.1132,[RFC3712] 504 | printer-name,A,1.3.18.0.2.4.1135,[RFC3712] 505 | printer-natural-language-configured,A,1.3.18.0.2.4.1119,[RFC3712] 506 | printer-number-up-supported,A,1.3.18.0.2.4.1124,[RFC3712] 507 | printer-output-features-supported,A,1.3.18.0.2.4.1116,[RFC3712] 508 | printer-pages-per-minute,A,1.3.18.0.2.4.1127,[RFC3712] 509 | printer-pages-per-minute-color,A,1.3.18.0.2.4.1126,[RFC3712] 510 | printer-print-quality-supported,A,1.3.18.0.2.4.1120,[RFC3712] 511 | printer-resolution-supported,A,1.3.18.0.2.4.1121,[RFC3712] 512 | printer-service-person,A,1.3.18.0.2.4.1113,[RFC3712] 513 | printer-sides-supported,A,1.3.18.0.2.4.1123,[RFC3712] 514 | printer-stacking-order-supported,A,1.3.18.0.2.4.1115,[RFC3712] 515 | printer-uri,A,1.3.18.0.2.4.1140,[RFC3712] 516 | printer-uuid,A,1.3.18.0.2.24.46.1.104,[RFC7612] 517 | printer-xri-supported,A,1.3.18.0.2.4.1107,[RFC3712] 518 | printerAbstract,O,1.3.18.0.2.6.258,[RFC3712] 519 | printerIPP,O,1.3.18.0.2.6.256,[RFC3712] 520 | printerLPR,O,1.3.18.0.2.6.253,[RFC3712] 521 | printerService,O,1.3.18.0.2.6.255,[RFC3712] 522 | printerServiceAuxClass,O,1.3.18.0.2.6.257,[RFC3712] 523 | profileTTL,A,1.3.6.1.4.1.11.1.3.1.1.7,[RFC4876] 524 | protocolInformation,A,2.5.4.48,[RFC2256] 525 | protocolInformationMatch,M,2.5.13.24,[RFC2252] 526 | provider,O,1.3.6.1.4.1.16572.2.1.2,[RFC6109] 527 | providerCertificate,A,1.3.6.1.4.1.16572.2.2.2,[RFC6109] 528 | providerCertificateHash,A,1.3.6.1.4.1.16572.2.2.1,[RFC6109] 529 | providerName,A,1.3.6.1.4.1.16572.2.2.3,[RFC6109] 530 | providerUnit,A,1.3.6.1.4.1.16572.2.2.7,[RFC6109] 531 | pseudonym,A,2.5.4.65,[RFC3280] 532 | qualityLabelledData,O,0.9.2342.19200300.100.4.22,[RFC1274] 533 | rdnMatch,M,1.2.36.79672281.1.13.3,[RFC3687] 534 | ref,A,2.16.840.1.113730.3.1.34,[RFC3296] 535 | referral,0,2.16.840.1.113730.3.2.6,[RFC3296] 536 | registeredAddress,A,2.5.4.26,[RFC4519] 537 | replace,A,Reserved for LDIF,[RFC2849] 538 | residentialPerson,O,2.5.6.10,[RFC4519] 539 | RFC822LocalPart,O,0.9.2342.19200300.100.4.14,[RFC4524] 540 | RFC822Mailbox,A*,0.9.2342.19200300.100.1.3,[RFC4524] 541 | rFC822ToX400Mapping,O,1.3.6.1.4.1.453.7.1.1,[RFC2164] 542 | roleOccupant,A,2.5.4.33,[RFC4519] 543 | room,O,0.9.2342.19200300.100.4.7,[RFC4524] 544 | roomNumber,A,0.9.2342.19200300.100.1.6,[RFC4524] 545 | searchGuide,A,2.5.4.14,[RFC4519] 546 | searchTimeLimit,A,1.3.6.1.4.1.11.1.3.1.1.3,[RFC4876] 547 | secretary,A,0.9.2342.19200300.100.1.21,[RFC4524] 548 | seeAlso,A,2.5.4.34,[RFC4519] 549 | serialNumber,A,2.5.4.5,[RFC4519] 550 | serviceAuthenticationMethod,A,1.3.6.1.4.1.11.1.3.1.1.15,[RFC4876] 551 | serviceCredentialLevel,A,1.3.6.1.4.1.11.1.3.1.1.13,[RFC4876] 552 | serviceSearchDescriptor,A,1.3.6.1.4.1.11.1.3.1.1.14,[RFC4876] 553 | simpleSecurityObject,O,0.9.2342.19200300.100.4.19,[RFC4524] 554 | singleLevelQuality,A,0.9.2342.19200300.100.1.50,[RFC4524] 555 | slpServicePrinter,O,1.3.18.0.2.6.254,[RFC3712] 556 | sn,A,2.5.4.4,[RFC4519] 557 | sOARecord,A,0.9.2342.19200300.100.1.30,[RFC1274] 558 | st,A,2.5.4.8,[RFC4519] 559 | stateOrProvinceName,A,2.5.4.8,[RFC2256] 560 | storedPrefixMatch,M,2.5.13.41,[RFC3698] 561 | street,A,2.5.4.9,[RFC4519] 562 | streetAddress,A,2.5.4.9,[RFC2256] 563 | strongAuthenticationUser,O,2.5.6.15,[RFC4523] 564 | structuralObjectClass,A,2.5.21.9,[RFC4512] 565 | subentry,O,2.5.17.0,[RFC3672] 566 | subschema,O,2.5.20.1,[RFC4512] 567 | subschemaAdminSpecificArea,R,2.5.23.4,[RFC3672] 568 | subschemaSubentry,A,2.5.18.10,[RFC4512] 569 | subtree,O,1.3.6.1.4.1.453.7.1.1,[RFC2293] 570 | subtreeMaximumQuality,A,0.9.2342.19200300.100.1.52,[RFC1274] 571 | subtreeMinimumQuality,A,0.9.2342.19200300.100.1.51,[RFC1274] 572 | subtreeSpecification,A,2.5.18.6,[RFC3672] 573 | supportedAlgorithms,A,2.5.4.52,[RFC4523] 574 | supportedApplicationContext,A,2.5.4.30,[RFC2256] 575 | supportedControl,A,1.3.6.1.4.1.1466.101.120.13,[RFC4512] 576 | supportedExtension,A,1.3.6.1.4.1.1466.101.120.7,[RFC4512] 577 | supportedFeatures,A,1.3.6.1.4.1.4203.1.3.5,[RFC4512] 578 | supportedLDAPVersion,A,1.3.6.1.4.1.1466.101.120.15,[RFC4512] 579 | supportedSASLMechanisms,A,1.3.6.1.4.1.1466.101.120.14,[RFC4512] 580 | surname,A,2.5.4.4,[RFC4519] 581 | table,O,1.3.6.1.4.1.453.7.1.2,[RFC2293] 582 | tableEntry,O,1.3.6.1.4.1.453.7.1.3,[RFC2293] 583 | telephoneNumber,A,2.5.4.20,[RFC4519] 584 | telephoneNumberMatch,M,2.5.13.20,[RFC4517] 585 | telephoneNumberSubstringsMatch,M,2.5.13.21,[RFC4517] 586 | teletexTerminalIdentifier,A,2.5.4.22,[RFC4519] 587 | telexNumber,A,2.5.4.21,[RFC4519] 588 | textEncodedORAddress,A,0.9.2342.19200300.100.1.2,[RFC1274] 589 | textTableEntry,O,1.3.6.1.4.1.453.7.1.4,[RFC2293] 590 | textTableKey,A,1.3.6.1.4.1.453.7.2.1,[RFC2293] 591 | textTableValue,A,1.3.6.1.4.1.453.7.2.2,[RFC2293] 592 | title,A,2.5.4.12,[RFC4519] 593 | top,O,2.5.6.0,[RFC4512] 594 | uddiAccessPoint,A,1.3.6.1.1.10.4.19,[RFC4403] 595 | uddiAddress,O,1.3.6.1.1.10.6.3,[RFC4403] 596 | uddiAddressLine,A,1.3.6.1.1.10.4.13,[RFC4403] 597 | uddiAddressNameForm,N,1.3.6.1.1.10.15.3,[RFC4403] 598 | uddiAuthorizedName,A,1.3.6.1.1.10.4.2,[RFC4403] 599 | uddiBindingKey,A,1.3.6.1.1.10.4.18,[RFC4403] 600 | uddiBindingTemplate,O,1.3.6.1.1.10.6.5,[RFC4403] 601 | uddiBindingTemplateNameForm,N,1.3.6.1.1.10.15.5,[RFC4403] 602 | uddiBusinessEntity,O,1.3.6.1.1.10.6.1,[RFC4403] 603 | uddiBusinessEntityNameForm,N,1.3.6.1.1.10.15.1,[RFC4403] 604 | uddiBusinessKey,A,1.3.6.1.1.10.4.1,[RFC4403] 605 | uddiBusinessService,O,1.3.6.1.1.10.6.4,[RFC4403] 606 | uddiBusinessServiceNameForm,N,1.3.6.1.1.10.15.4,[RFC4403] 607 | uddiCategoryBag,A,1.3.6.1.1.10.4.15,[RFC4403] 608 | uddiContact,O,1.3.6.1.1.10.6.2,[RFC4403] 609 | uddiContactNameForm,N,1.3.6.1.1.10.15.2,[RFC4403] 610 | uddiDescription,A,1.3.6.1.1.10.4.5,[RFC4403] 611 | uddiDiscoveryURLs,A,1.3.6.1.1.10.4.6,[RFC4403] 612 | uddiEMail,A,1.3.6.1.1.10.4.10,[RFC4403] 613 | uddiFromKey,A,1.3.6.1.1.10.4.25,[RFC4403] 614 | uddiHostingRedirector,A,1.3.6.1.1.10.4.20,[RFC4403] 615 | uddiIdentifierBag,A,1.3.6.1.1.10.4.14,[RFC4403] 616 | uddiInstanceDescription,A,1.3.6.1.1.10.4.21,[RFC4403] 617 | uddiInstanceParms,A,1.3.6.1.1.10.4.22,[RFC4403] 618 | uddiIsHidden,A,1.3.6.1.1.10.4.28,[RFC4403] 619 | uddiIsProjection,A,1.3.6.1.1.10.4.29,[RFC4403] 620 | uddiKeyedReference,A,1.3.6.1.1.10.4.16,[RFC4403] 621 | uddiLang,A,1.3.6.1.1.10.4.30,[RFC4403] 622 | uddiName,A,1.3.6.1.1.10.4.4,[RFC4403] 623 | uddiOperator,A,1.3.6.1.1.10.4.3,[RFC4403] 624 | uddiOverviewDescription,A,1.3.6.1.1.10.4.23,[RFC4403] 625 | uddiOverviewURL,A,1.3.6.1.1.10.4.24,[RFC4403] 626 | uddiPersonName,A,1.3.6.1.1.10.4.8,[RFC4403] 627 | uddiPhone,A,1.3.6.1.1.10.4.9,[RFC4403] 628 | uddiPublisherAssertion,O,1.3.6.1.1.10.6.8,[RFC4403] 629 | uddiPublisherAssertionNameForm,N,1.3.6.1.1.10.15.8,[RFC4403] 630 | uddiServiceKey,A,1.3.6.1.1.10.4.17,[RFC4403] 631 | uddiSortCode,A,1.3.6.1.1.10.4.11,[RFC4403] 632 | uddiTModel,O,1.3.6.1.1.10.6.7,[RFC4403] 633 | uddiTModelInstanceInfo,O,1.3.6.1.1.10.6.6,[RFC4403] 634 | uddiTModelInstanceInfoNameForm,N,1.3.6.1.1.10.15.6,[RFC4403] 635 | uddiTModelKey,A,1.3.6.1.1.10.4.12,[RFC4403] 636 | uddiTModelNameForm,N,1.3.6.1.1.10.15.7,[RFC4403] 637 | uddiToKey,A,1.3.6.1.1.10.4.26,[RFC4403] 638 | uddiUseType,A,1.3.6.1.1.10.4.7,[RFC4403] 639 | uddiUUID,A,1.3.6.1.1.10.4.27,[RFC4403] 640 | uddiv3BindingKey,A,1.3.6.1.1.10.4.33,[RFC4403] 641 | uddiv3BriefResponse,A,1.3.6.1.1.10.4.43,[RFC4403] 642 | uddiv3BusinessKey,A,1.3.6.1.1.10.4.31,[RFC4403] 643 | uddiv3DigitalSignature,A,1.3.6.1.1.10.4.35,[RFC4403] 644 | uddiv3EntityCreationTime,A,1.3.6.1.1.10.4.45,[RFC4403] 645 | uddiv3EntityDeletionTime,A,1.3.6.1.1.10.4.46,[RFC4403] 646 | uddiv3EntityKey,A,1.3.6.1.1.10.4.44,[RFC4403] 647 | uddiv3EntityModificationTime,A,1.3.6.1.1.10.4.37,[RFC4403] 648 | uddiv3EntityObituary,O,1.3.6.1.1.10.6.10,[RFC4403] 649 | uddiv3EntityObituaryNameForm,N,1.3.6.1.1.10.15.10,[RFC4403] 650 | uddiv3ExpiresAfter,A,1.3.6.1.1.10.4.42,[RFC4403] 651 | uddiv3MaxEntities,A,1.3.6.1.1.10.4.41,[RFC4403] 652 | uddiv3NodeId,A,1.3.6.1.1.10.4.36,[RFC4403] 653 | uddiv3NotificationInterval,A,1.3.6.1.1.10.4.40,[RFC4403] 654 | uddiv3ServiceKey,A,1.3.6.1.1. 10.4.32,[RFC4403] 655 | uddiv3Subscription,O,1.3.6.1.1.10.6.9,[RFC4403] 656 | uddiv3SubscriptionFilter,A,1.3.6.1.1.10.4.39,[RFC4403] 657 | uddiv3SubscriptionKey,A,1.3.6.1.1.10.4.38,[RFC4403] 658 | uddiv3SubscriptionNameForm,N,1.3.6.1.1.10.15.9,[RFC4403] 659 | uddiv3TmodelKey,A,1.3.6.1.1.10.4.34,[RFC4403] 660 | uid,A,0.9.2342.19200300.100.1.1,[RFC4519] 661 | uidObject,O,1.3.6.1.1.3.1,[RFC4519] 662 | uniqueIdentifier,A,0.9.2342.19200300.100.1.44,[RFC4524] 663 | uniqueMember,A,2.5.4.50,[RFC4519] 664 | uniqueMemberMatch,M,2.5.13.23,[RFC4517] 665 | userCertificate,A,2.5.4.36,[RFC4523] 666 | userClass,A,0.9.2342.19200300.100.1.8,[RFC4524] 667 | userId,A,0.9.2342.19200300.100.1.1,[RFC4519] 668 | userPassword,A,2.5.4.35,[RFC4519] 669 | userSecurityInformation,O,2.5.6.18,[RFC4523] 670 | uuidMatch,M,1.3.6.1.1.16.2,[RFC4530] 671 | uuidOrderingMatch,M,1.3.6.1.1.16.3,[RFC4530] 672 | version,A,Reserved for LDIF,[RFC2849] 673 | vPIMUser,O,1.3.6.1.1.11.1.1,[RFC4237] 674 | vPIMRfc822Mailbox,A,1.3.6.1.1.11.2.2,[RFC4237] 675 | vPIMTelephoneNumber,A,1.3.6.1.1.11.2.1,[RFC4237] 676 | vPIMSpokenName,A,1.3.6.1.1.11.2.3,[RFC4237] 677 | vPIMSupportedUABehaviors,A,1.3.6.1.1.11.2.4,[RFC4237] 678 | vPIMSupportedAudioMediaTypes,A,1.3.6.1.1.11.2.5,[RFC4237] 679 | vPIMSupportedMessageContext,A,1.3.6.1.1.11.2.6,[RFC4237] 680 | vPIMTextName,A,1.3.6.1.1.11.2.7,[RFC4237] 681 | vPIMExtendedAbsenceStatus,A,1.3.6.1.1.11.2.8,[RFC4237] 682 | vPIMMaxMessageSize,A,1.3.6.1.1.11.2.9,[RFC4237] 683 | vPIMSubMailboxes,A,1.3.6.1.1.11.2.10,[RFC4237] 684 | wordMatch,M,2.5.13.32,[RFC4517] 685 | x121Address,A,2.5.4.24,[RFC4519] 686 | x400ToRFC822Mapping,O,1.3.6.1.4.1.453.7.1.2,[RFC2164] 687 | x500UniqueIdentifier,A,2.5.4.45,[RFC4519] 688 | --------------------------------------------------------------------------------