github.com/zmap/zlint@v1.1.0/lints/lint_subject_printable_string_badalpha.go (about) 1 /* 2 * ZLint Copyright 2019 Regents of the University of Michigan 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy 6 * of the License at http://www.apache.org/licenses/LICENSE-2.0 7 * 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 * implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package lints 16 17 import ( 18 "encoding/asn1" 19 "errors" 20 "fmt" 21 "regexp" 22 23 "github.com/zmap/zcrypto/x509" 24 "github.com/zmap/zlint/util" 25 ) 26 27 var ( 28 // Per RFC 5280, Appendix B. ASN.1 Notes: 29 // The character string type PrintableString supports a very basic Latin 30 // character set: the lowercase letters 'a' through 'z', uppercase 31 // letters 'A' through 'Z', the digits '0' through '9', eleven special 32 // characters ' = ( ) + , - . / : ? and space. 33 printableStringRegex = regexp.MustCompile(`^[a-zA-Z0-9\=\(\)\+,\-.\/:\? ']+$`) 34 ) 35 36 // validatePrintableString returns an error if the provided encoded printable 37 // string doesn't adhere to the character set defined in RFC 5280. 38 func validatePrintableString(rawPS []byte) error { 39 if !printableStringRegex.Match(rawPS) { 40 return errors.New("encoded PrintableString contained illegal characters") 41 } 42 return nil 43 } 44 45 type subjectPrintableStringBadAlpha struct { 46 } 47 48 func (l *subjectPrintableStringBadAlpha) Initialize() error { 49 return nil 50 } 51 52 // CheckApplies returns true for any certificate with a non-empty RawSubject. 53 func (l *subjectPrintableStringBadAlpha) CheckApplies(c *x509.Certificate) bool { 54 return len(c.RawSubject) > 0 55 } 56 57 // Execute checks the certificate's RawSubject to ensure that any 58 // PrintableString attribute/value pairs in the Subject match the character set 59 // defined for this type in RFC 5280. An Error level LintResult is returned if any 60 // of the PrintableString attributes do not match a regular expression for the 61 // allowed character set. 62 func (l *subjectPrintableStringBadAlpha) Execute(c *x509.Certificate) *LintResult { 63 rdnSequence := util.RawRDNSequence{} 64 rest, err := asn1.Unmarshal(c.RawSubject, &rdnSequence) 65 if err != nil { 66 return &LintResult{ 67 Status: Fatal, 68 Details: "Failed to Unmarshal RawSubject into RawRDNSequence", 69 } 70 } 71 if len(rest) > 0 { 72 return &LintResult{ 73 Status: Fatal, 74 Details: "Trailing data after RawSubject RawRDNSequence", 75 } 76 } 77 78 for _, attrTypeAndValueSet := range rdnSequence { 79 for _, attrTypeAndValue := range attrTypeAndValueSet { 80 // If the attribute type is a PrintableString the bytes of the attribute 81 // value must match the printable string alphabet. 82 if attrTypeAndValue.Value.Tag == asn1.TagPrintableString { 83 if err := validatePrintableString(attrTypeAndValue.Value.Bytes); err != nil { 84 return &LintResult{ 85 Status: Error, 86 Details: fmt.Sprintf("RawSubject attr oid %s %s", 87 attrTypeAndValue.Type, err.Error()), 88 } 89 } 90 } 91 } 92 } 93 94 return &LintResult{ 95 Status: Pass, 96 } 97 } 98 99 func init() { 100 RegisterLint(&Lint{ 101 Name: "e_subject_printable_string_badalpha", 102 Description: "PrintableString type's alphabet only includes a-z, A-Z, 0-9, and 11 special characters", 103 Citation: "RFC 5280: Appendix B. ASN.1 Notes", 104 Source: RFC5280, 105 EffectiveDate: util.RFC2459Date, 106 Lint: &subjectPrintableStringBadAlpha{}, 107 }) 108 }