github.com/zmap/zlint@v1.1.0/lints/lint_generalized_time_includes_fraction_seconds.go (about)

     1  package lints
     2  
     3  /*
     4   * ZLint Copyright 2018 Regents of the University of Michigan
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
     7   * use this file except in compliance with the License. You may obtain a copy
     8   * of the License at http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    13   * implied. See the License for the specific language governing
    14   * permissions and limitations under the License.
    15   */
    16  
    17  /********************************************************************
    18  4.1.2.5.2.  GeneralizedTime
    19  The generalized time type, GeneralizedTime, is a standard ASN.1 type
    20  for variable precision representation of time.  Optionally, the
    21  GeneralizedTime field can include a representation of the time
    22  differential between local and Greenwich Mean Time.
    23  
    24  For the purposes of this profile, GeneralizedTime values MUST be
    25  expressed in Greenwich Mean Time (Zulu) and MUST include seconds
    26  (i.e., times are YYYYMMDDHHMMSSZ), even where the number of seconds
    27  is zero.  GeneralizedTime values MUST NOT include fractional seconds.
    28  ********************************************************************/
    29  
    30  import (
    31  	"encoding/asn1"
    32  
    33  	"github.com/zmap/zcrypto/x509"
    34  	"github.com/zmap/zlint/util"
    35  )
    36  
    37  type generalizedTimeFraction struct {
    38  }
    39  
    40  func (l *generalizedTimeFraction) Initialize() error {
    41  	return nil
    42  }
    43  
    44  func (l *generalizedTimeFraction) CheckApplies(c *x509.Certificate) bool {
    45  	firstDate, secondDate := util.GetTimes(c)
    46  	beforeTag, afterTag := util.FindTimeType(firstDate, secondDate)
    47  	date1Gen := beforeTag == 24
    48  	date2Gen := afterTag == 24
    49  	return date1Gen || date2Gen
    50  }
    51  
    52  func (l *generalizedTimeFraction) Execute(c *x509.Certificate) *LintResult {
    53  	r := Pass
    54  	date1, date2 := util.GetTimes(c)
    55  	beforeTag, afterTag := util.FindTimeType(date1, date2)
    56  	date1Gen := beforeTag == 24
    57  	date2Gen := afterTag == 24
    58  	if date1Gen {
    59  		// UTC Tests on notBefore
    60  		checkFraction(&r, date1)
    61  		if r == Error {
    62  			return &LintResult{Status: r}
    63  		}
    64  	}
    65  	if date2Gen {
    66  		checkFraction(&r, date2)
    67  	}
    68  	return &LintResult{Status: r}
    69  }
    70  
    71  func checkFraction(r *LintStatus, t asn1.RawValue) {
    72  	if t.Bytes[len(t.Bytes)-1] == 'Z' {
    73  		if len(t.Bytes) > 15 {
    74  			*r = Error
    75  		}
    76  	} else if t.Bytes[len(t.Bytes)-5] == '-' || t.Bytes[len(t.Bytes)-1] == '+' {
    77  		if len(t.Bytes) > 19 {
    78  			*r = Error
    79  		}
    80  	} else {
    81  		if len(t.Bytes) > 14 {
    82  			*r = Error
    83  		}
    84  	}
    85  }
    86  
    87  func init() {
    88  	RegisterLint(&Lint{
    89  		Name:          "e_generalized_time_includes_fraction_seconds",
    90  		Description:   "Generalized time values MUST NOT include fractional seconds",
    91  		Citation:      "RFC 5280: 4.1.2.5.2",
    92  		Source:        RFC5280,
    93  		EffectiveDate: util.RFC2459Date,
    94  		Lint:          &generalizedTimeFraction{},
    95  	})
    96  }