diff --git a/go.mod b/go.mod index 556a3d355..f6a37c7f8 100644 --- a/go.mod +++ b/go.mod @@ -15,8 +15,8 @@ require ( github.com/mattn/go-sqlite3 v1.14.15 github.com/prometheus/client_golang v1.15.1 github.com/stretchr/testify v1.8.0 - github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc - github.com/zmap/zlint/v3 v3.1.0 + github.com/zmap/zcrypto v0.0.0-20220402174210-599ec18ecbac + github.com/zmap/zlint/v3 v3.4.1 golang.org/x/crypto v0.3.0 ) @@ -27,15 +27,15 @@ require ( github.com/getsentry/sentry-go v0.11.0 // indirect github.com/go-logr/logr v1.2.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/kr/text v0.2.0 // indirect github.com/kylelemons/go-gypsy v1.0.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/pelletier/go-toml v1.9.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b // indirect + github.com/weppos/publicsuffix-go v0.15.1-0.20220329081811-9a40b608a236 // indirect github.com/ziutek/mymysql v1.5.4 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/sys v0.6.0 // indirect diff --git a/go.sum b/go.sum index ca331aeae..b97425dd8 100644 --- a/go.sum +++ b/go.sum @@ -72,7 +72,6 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -223,7 +222,6 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/go-gypsy v1.0.0 h1:7/wQ7A3UL1bnqRMnZ6T8cwCOArfZCxFmb1iTxaOOo1s= github.com/kylelemons/go-gypsy v1.0.0/go.mod h1:chkXM0zjdpXOiqkCW1XcCHDfjfk14PH2KKkQWxfJUcU= github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= @@ -264,6 +262,8 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -309,7 +309,6 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -336,9 +335,8 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/weppos/publicsuffix-go v0.13.1-0.20210123135404-5fd73613514e/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= -github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b h1:FsyNrX12e5BkplJq7wKOLk0+C6LZ+KGXvuEcKUYm5ss= -github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= +github.com/weppos/publicsuffix-go v0.15.1-0.20220329081811-9a40b608a236 h1:vMJBP3PQViZsF6cOINtvyMC8ptpLsyJ4EwyFnzuWNxc= +github.com/weppos/publicsuffix-go v0.15.1-0.20220329081811-9a40b608a236/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= @@ -354,11 +352,10 @@ github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE= github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is= -github.com/zmap/zcrypto v0.0.0-20210123152837-9cf5beac6d91/go.mod h1:R/deQh6+tSWlgI9tb4jNmXxn8nSCabl5ZQsBX9//I/E= -github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc h1:zkGwegkOW709y0oiAraH/3D8njopUR/pARHv4tZZ6pw= -github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc/go.mod h1:FM4U1E3NzlNMRnSUTU3P1UdukWhYGifqEsjk9fn7BCk= -github.com/zmap/zlint/v3 v3.1.0 h1:WjVytZo79m/L1+/Mlphl09WBob6YTGljN5IGWZFpAv0= -github.com/zmap/zlint/v3 v3.1.0/go.mod h1:L7t8s3sEKkb0A2BxGy1IWrxt1ZATa1R4QfJZaQOD3zU= +github.com/zmap/zcrypto v0.0.0-20220402174210-599ec18ecbac h1:+nr36qrZEH0RIYNjcUEnOrCUdcSG3om2ANaFA6iSVWA= +github.com/zmap/zcrypto v0.0.0-20220402174210-599ec18ecbac/go.mod h1:egdRkzUylATvPkWMpebZbXhv0FMEMJGX/ur0D3Csk2s= +github.com/zmap/zlint/v3 v3.4.1 h1:zhGB2Q1oPNS+bODC5tTPlKDOnLfDGyxejgAEp1SfFiQ= +github.com/zmap/zlint/v3 v3.4.1/go.mod h1:WgepL2QqxyMHnrOWJ54NqrgfMtOyuXr52wEE0tcfo9k= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -498,7 +495,6 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -514,7 +510,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= diff --git a/vendor/github.com/pelletier/go-toml/.dockerignore b/vendor/github.com/pelletier/go-toml/.dockerignore new file mode 100644 index 000000000..7b5883475 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/.dockerignore @@ -0,0 +1,2 @@ +cmd/tomll/tomll +cmd/tomljson/tomljson diff --git a/vendor/github.com/pelletier/go-toml/.gitignore b/vendor/github.com/pelletier/go-toml/.gitignore new file mode 100644 index 000000000..e6ba63a5c --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/.gitignore @@ -0,0 +1,5 @@ +test_program/test_program_bin +fuzz/ +cmd/tomll/tomll +cmd/tomljson/tomljson +cmd/tomltestgen/tomltestgen diff --git a/vendor/github.com/pelletier/go-toml/CONTRIBUTING.md b/vendor/github.com/pelletier/go-toml/CONTRIBUTING.md new file mode 100644 index 000000000..98b9893d3 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/CONTRIBUTING.md @@ -0,0 +1,132 @@ +## Contributing + +Thank you for your interest in go-toml! We appreciate you considering +contributing to go-toml! + +The main goal is the project is to provide an easy-to-use TOML +implementation for Go that gets the job done and gets out of your way – +dealing with TOML is probably not the central piece of your project. + +As the single maintainer of go-toml, time is scarce. All help, big or +small, is more than welcomed! + +### Ask questions + +Any question you may have, somebody else might have it too. Always feel +free to ask them on the [issues tracker][issues-tracker]. We will try to +answer them as clearly and quickly as possible, time permitting. + +Asking questions also helps us identify areas where the documentation needs +improvement, or new features that weren't envisioned before. Sometimes, a +seemingly innocent question leads to the fix of a bug. Don't hesitate and +ask away! + +### Improve the documentation + +The best way to share your knowledge and experience with go-toml is to +improve the documentation. Fix a typo, clarify an interface, add an +example, anything goes! + +The documentation is present in the [README][readme] and thorough the +source code. On release, it gets updated on [pkg.go.dev][pkg.go.dev]. To make a +change to the documentation, create a pull request with your proposed +changes. For simple changes like that, the easiest way to go is probably +the "Fork this project and edit the file" button on Github, displayed at +the top right of the file. Unless it's a trivial change (for example a +typo), provide a little bit of context in your pull request description or +commit message. + +### Report a bug + +Found a bug! Sorry to hear that :(. Help us and other track them down and +fix by reporting it. [File a new bug report][bug-report] on the [issues +tracker][issues-tracker]. The template should provide enough guidance on +what to include. When in doubt: add more details! By reducing ambiguity and +providing more information, it decreases back and forth and saves everyone +time. + +### Code changes + +Want to contribute a patch? Very happy to hear that! + +First, some high-level rules: + +* A short proposal with some POC code is better than a lengthy piece of + text with no code. Code speaks louder than words. +* No backward-incompatible patch will be accepted unless discussed. + Sometimes it's hard, and Go's lack of versioning by default does not + help, but we try not to break people's programs unless we absolutely have + to. +* If you are writing a new feature or extending an existing one, make sure + to write some documentation. +* Bug fixes need to be accompanied with regression tests. +* New code needs to be tested. +* Your commit messages need to explain why the change is needed, even if + already included in the PR description. + +It does sound like a lot, but those best practices are here to save time +overall and continuously improve the quality of the project, which is +something everyone benefits from. + +#### Get started + +The fairly standard code contribution process looks like that: + +1. [Fork the project][fork]. +2. Make your changes, commit on any branch you like. +3. [Open up a pull request][pull-request] +4. Review, potential ask for changes. +5. Merge. You're in! + +Feel free to ask for help! You can create draft pull requests to gather +some early feedback! + +#### Run the tests + +You can run tests for go-toml using Go's test tool: `go test ./...`. +When creating a pull requests, all tests will be ran on Linux on a few Go +versions (Travis CI), and on Windows using the latest Go version +(AppVeyor). + +#### Style + +Try to look around and follow the same format and structure as the rest of +the code. We enforce using `go fmt` on the whole code base. + +--- + +### Maintainers-only + +#### Merge pull request + +Checklist: + +* Passing CI. +* Does not introduce backward-incompatible changes (unless discussed). +* Has relevant doc changes. +* Has relevant unit tests. + +1. Merge using "squash and merge". +2. Make sure to edit the commit message to keep all the useful information + nice and clean. +3. Make sure the commit title is clear and contains the PR number (#123). + +#### New release + +1. Go to [releases][releases]. Click on "X commits to master since this + release". +2. Make note of all the changes. Look for backward incompatible changes, + new features, and bug fixes. +3. Pick the new version using the above and semver. +4. Create a [new release][new-release]. +5. Follow the same format as [1.1.0][release-110]. + +[issues-tracker]: https://github.com/pelletier/go-toml/issues +[bug-report]: https://github.com/pelletier/go-toml/issues/new?template=bug_report.md +[pkg.go.dev]: https://pkg.go.dev/github.com/pelletier/go-toml +[readme]: ./README.md +[fork]: https://help.github.com/articles/fork-a-repo +[pull-request]: https://help.github.com/en/articles/creating-a-pull-request +[releases]: https://github.com/pelletier/go-toml/releases +[new-release]: https://github.com/pelletier/go-toml/releases/new +[release-110]: https://github.com/pelletier/go-toml/releases/tag/v1.1.0 diff --git a/vendor/github.com/pelletier/go-toml/Dockerfile b/vendor/github.com/pelletier/go-toml/Dockerfile new file mode 100644 index 000000000..fffdb0166 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/Dockerfile @@ -0,0 +1,11 @@ +FROM golang:1.12-alpine3.9 as builder +WORKDIR /go/src/github.com/pelletier/go-toml +COPY . . +ENV CGO_ENABLED=0 +ENV GOOS=linux +RUN go install ./... + +FROM scratch +COPY --from=builder /go/bin/tomll /usr/bin/tomll +COPY --from=builder /go/bin/tomljson /usr/bin/tomljson +COPY --from=builder /go/bin/jsontoml /usr/bin/jsontoml diff --git a/vendor/github.com/pelletier/go-toml/LICENSE b/vendor/github.com/pelletier/go-toml/LICENSE new file mode 100644 index 000000000..f414553c2 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/LICENSE @@ -0,0 +1,247 @@ +The bulk of github.com/pelletier/go-toml is distributed under the MIT license +(see below), with the exception of localtime.go and localtime.test.go. +Those two files have been copied over from Google's civil library at revision +ed46f5086358513cf8c25f8e3f022cb838a49d66, and are distributed under the Apache +2.0 license (see below). + + +github.com/pelletier/go-toml: + + +The MIT License (MIT) + +Copyright (c) 2013 - 2021 Thomas Pelletier, Eric Anderton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +localtime.go, localtime_test.go: + +Originals: + https://raw.githubusercontent.com/googleapis/google-cloud-go/ed46f5086358513cf8c25f8e3f022cb838a49d66/civil/civil.go + https://raw.githubusercontent.com/googleapis/google-cloud-go/ed46f5086358513cf8c25f8e3f022cb838a49d66/civil/civil_test.go +Changes: + * Renamed files from civil* to localtime*. + * Package changed from civil to toml. + * 'Local' prefix added to all structs. +License: + https://raw.githubusercontent.com/googleapis/google-cloud-go/ed46f5086358513cf8c25f8e3f022cb838a49d66/LICENSE + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/pelletier/go-toml/Makefile b/vendor/github.com/pelletier/go-toml/Makefile new file mode 100644 index 000000000..9e4503aea --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/Makefile @@ -0,0 +1,29 @@ +export CGO_ENABLED=0 +go := go +go.goos ?= $(shell echo `go version`|cut -f4 -d ' '|cut -d '/' -f1) +go.goarch ?= $(shell echo `go version`|cut -f4 -d ' '|cut -d '/' -f2) + +out.tools := tomll tomljson jsontoml +out.dist := $(out.tools:=_$(go.goos)_$(go.goarch).tar.xz) +sources := $(wildcard **/*.go) + + +.PHONY: +tools: $(out.tools) + +$(out.tools): $(sources) + GOOS=$(go.goos) GOARCH=$(go.goarch) $(go) build ./cmd/$@ + +.PHONY: +dist: $(out.dist) + +$(out.dist):%_$(go.goos)_$(go.goarch).tar.xz: % + if [ "$(go.goos)" = "windows" ]; then \ + tar -cJf $@ $^.exe; \ + else \ + tar -cJf $@ $^; \ + fi + +.PHONY: +clean: + rm -rf $(out.tools) $(out.dist) diff --git a/vendor/github.com/pelletier/go-toml/PULL_REQUEST_TEMPLATE.md b/vendor/github.com/pelletier/go-toml/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..041cdc4a2 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,5 @@ +**Issue:** add link to pelletier/go-toml issue here + +Explanation of what this pull request does. + +More detailed description of the decisions being made and the reasons why (if the patch is non-trivial). diff --git a/vendor/github.com/pelletier/go-toml/README.md b/vendor/github.com/pelletier/go-toml/README.md new file mode 100644 index 000000000..6c061712b --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/README.md @@ -0,0 +1,176 @@ +# go-toml + +Go library for the [TOML](https://toml.io/) format. + +This library supports TOML version +[v1.0.0-rc.3](https://toml.io/en/v1.0.0-rc.3) + +[![Go Reference](https://pkg.go.dev/badge/github.com/pelletier/go-toml.svg)](https://pkg.go.dev/github.com/pelletier/go-toml) +[![license](https://img.shields.io/github/license/pelletier/go-toml.svg)](https://github.com/pelletier/go-toml/blob/master/LICENSE) +[![Build Status](https://dev.azure.com/pelletierthomas/go-toml-ci/_apis/build/status/pelletier.go-toml?branchName=master)](https://dev.azure.com/pelletierthomas/go-toml-ci/_build/latest?definitionId=1&branchName=master) +[![codecov](https://codecov.io/gh/pelletier/go-toml/branch/master/graph/badge.svg)](https://codecov.io/gh/pelletier/go-toml) +[![Go Report Card](https://goreportcard.com/badge/github.com/pelletier/go-toml)](https://goreportcard.com/report/github.com/pelletier/go-toml) +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fpelletier%2Fgo-toml.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fpelletier%2Fgo-toml?ref=badge_shield) + + +## Development status + +**ℹī¸ Consider go-toml v2!** + +The next version of go-toml is in [active development][v2-dev], and +[nearing completion][v2-map]. + +Though technically in beta, v2 is already more tested, [fixes bugs][v1-bugs], +and [much faster][v2-bench]. If you only need reading and writing TOML documents +(majority of cases), those features are implemented and the API unlikely to +change. + +The remaining features (Document structure editing and tooling) will be added +shortly. While pull-requests are welcome on v1, no active development is +expected on it. When v2.0.0 is released, v1 will be deprecated. + +👉 [go-toml v2][v2] + +[v2]: https://github.com/pelletier/go-toml/tree/v2 +[v2-map]: https://github.com/pelletier/go-toml/discussions/506 +[v2-dev]: https://github.com/pelletier/go-toml/tree/v2 +[v1-bugs]: https://github.com/pelletier/go-toml/issues?q=is%3Aissue+is%3Aopen+label%3Av2-fixed +[v2-bench]: https://github.com/pelletier/go-toml/tree/v2#benchmarks + +## Features + +Go-toml provides the following features for using data parsed from TOML documents: + +* Load TOML documents from files and string data +* Easily navigate TOML structure using Tree +* Marshaling and unmarshaling to and from data structures +* Line & column position data for all parsed elements +* [Query support similar to JSON-Path](query/) +* Syntax errors contain line and column numbers + +## Import + +```go +import "github.com/pelletier/go-toml" +``` + +## Usage example + +Read a TOML document: + +```go +config, _ := toml.Load(` +[postgres] +user = "pelletier" +password = "mypassword"`) +// retrieve data directly +user := config.Get("postgres.user").(string) + +// or using an intermediate object +postgresConfig := config.Get("postgres").(*toml.Tree) +password := postgresConfig.Get("password").(string) +``` + +Or use Unmarshal: + +```go +type Postgres struct { + User string + Password string +} +type Config struct { + Postgres Postgres +} + +doc := []byte(` +[Postgres] +User = "pelletier" +Password = "mypassword"`) + +config := Config{} +toml.Unmarshal(doc, &config) +fmt.Println("user=", config.Postgres.User) +``` + +Or use a query: + +```go +// use a query to gather elements without walking the tree +q, _ := query.Compile("$..[user,password]") +results := q.Execute(config) +for ii, item := range results.Values() { + fmt.Printf("Query result %d: %v\n", ii, item) +} +``` + +## Documentation + +The documentation and additional examples are available at +[pkg.go.dev](https://pkg.go.dev/github.com/pelletier/go-toml). + +## Tools + +Go-toml provides three handy command line tools: + +* `tomll`: Reads TOML files and lints them. + + ``` + go install github.com/pelletier/go-toml/cmd/tomll + tomll --help + ``` +* `tomljson`: Reads a TOML file and outputs its JSON representation. + + ``` + go install github.com/pelletier/go-toml/cmd/tomljson + tomljson --help + ``` + + * `jsontoml`: Reads a JSON file and outputs a TOML representation. + + ``` + go install github.com/pelletier/go-toml/cmd/jsontoml + jsontoml --help + ``` + +### Docker image + +Those tools are also available as a Docker image from +[dockerhub](https://hub.docker.com/r/pelletier/go-toml). For example, to +use `tomljson`: + +``` +docker run -v $PWD:/workdir pelletier/go-toml tomljson /workdir/example.toml +``` + +Only master (`latest`) and tagged versions are published to dockerhub. You +can build your own image as usual: + +``` +docker build -t go-toml . +``` + +## Contribute + +Feel free to report bugs and patches using GitHub's pull requests system on +[pelletier/go-toml](https://github.com/pelletier/go-toml). Any feedback would be +much appreciated! + +### Run tests + +`go test ./...` + +### Fuzzing + +The script `./fuzz.sh` is available to +run [go-fuzz](https://github.com/dvyukov/go-fuzz) on go-toml. + +## Versioning + +Go-toml follows [Semantic Versioning](http://semver.org/). The supported version +of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of +this document. The last two major versions of Go are supported +(see [Go Release Policy](https://golang.org/doc/devel/release.html#policy)). + +## License + +The MIT License (MIT) + Apache 2.0. Read [LICENSE](LICENSE). diff --git a/vendor/github.com/pelletier/go-toml/azure-pipelines.yml b/vendor/github.com/pelletier/go-toml/azure-pipelines.yml new file mode 100644 index 000000000..4af198b4d --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/azure-pipelines.yml @@ -0,0 +1,188 @@ +trigger: +- master + +stages: +- stage: run_checks + displayName: "Check" + dependsOn: [] + jobs: + - job: fmt + displayName: "fmt" + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go 1.16" + inputs: + version: "1.16" + - task: Go@0 + displayName: "go fmt ./..." + inputs: + command: 'custom' + customCommand: 'fmt' + arguments: './...' + - job: coverage + displayName: "coverage" + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go 1.16" + inputs: + version: "1.16" + - task: Go@0 + displayName: "Generate coverage" + inputs: + command: 'test' + arguments: "-race -coverprofile=coverage.txt -covermode=atomic" + - task: Bash@3 + inputs: + targetType: 'inline' + script: 'bash <(curl -s https://codecov.io/bash) -t ${CODECOV_TOKEN}' + env: + CODECOV_TOKEN: $(CODECOV_TOKEN) + - job: benchmark + displayName: "benchmark" + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go 1.16" + inputs: + version: "1.16" + - script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/" + - task: Bash@3 + inputs: + filePath: './benchmark.sh' + arguments: "master $(Build.Repository.Uri)" + + - job: go_unit_tests + displayName: "unit tests" + strategy: + matrix: + linux 1.16: + goVersion: '1.16' + imageName: 'ubuntu-latest' + mac 1.16: + goVersion: '1.16' + imageName: 'macOS-latest' + windows 1.16: + goVersion: '1.16' + imageName: 'windows-latest' + linux 1.15: + goVersion: '1.15' + imageName: 'ubuntu-latest' + mac 1.15: + goVersion: '1.15' + imageName: 'macOS-latest' + windows 1.15: + goVersion: '1.15' + imageName: 'windows-latest' + pool: + vmImage: $(imageName) + steps: + - task: GoTool@0 + displayName: "Install Go $(goVersion)" + inputs: + version: $(goVersion) + - task: Go@0 + displayName: "go test ./..." + inputs: + command: 'test' + arguments: './...' +- stage: build_binaries + displayName: "Build binaries" + dependsOn: run_checks + jobs: + - job: build_binary + displayName: "Build binary" + strategy: + matrix: + linux_amd64: + GOOS: linux + GOARCH: amd64 + darwin_amd64: + GOOS: darwin + GOARCH: amd64 + windows_amd64: + GOOS: windows + GOARCH: amd64 + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go" + inputs: + version: 1.16 + - task: Bash@3 + inputs: + targetType: inline + script: "make dist" + env: + go.goos: $(GOOS) + go.goarch: $(GOARCH) + - task: CopyFiles@2 + inputs: + sourceFolder: '$(Build.SourcesDirectory)' + contents: '*.tar.xz' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: '$(Build.ArtifactStagingDirectory)' + artifactName: binaries +- stage: build_binaries_manifest + displayName: "Build binaries manifest" + dependsOn: build_binaries + jobs: + - job: build_manifest + displayName: "Build binaries manifest" + steps: + - task: DownloadBuildArtifacts@0 + inputs: + buildType: 'current' + downloadType: 'single' + artifactName: 'binaries' + downloadPath: '$(Build.SourcesDirectory)' + - task: Bash@3 + inputs: + targetType: inline + script: "cd binaries && sha256sum --binary *.tar.xz | tee $(Build.ArtifactStagingDirectory)/sha256sums.txt" + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: '$(Build.ArtifactStagingDirectory)' + artifactName: manifest + +- stage: build_docker_image + displayName: "Build Docker image" + dependsOn: run_checks + jobs: + - job: build + displayName: "Build" + pool: + vmImage: ubuntu-latest + steps: + - task: Docker@2 + inputs: + command: 'build' + Dockerfile: 'Dockerfile' + buildContext: '.' + addPipelineData: false + +- stage: publish_docker_image + displayName: "Publish Docker image" + dependsOn: build_docker_image + condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'master')) + jobs: + - job: publish + displayName: "Publish" + pool: + vmImage: ubuntu-latest + steps: + - task: Docker@2 + inputs: + containerRegistry: 'DockerHub' + repository: 'pelletier/go-toml' + command: 'buildAndPush' + Dockerfile: 'Dockerfile' + buildContext: '.' + tags: 'latest' diff --git a/vendor/github.com/pelletier/go-toml/benchmark.sh b/vendor/github.com/pelletier/go-toml/benchmark.sh new file mode 100644 index 000000000..a69d3040f --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -ex + +reference_ref=${1:-master} +reference_git=${2:-.} + +if ! `hash benchstat 2>/dev/null`; then + echo "Installing benchstat" + go get golang.org/x/perf/cmd/benchstat +fi + +tempdir=`mktemp -d /tmp/go-toml-benchmark-XXXXXX` +ref_tempdir="${tempdir}/ref" +ref_benchmark="${ref_tempdir}/benchmark-`echo -n ${reference_ref}|tr -s '/' '-'`.txt" +local_benchmark="`pwd`/benchmark-local.txt" + +echo "=== ${reference_ref} (${ref_tempdir})" +git clone ${reference_git} ${ref_tempdir} >/dev/null 2>/dev/null +pushd ${ref_tempdir} >/dev/null +git checkout ${reference_ref} >/dev/null 2>/dev/null +go test -bench=. -benchmem | tee ${ref_benchmark} +cd benchmark +go test -bench=. -benchmem | tee -a ${ref_benchmark} +popd >/dev/null + +echo "" +echo "=== local" +go test -bench=. -benchmem | tee ${local_benchmark} +cd benchmark +go test -bench=. -benchmem | tee -a ${local_benchmark} + +echo "" +echo "=== diff" +benchstat -delta-test=none ${ref_benchmark} ${local_benchmark} diff --git a/vendor/github.com/pelletier/go-toml/doc.go b/vendor/github.com/pelletier/go-toml/doc.go new file mode 100644 index 000000000..a1406a32b --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/doc.go @@ -0,0 +1,23 @@ +// Package toml is a TOML parser and manipulation library. +// +// This version supports the specification as described in +// https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md +// +// Marshaling +// +// Go-toml can marshal and unmarshal TOML documents from and to data +// structures. +// +// TOML document as a tree +// +// Go-toml can operate on a TOML document as a tree. Use one of the Load* +// functions to parse TOML data and obtain a Tree instance, then one of its +// methods to manipulate the tree. +// +// JSONPath-like queries +// +// The package github.com/pelletier/go-toml/query implements a system +// similar to JSONPath to quickly retrieve elements of a TOML document using a +// single expression. See the package documentation for more information. +// +package toml diff --git a/vendor/github.com/pelletier/go-toml/example-crlf.toml b/vendor/github.com/pelletier/go-toml/example-crlf.toml new file mode 100644 index 000000000..780d9c68f --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/example-crlf.toml @@ -0,0 +1,30 @@ +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it +score = 4e-08 # to make sure leading zeroes in exponent parts of floats are supported \ No newline at end of file diff --git a/vendor/github.com/pelletier/go-toml/example.toml b/vendor/github.com/pelletier/go-toml/example.toml new file mode 100644 index 000000000..f45bf88b8 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/example.toml @@ -0,0 +1,30 @@ +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it +score = 4e-08 # to make sure leading zeroes in exponent parts of floats are supported \ No newline at end of file diff --git a/vendor/github.com/pelletier/go-toml/fuzz.go b/vendor/github.com/pelletier/go-toml/fuzz.go new file mode 100644 index 000000000..14570c8d3 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/fuzz.go @@ -0,0 +1,31 @@ +// +build gofuzz + +package toml + +func Fuzz(data []byte) int { + tree, err := LoadBytes(data) + if err != nil { + if tree != nil { + panic("tree must be nil if there is an error") + } + return 0 + } + + str, err := tree.ToTomlString() + if err != nil { + if str != "" { + panic(`str must be "" if there is an error`) + } + panic(err) + } + + tree, err = Load(str) + if err != nil { + if tree != nil { + panic("tree must be nil if there is an error") + } + return 0 + } + + return 1 +} diff --git a/vendor/github.com/pelletier/go-toml/fuzz.sh b/vendor/github.com/pelletier/go-toml/fuzz.sh new file mode 100644 index 000000000..3204b4c44 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/fuzz.sh @@ -0,0 +1,15 @@ +#! /bin/sh +set -eu + +go get github.com/dvyukov/go-fuzz/go-fuzz +go get github.com/dvyukov/go-fuzz/go-fuzz-build + +if [ ! -e toml-fuzz.zip ]; then + go-fuzz-build github.com/pelletier/go-toml +fi + +rm -fr fuzz +mkdir -p fuzz/corpus +cp *.toml fuzz/corpus + +go-fuzz -bin=toml-fuzz.zip -workdir=fuzz diff --git a/vendor/github.com/pelletier/go-toml/keysparsing.go b/vendor/github.com/pelletier/go-toml/keysparsing.go new file mode 100644 index 000000000..e091500b2 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/keysparsing.go @@ -0,0 +1,112 @@ +// Parsing keys handling both bare and quoted keys. + +package toml + +import ( + "errors" + "fmt" +) + +// Convert the bare key group string to an array. +// The input supports double quotation and single quotation, +// but escape sequences are not supported. Lexers must unescape them beforehand. +func parseKey(key string) ([]string, error) { + runes := []rune(key) + var groups []string + + if len(key) == 0 { + return nil, errors.New("empty key") + } + + idx := 0 + for idx < len(runes) { + for ; idx < len(runes) && isSpace(runes[idx]); idx++ { + // skip leading whitespace + } + if idx >= len(runes) { + break + } + r := runes[idx] + if isValidBareChar(r) { + // parse bare key + startIdx := idx + endIdx := -1 + idx++ + for idx < len(runes) { + r = runes[idx] + if isValidBareChar(r) { + idx++ + } else if r == '.' { + endIdx = idx + break + } else if isSpace(r) { + endIdx = idx + for ; idx < len(runes) && isSpace(runes[idx]); idx++ { + // skip trailing whitespace + } + if idx < len(runes) && runes[idx] != '.' { + return nil, fmt.Errorf("invalid key character after whitespace: %c", runes[idx]) + } + break + } else { + return nil, fmt.Errorf("invalid bare key character: %c", r) + } + } + if endIdx == -1 { + endIdx = idx + } + groups = append(groups, string(runes[startIdx:endIdx])) + } else if r == '\'' { + // parse single quoted key + idx++ + startIdx := idx + for { + if idx >= len(runes) { + return nil, fmt.Errorf("unclosed single-quoted key") + } + r = runes[idx] + if r == '\'' { + groups = append(groups, string(runes[startIdx:idx])) + idx++ + break + } + idx++ + } + } else if r == '"' { + // parse double quoted key + idx++ + startIdx := idx + for { + if idx >= len(runes) { + return nil, fmt.Errorf("unclosed double-quoted key") + } + r = runes[idx] + if r == '"' { + groups = append(groups, string(runes[startIdx:idx])) + idx++ + break + } + idx++ + } + } else if r == '.' { + idx++ + if idx >= len(runes) { + return nil, fmt.Errorf("unexpected end of key") + } + r = runes[idx] + if !isValidBareChar(r) && r != '\'' && r != '"' && r != ' ' { + return nil, fmt.Errorf("expecting key part after dot") + } + } else { + return nil, fmt.Errorf("invalid key character: %c", r) + } + } + if len(groups) == 0 { + return nil, fmt.Errorf("empty key") + } + return groups, nil +} + +func isValidBareChar(r rune) bool { + return isAlphanumeric(r) || r == '-' || isDigit(r) +} diff --git a/vendor/github.com/pelletier/go-toml/lexer.go b/vendor/github.com/pelletier/go-toml/lexer.go new file mode 100644 index 000000000..313908e3e --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/lexer.go @@ -0,0 +1,1031 @@ +// TOML lexer. +// +// Written using the principles developed by Rob Pike in +// http://www.youtube.com/watch?v=HxaD_trXwRE + +package toml + +import ( + "bytes" + "errors" + "fmt" + "strconv" + "strings" +) + +// Define state functions +type tomlLexStateFn func() tomlLexStateFn + +// Define lexer +type tomlLexer struct { + inputIdx int + input []rune // Textual source + currentTokenStart int + currentTokenStop int + tokens []token + brackets []rune + line int + col int + endbufferLine int + endbufferCol int +} + +// Basic read operations on input + +func (l *tomlLexer) read() rune { + r := l.peek() + if r == '\n' { + l.endbufferLine++ + l.endbufferCol = 1 + } else { + l.endbufferCol++ + } + l.inputIdx++ + return r +} + +func (l *tomlLexer) next() rune { + r := l.read() + + if r != eof { + l.currentTokenStop++ + } + return r +} + +func (l *tomlLexer) ignore() { + l.currentTokenStart = l.currentTokenStop + l.line = l.endbufferLine + l.col = l.endbufferCol +} + +func (l *tomlLexer) skip() { + l.next() + l.ignore() +} + +func (l *tomlLexer) fastForward(n int) { + for i := 0; i < n; i++ { + l.next() + } +} + +func (l *tomlLexer) emitWithValue(t tokenType, value string) { + l.tokens = append(l.tokens, token{ + Position: Position{l.line, l.col}, + typ: t, + val: value, + }) + l.ignore() +} + +func (l *tomlLexer) emit(t tokenType) { + l.emitWithValue(t, string(l.input[l.currentTokenStart:l.currentTokenStop])) +} + +func (l *tomlLexer) peek() rune { + if l.inputIdx >= len(l.input) { + return eof + } + return l.input[l.inputIdx] +} + +func (l *tomlLexer) peekString(size int) string { + maxIdx := len(l.input) + upperIdx := l.inputIdx + size // FIXME: potential overflow + if upperIdx > maxIdx { + upperIdx = maxIdx + } + return string(l.input[l.inputIdx:upperIdx]) +} + +func (l *tomlLexer) follow(next string) bool { + return next == l.peekString(len(next)) +} + +// Error management + +func (l *tomlLexer) errorf(format string, args ...interface{}) tomlLexStateFn { + l.tokens = append(l.tokens, token{ + Position: Position{l.line, l.col}, + typ: tokenError, + val: fmt.Sprintf(format, args...), + }) + return nil +} + +// State functions + +func (l *tomlLexer) lexVoid() tomlLexStateFn { + for { + next := l.peek() + switch next { + case '}': // after '{' + return l.lexRightCurlyBrace + case '[': + return l.lexTableKey + case '#': + return l.lexComment(l.lexVoid) + case '=': + return l.lexEqual + case '\r': + fallthrough + case '\n': + l.skip() + continue + } + + if isSpace(next) { + l.skip() + } + + if isKeyStartChar(next) { + return l.lexKey + } + + if next == eof { + l.next() + break + } + } + + l.emit(tokenEOF) + return nil +} + +func (l *tomlLexer) lexRvalue() tomlLexStateFn { + for { + next := l.peek() + switch next { + case '.': + return l.errorf("cannot start float with a dot") + case '=': + return l.lexEqual + case '[': + return l.lexLeftBracket + case ']': + return l.lexRightBracket + case '{': + return l.lexLeftCurlyBrace + case '}': + return l.lexRightCurlyBrace + case '#': + return l.lexComment(l.lexRvalue) + case '"': + return l.lexString + case '\'': + return l.lexLiteralString + case ',': + return l.lexComma + case '\r': + fallthrough + case '\n': + l.skip() + if len(l.brackets) > 0 && l.brackets[len(l.brackets)-1] == '[' { + return l.lexRvalue + } + return l.lexVoid + } + + if l.follow("true") { + return l.lexTrue + } + + if l.follow("false") { + return l.lexFalse + } + + if l.follow("inf") { + return l.lexInf + } + + if l.follow("nan") { + return l.lexNan + } + + if isSpace(next) { + l.skip() + continue + } + + if next == eof { + l.next() + break + } + + if next == '+' || next == '-' { + return l.lexNumber + } + + if isDigit(next) { + return l.lexDateTimeOrNumber + } + + return l.errorf("no value can start with %c", next) + } + + l.emit(tokenEOF) + return nil +} + +func (l *tomlLexer) lexDateTimeOrNumber() tomlLexStateFn { + // Could be either a date/time, or a digit. + // The options for date/times are: + // YYYY-... => date or date-time + // HH:... => time + // Anything else should be a number. + + lookAhead := l.peekString(5) + if len(lookAhead) < 3 { + return l.lexNumber() + } + + for idx, r := range lookAhead { + if !isDigit(r) { + if idx == 2 && r == ':' { + return l.lexDateTimeOrTime() + } + if idx == 4 && r == '-' { + return l.lexDateTimeOrTime() + } + return l.lexNumber() + } + } + return l.lexNumber() +} + +func (l *tomlLexer) lexLeftCurlyBrace() tomlLexStateFn { + l.next() + l.emit(tokenLeftCurlyBrace) + l.brackets = append(l.brackets, '{') + return l.lexVoid +} + +func (l *tomlLexer) lexRightCurlyBrace() tomlLexStateFn { + l.next() + l.emit(tokenRightCurlyBrace) + if len(l.brackets) == 0 || l.brackets[len(l.brackets)-1] != '{' { + return l.errorf("cannot have '}' here") + } + l.brackets = l.brackets[:len(l.brackets)-1] + return l.lexRvalue +} + +func (l *tomlLexer) lexDateTimeOrTime() tomlLexStateFn { + // Example matches: + // 1979-05-27T07:32:00Z + // 1979-05-27T00:32:00-07:00 + // 1979-05-27T00:32:00.999999-07:00 + // 1979-05-27 07:32:00Z + // 1979-05-27 00:32:00-07:00 + // 1979-05-27 00:32:00.999999-07:00 + // 1979-05-27T07:32:00 + // 1979-05-27T00:32:00.999999 + // 1979-05-27 07:32:00 + // 1979-05-27 00:32:00.999999 + // 1979-05-27 + // 07:32:00 + // 00:32:00.999999 + + // we already know those two are digits + l.next() + l.next() + + // Got 2 digits. At that point it could be either a time or a date(-time). + + r := l.next() + if r == ':' { + return l.lexTime() + } + + return l.lexDateTime() +} + +func (l *tomlLexer) lexDateTime() tomlLexStateFn { + // This state accepts an offset date-time, a local date-time, or a local date. + // + // v--- cursor + // 1979-05-27T07:32:00Z + // 1979-05-27T00:32:00-07:00 + // 1979-05-27T00:32:00.999999-07:00 + // 1979-05-27 07:32:00Z + // 1979-05-27 00:32:00-07:00 + // 1979-05-27 00:32:00.999999-07:00 + // 1979-05-27T07:32:00 + // 1979-05-27T00:32:00.999999 + // 1979-05-27 07:32:00 + // 1979-05-27 00:32:00.999999 + // 1979-05-27 + + // date + + // already checked by lexRvalue + l.next() // digit + l.next() // - + + for i := 0; i < 2; i++ { + r := l.next() + if !isDigit(r) { + return l.errorf("invalid month digit in date: %c", r) + } + } + + r := l.next() + if r != '-' { + return l.errorf("expected - to separate month of a date, not %c", r) + } + + for i := 0; i < 2; i++ { + r := l.next() + if !isDigit(r) { + return l.errorf("invalid day digit in date: %c", r) + } + } + + l.emit(tokenLocalDate) + + r = l.peek() + + if r == eof { + + return l.lexRvalue + } + + if r != ' ' && r != 'T' { + return l.errorf("incorrect date/time separation character: %c", r) + } + + if r == ' ' { + lookAhead := l.peekString(3)[1:] + if len(lookAhead) < 2 { + return l.lexRvalue + } + for _, r := range lookAhead { + if !isDigit(r) { + return l.lexRvalue + } + } + } + + l.skip() // skip the T or ' ' + + // time + + for i := 0; i < 2; i++ { + r := l.next() + if !isDigit(r) { + return l.errorf("invalid hour digit in time: %c", r) + } + } + + r = l.next() + if r != ':' { + return l.errorf("time hour/minute separator should be :, not %c", r) + } + + for i := 0; i < 2; i++ { + r := l.next() + if !isDigit(r) { + return l.errorf("invalid minute digit in time: %c", r) + } + } + + r = l.next() + if r != ':' { + return l.errorf("time minute/second separator should be :, not %c", r) + } + + for i := 0; i < 2; i++ { + r := l.next() + if !isDigit(r) { + return l.errorf("invalid second digit in time: %c", r) + } + } + + r = l.peek() + if r == '.' { + l.next() + r := l.next() + if !isDigit(r) { + return l.errorf("expected at least one digit in time's fraction, not %c", r) + } + + for { + r := l.peek() + if !isDigit(r) { + break + } + l.next() + } + } + + l.emit(tokenLocalTime) + + return l.lexTimeOffset + +} + +func (l *tomlLexer) lexTimeOffset() tomlLexStateFn { + // potential offset + + // Z + // -07:00 + // +07:00 + // nothing + + r := l.peek() + + if r == 'Z' { + l.next() + l.emit(tokenTimeOffset) + } else if r == '+' || r == '-' { + l.next() + + for i := 0; i < 2; i++ { + r := l.next() + if !isDigit(r) { + return l.errorf("invalid hour digit in time offset: %c", r) + } + } + + r = l.next() + if r != ':' { + return l.errorf("time offset hour/minute separator should be :, not %c", r) + } + + for i := 0; i < 2; i++ { + r := l.next() + if !isDigit(r) { + return l.errorf("invalid minute digit in time offset: %c", r) + } + } + + l.emit(tokenTimeOffset) + } + + return l.lexRvalue +} + +func (l *tomlLexer) lexTime() tomlLexStateFn { + // v--- cursor + // 07:32:00 + // 00:32:00.999999 + + for i := 0; i < 2; i++ { + r := l.next() + if !isDigit(r) { + return l.errorf("invalid minute digit in time: %c", r) + } + } + + r := l.next() + if r != ':' { + return l.errorf("time minute/second separator should be :, not %c", r) + } + + for i := 0; i < 2; i++ { + r := l.next() + if !isDigit(r) { + return l.errorf("invalid second digit in time: %c", r) + } + } + + r = l.peek() + if r == '.' { + l.next() + r := l.next() + if !isDigit(r) { + return l.errorf("expected at least one digit in time's fraction, not %c", r) + } + + for { + r := l.peek() + if !isDigit(r) { + break + } + l.next() + } + } + + l.emit(tokenLocalTime) + return l.lexRvalue + +} + +func (l *tomlLexer) lexTrue() tomlLexStateFn { + l.fastForward(4) + l.emit(tokenTrue) + return l.lexRvalue +} + +func (l *tomlLexer) lexFalse() tomlLexStateFn { + l.fastForward(5) + l.emit(tokenFalse) + return l.lexRvalue +} + +func (l *tomlLexer) lexInf() tomlLexStateFn { + l.fastForward(3) + l.emit(tokenInf) + return l.lexRvalue +} + +func (l *tomlLexer) lexNan() tomlLexStateFn { + l.fastForward(3) + l.emit(tokenNan) + return l.lexRvalue +} + +func (l *tomlLexer) lexEqual() tomlLexStateFn { + l.next() + l.emit(tokenEqual) + return l.lexRvalue +} + +func (l *tomlLexer) lexComma() tomlLexStateFn { + l.next() + l.emit(tokenComma) + if len(l.brackets) > 0 && l.brackets[len(l.brackets)-1] == '{' { + return l.lexVoid + } + return l.lexRvalue +} + +// Parse the key and emits its value without escape sequences. +// bare keys, basic string keys and literal string keys are supported. +func (l *tomlLexer) lexKey() tomlLexStateFn { + var sb strings.Builder + + for r := l.peek(); isKeyChar(r) || r == '\n' || r == '\r'; r = l.peek() { + if r == '"' { + l.next() + str, err := l.lexStringAsString(`"`, false, true) + if err != nil { + return l.errorf(err.Error()) + } + sb.WriteString("\"") + sb.WriteString(str) + sb.WriteString("\"") + l.next() + continue + } else if r == '\'' { + l.next() + str, err := l.lexLiteralStringAsString(`'`, false) + if err != nil { + return l.errorf(err.Error()) + } + sb.WriteString("'") + sb.WriteString(str) + sb.WriteString("'") + l.next() + continue + } else if r == '\n' { + return l.errorf("keys cannot contain new lines") + } else if isSpace(r) { + var str strings.Builder + str.WriteString(" ") + + // skip trailing whitespace + l.next() + for r = l.peek(); isSpace(r); r = l.peek() { + str.WriteRune(r) + l.next() + } + // break loop if not a dot + if r != '.' { + break + } + str.WriteString(".") + // skip trailing whitespace after dot + l.next() + for r = l.peek(); isSpace(r); r = l.peek() { + str.WriteRune(r) + l.next() + } + sb.WriteString(str.String()) + continue + } else if r == '.' { + // skip + } else if !isValidBareChar(r) { + return l.errorf("keys cannot contain %c character", r) + } + sb.WriteRune(r) + l.next() + } + l.emitWithValue(tokenKey, sb.String()) + return l.lexVoid +} + +func (l *tomlLexer) lexComment(previousState tomlLexStateFn) tomlLexStateFn { + return func() tomlLexStateFn { + for next := l.peek(); next != '\n' && next != eof; next = l.peek() { + if next == '\r' && l.follow("\r\n") { + break + } + l.next() + } + l.ignore() + return previousState + } +} + +func (l *tomlLexer) lexLeftBracket() tomlLexStateFn { + l.next() + l.emit(tokenLeftBracket) + l.brackets = append(l.brackets, '[') + return l.lexRvalue +} + +func (l *tomlLexer) lexLiteralStringAsString(terminator string, discardLeadingNewLine bool) (string, error) { + var sb strings.Builder + + if discardLeadingNewLine { + if l.follow("\r\n") { + l.skip() + l.skip() + } else if l.peek() == '\n' { + l.skip() + } + } + + // find end of string + for { + if l.follow(terminator) { + return sb.String(), nil + } + + next := l.peek() + if next == eof { + break + } + sb.WriteRune(l.next()) + } + + return "", errors.New("unclosed string") +} + +func (l *tomlLexer) lexLiteralString() tomlLexStateFn { + l.skip() + + // handle special case for triple-quote + terminator := "'" + discardLeadingNewLine := false + if l.follow("''") { + l.skip() + l.skip() + terminator = "'''" + discardLeadingNewLine = true + } + + str, err := l.lexLiteralStringAsString(terminator, discardLeadingNewLine) + if err != nil { + return l.errorf(err.Error()) + } + + l.emitWithValue(tokenString, str) + l.fastForward(len(terminator)) + l.ignore() + return l.lexRvalue +} + +// Lex a string and return the results as a string. +// Terminator is the substring indicating the end of the token. +// The resulting string does not include the terminator. +func (l *tomlLexer) lexStringAsString(terminator string, discardLeadingNewLine, acceptNewLines bool) (string, error) { + var sb strings.Builder + + if discardLeadingNewLine { + if l.follow("\r\n") { + l.skip() + l.skip() + } else if l.peek() == '\n' { + l.skip() + } + } + + for { + if l.follow(terminator) { + return sb.String(), nil + } + + if l.follow("\\") { + l.next() + switch l.peek() { + case '\r': + fallthrough + case '\n': + fallthrough + case '\t': + fallthrough + case ' ': + // skip all whitespace chars following backslash + for strings.ContainsRune("\r\n\t ", l.peek()) { + l.next() + } + case '"': + sb.WriteString("\"") + l.next() + case 'n': + sb.WriteString("\n") + l.next() + case 'b': + sb.WriteString("\b") + l.next() + case 'f': + sb.WriteString("\f") + l.next() + case '/': + sb.WriteString("/") + l.next() + case 't': + sb.WriteString("\t") + l.next() + case 'r': + sb.WriteString("\r") + l.next() + case '\\': + sb.WriteString("\\") + l.next() + case 'u': + l.next() + var code strings.Builder + for i := 0; i < 4; i++ { + c := l.peek() + if !isHexDigit(c) { + return "", errors.New("unfinished unicode escape") + } + l.next() + code.WriteRune(c) + } + intcode, err := strconv.ParseInt(code.String(), 16, 32) + if err != nil { + return "", errors.New("invalid unicode escape: \\u" + code.String()) + } + sb.WriteRune(rune(intcode)) + case 'U': + l.next() + var code strings.Builder + for i := 0; i < 8; i++ { + c := l.peek() + if !isHexDigit(c) { + return "", errors.New("unfinished unicode escape") + } + l.next() + code.WriteRune(c) + } + intcode, err := strconv.ParseInt(code.String(), 16, 64) + if err != nil { + return "", errors.New("invalid unicode escape: \\U" + code.String()) + } + sb.WriteRune(rune(intcode)) + default: + return "", errors.New("invalid escape sequence: \\" + string(l.peek())) + } + } else { + r := l.peek() + + if 0x00 <= r && r <= 0x1F && r != '\t' && !(acceptNewLines && (r == '\n' || r == '\r')) { + return "", fmt.Errorf("unescaped control character %U", r) + } + l.next() + sb.WriteRune(r) + } + + if l.peek() == eof { + break + } + } + + return "", errors.New("unclosed string") +} + +func (l *tomlLexer) lexString() tomlLexStateFn { + l.skip() + + // handle special case for triple-quote + terminator := `"` + discardLeadingNewLine := false + acceptNewLines := false + if l.follow(`""`) { + l.skip() + l.skip() + terminator = `"""` + discardLeadingNewLine = true + acceptNewLines = true + } + + str, err := l.lexStringAsString(terminator, discardLeadingNewLine, acceptNewLines) + if err != nil { + return l.errorf(err.Error()) + } + + l.emitWithValue(tokenString, str) + l.fastForward(len(terminator)) + l.ignore() + return l.lexRvalue +} + +func (l *tomlLexer) lexTableKey() tomlLexStateFn { + l.next() + + if l.peek() == '[' { + // token '[[' signifies an array of tables + l.next() + l.emit(tokenDoubleLeftBracket) + return l.lexInsideTableArrayKey + } + // vanilla table key + l.emit(tokenLeftBracket) + return l.lexInsideTableKey +} + +// Parse the key till "]]", but only bare keys are supported +func (l *tomlLexer) lexInsideTableArrayKey() tomlLexStateFn { + for r := l.peek(); r != eof; r = l.peek() { + switch r { + case ']': + if l.currentTokenStop > l.currentTokenStart { + l.emit(tokenKeyGroupArray) + } + l.next() + if l.peek() != ']' { + break + } + l.next() + l.emit(tokenDoubleRightBracket) + return l.lexVoid + case '[': + return l.errorf("table array key cannot contain ']'") + default: + l.next() + } + } + return l.errorf("unclosed table array key") +} + +// Parse the key till "]" but only bare keys are supported +func (l *tomlLexer) lexInsideTableKey() tomlLexStateFn { + for r := l.peek(); r != eof; r = l.peek() { + switch r { + case ']': + if l.currentTokenStop > l.currentTokenStart { + l.emit(tokenKeyGroup) + } + l.next() + l.emit(tokenRightBracket) + return l.lexVoid + case '[': + return l.errorf("table key cannot contain ']'") + default: + l.next() + } + } + return l.errorf("unclosed table key") +} + +func (l *tomlLexer) lexRightBracket() tomlLexStateFn { + l.next() + l.emit(tokenRightBracket) + if len(l.brackets) == 0 || l.brackets[len(l.brackets)-1] != '[' { + return l.errorf("cannot have ']' here") + } + l.brackets = l.brackets[:len(l.brackets)-1] + return l.lexRvalue +} + +type validRuneFn func(r rune) bool + +func isValidHexRune(r rune) bool { + return r >= 'a' && r <= 'f' || + r >= 'A' && r <= 'F' || + r >= '0' && r <= '9' || + r == '_' +} + +func isValidOctalRune(r rune) bool { + return r >= '0' && r <= '7' || r == '_' +} + +func isValidBinaryRune(r rune) bool { + return r == '0' || r == '1' || r == '_' +} + +func (l *tomlLexer) lexNumber() tomlLexStateFn { + r := l.peek() + + if r == '0' { + follow := l.peekString(2) + if len(follow) == 2 { + var isValidRune validRuneFn + switch follow[1] { + case 'x': + isValidRune = isValidHexRune + case 'o': + isValidRune = isValidOctalRune + case 'b': + isValidRune = isValidBinaryRune + default: + if follow[1] >= 'a' && follow[1] <= 'z' || follow[1] >= 'A' && follow[1] <= 'Z' { + return l.errorf("unknown number base: %s. possible options are x (hex) o (octal) b (binary)", string(follow[1])) + } + } + + if isValidRune != nil { + l.next() + l.next() + digitSeen := false + for { + next := l.peek() + if !isValidRune(next) { + break + } + digitSeen = true + l.next() + } + + if !digitSeen { + return l.errorf("number needs at least one digit") + } + + l.emit(tokenInteger) + + return l.lexRvalue + } + } + } + + if r == '+' || r == '-' { + l.next() + if l.follow("inf") { + return l.lexInf + } + if l.follow("nan") { + return l.lexNan + } + } + + pointSeen := false + expSeen := false + digitSeen := false + for { + next := l.peek() + if next == '.' { + if pointSeen { + return l.errorf("cannot have two dots in one float") + } + l.next() + if !isDigit(l.peek()) { + return l.errorf("float cannot end with a dot") + } + pointSeen = true + } else if next == 'e' || next == 'E' { + expSeen = true + l.next() + r := l.peek() + if r == '+' || r == '-' { + l.next() + } + } else if isDigit(next) { + digitSeen = true + l.next() + } else if next == '_' { + l.next() + } else { + break + } + if pointSeen && !digitSeen { + return l.errorf("cannot start float with a dot") + } + } + + if !digitSeen { + return l.errorf("no digit in that number") + } + if pointSeen || expSeen { + l.emit(tokenFloat) + } else { + l.emit(tokenInteger) + } + return l.lexRvalue +} + +func (l *tomlLexer) run() { + for state := l.lexVoid; state != nil; { + state = state() + } +} + +// Entry point +func lexToml(inputBytes []byte) []token { + runes := bytes.Runes(inputBytes) + l := &tomlLexer{ + input: runes, + tokens: make([]token, 0, 256), + line: 1, + col: 1, + endbufferLine: 1, + endbufferCol: 1, + } + l.run() + return l.tokens +} diff --git a/vendor/github.com/pelletier/go-toml/localtime.go b/vendor/github.com/pelletier/go-toml/localtime.go new file mode 100644 index 000000000..9dfe4b9e6 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/localtime.go @@ -0,0 +1,287 @@ +// Implementation of TOML's local date/time. +// +// Copied over from Google's civil to avoid pulling all the Google dependencies. +// Originals: +// https://raw.githubusercontent.com/googleapis/google-cloud-go/ed46f5086358513cf8c25f8e3f022cb838a49d66/civil/civil.go +// Changes: +// * Renamed files from civil* to localtime*. +// * Package changed from civil to toml. +// * 'Local' prefix added to all structs. +// +// Copyright 2016 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package civil implements types for civil time, a time-zone-independent +// representation of time that follows the rules of the proleptic +// Gregorian calendar with exactly 24-hour days, 60-minute hours, and 60-second +// minutes. +// +// Because they lack location information, these types do not represent unique +// moments or intervals of time. Use time.Time for that purpose. +package toml + +import ( + "fmt" + "time" +) + +// A LocalDate represents a date (year, month, day). +// +// This type does not include location information, and therefore does not +// describe a unique 24-hour timespan. +type LocalDate struct { + Year int // Year (e.g., 2014). + Month time.Month // Month of the year (January = 1, ...). + Day int // Day of the month, starting at 1. +} + +// LocalDateOf returns the LocalDate in which a time occurs in that time's location. +func LocalDateOf(t time.Time) LocalDate { + var d LocalDate + d.Year, d.Month, d.Day = t.Date() + return d +} + +// ParseLocalDate parses a string in RFC3339 full-date format and returns the date value it represents. +func ParseLocalDate(s string) (LocalDate, error) { + t, err := time.Parse("2006-01-02", s) + if err != nil { + return LocalDate{}, err + } + return LocalDateOf(t), nil +} + +// String returns the date in RFC3339 full-date format. +func (d LocalDate) String() string { + return fmt.Sprintf("%04d-%02d-%02d", d.Year, d.Month, d.Day) +} + +// IsValid reports whether the date is valid. +func (d LocalDate) IsValid() bool { + return LocalDateOf(d.In(time.UTC)) == d +} + +// In returns the time corresponding to time 00:00:00 of the date in the location. +// +// In is always consistent with time.LocalDate, even when time.LocalDate returns a time +// on a different day. For example, if loc is America/Indiana/Vincennes, then both +// time.LocalDate(1955, time.May, 1, 0, 0, 0, 0, loc) +// and +// civil.LocalDate{Year: 1955, Month: time.May, Day: 1}.In(loc) +// return 23:00:00 on April 30, 1955. +// +// In panics if loc is nil. +func (d LocalDate) In(loc *time.Location) time.Time { + return time.Date(d.Year, d.Month, d.Day, 0, 0, 0, 0, loc) +} + +// AddDays returns the date that is n days in the future. +// n can also be negative to go into the past. +func (d LocalDate) AddDays(n int) LocalDate { + return LocalDateOf(d.In(time.UTC).AddDate(0, 0, n)) +} + +// DaysSince returns the signed number of days between the date and s, not including the end day. +// This is the inverse operation to AddDays. +func (d LocalDate) DaysSince(s LocalDate) (days int) { + // We convert to Unix time so we do not have to worry about leap seconds: + // Unix time increases by exactly 86400 seconds per day. + deltaUnix := d.In(time.UTC).Unix() - s.In(time.UTC).Unix() + return int(deltaUnix / 86400) +} + +// Before reports whether d1 occurs before d2. +func (d1 LocalDate) Before(d2 LocalDate) bool { + if d1.Year != d2.Year { + return d1.Year < d2.Year + } + if d1.Month != d2.Month { + return d1.Month < d2.Month + } + return d1.Day < d2.Day +} + +// After reports whether d1 occurs after d2. +func (d1 LocalDate) After(d2 LocalDate) bool { + return d2.Before(d1) +} + +// MarshalText implements the encoding.TextMarshaler interface. +// The output is the result of d.String(). +func (d LocalDate) MarshalText() ([]byte, error) { + return []byte(d.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// The date is expected to be a string in a format accepted by ParseLocalDate. +func (d *LocalDate) UnmarshalText(data []byte) error { + var err error + *d, err = ParseLocalDate(string(data)) + return err +} + +// A LocalTime represents a time with nanosecond precision. +// +// This type does not include location information, and therefore does not +// describe a unique moment in time. +// +// This type exists to represent the TIME type in storage-based APIs like BigQuery. +// Most operations on Times are unlikely to be meaningful. Prefer the LocalDateTime type. +type LocalTime struct { + Hour int // The hour of the day in 24-hour format; range [0-23] + Minute int // The minute of the hour; range [0-59] + Second int // The second of the minute; range [0-59] + Nanosecond int // The nanosecond of the second; range [0-999999999] +} + +// LocalTimeOf returns the LocalTime representing the time of day in which a time occurs +// in that time's location. It ignores the date. +func LocalTimeOf(t time.Time) LocalTime { + var tm LocalTime + tm.Hour, tm.Minute, tm.Second = t.Clock() + tm.Nanosecond = t.Nanosecond() + return tm +} + +// ParseLocalTime parses a string and returns the time value it represents. +// ParseLocalTime accepts an extended form of the RFC3339 partial-time format. After +// the HH:MM:SS part of the string, an optional fractional part may appear, +// consisting of a decimal point followed by one to nine decimal digits. +// (RFC3339 admits only one digit after the decimal point). +func ParseLocalTime(s string) (LocalTime, error) { + t, err := time.Parse("15:04:05.999999999", s) + if err != nil { + return LocalTime{}, err + } + return LocalTimeOf(t), nil +} + +// String returns the date in the format described in ParseLocalTime. If Nanoseconds +// is zero, no fractional part will be generated. Otherwise, the result will +// end with a fractional part consisting of a decimal point and nine digits. +func (t LocalTime) String() string { + s := fmt.Sprintf("%02d:%02d:%02d", t.Hour, t.Minute, t.Second) + if t.Nanosecond == 0 { + return s + } + return s + fmt.Sprintf(".%09d", t.Nanosecond) +} + +// IsValid reports whether the time is valid. +func (t LocalTime) IsValid() bool { + // Construct a non-zero time. + tm := time.Date(2, 2, 2, t.Hour, t.Minute, t.Second, t.Nanosecond, time.UTC) + return LocalTimeOf(tm) == t +} + +// MarshalText implements the encoding.TextMarshaler interface. +// The output is the result of t.String(). +func (t LocalTime) MarshalText() ([]byte, error) { + return []byte(t.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// The time is expected to be a string in a format accepted by ParseLocalTime. +func (t *LocalTime) UnmarshalText(data []byte) error { + var err error + *t, err = ParseLocalTime(string(data)) + return err +} + +// A LocalDateTime represents a date and time. +// +// This type does not include location information, and therefore does not +// describe a unique moment in time. +type LocalDateTime struct { + Date LocalDate + Time LocalTime +} + +// Note: We deliberately do not embed LocalDate into LocalDateTime, to avoid promoting AddDays and Sub. + +// LocalDateTimeOf returns the LocalDateTime in which a time occurs in that time's location. +func LocalDateTimeOf(t time.Time) LocalDateTime { + return LocalDateTime{ + Date: LocalDateOf(t), + Time: LocalTimeOf(t), + } +} + +// ParseLocalDateTime parses a string and returns the LocalDateTime it represents. +// ParseLocalDateTime accepts a variant of the RFC3339 date-time format that omits +// the time offset but includes an optional fractional time, as described in +// ParseLocalTime. Informally, the accepted format is +// YYYY-MM-DDTHH:MM:SS[.FFFFFFFFF] +// where the 'T' may be a lower-case 't'. +func ParseLocalDateTime(s string) (LocalDateTime, error) { + t, err := time.Parse("2006-01-02T15:04:05.999999999", s) + if err != nil { + t, err = time.Parse("2006-01-02t15:04:05.999999999", s) + if err != nil { + return LocalDateTime{}, err + } + } + return LocalDateTimeOf(t), nil +} + +// String returns the date in the format described in ParseLocalDate. +func (dt LocalDateTime) String() string { + return dt.Date.String() + "T" + dt.Time.String() +} + +// IsValid reports whether the datetime is valid. +func (dt LocalDateTime) IsValid() bool { + return dt.Date.IsValid() && dt.Time.IsValid() +} + +// In returns the time corresponding to the LocalDateTime in the given location. +// +// If the time is missing or ambigous at the location, In returns the same +// result as time.LocalDate. For example, if loc is America/Indiana/Vincennes, then +// both +// time.LocalDate(1955, time.May, 1, 0, 30, 0, 0, loc) +// and +// civil.LocalDateTime{ +// civil.LocalDate{Year: 1955, Month: time.May, Day: 1}}, +// civil.LocalTime{Minute: 30}}.In(loc) +// return 23:30:00 on April 30, 1955. +// +// In panics if loc is nil. +func (dt LocalDateTime) In(loc *time.Location) time.Time { + return time.Date(dt.Date.Year, dt.Date.Month, dt.Date.Day, dt.Time.Hour, dt.Time.Minute, dt.Time.Second, dt.Time.Nanosecond, loc) +} + +// Before reports whether dt1 occurs before dt2. +func (dt1 LocalDateTime) Before(dt2 LocalDateTime) bool { + return dt1.In(time.UTC).Before(dt2.In(time.UTC)) +} + +// After reports whether dt1 occurs after dt2. +func (dt1 LocalDateTime) After(dt2 LocalDateTime) bool { + return dt2.Before(dt1) +} + +// MarshalText implements the encoding.TextMarshaler interface. +// The output is the result of dt.String(). +func (dt LocalDateTime) MarshalText() ([]byte, error) { + return []byte(dt.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// The datetime is expected to be a string in a format accepted by ParseLocalDateTime +func (dt *LocalDateTime) UnmarshalText(data []byte) error { + var err error + *dt, err = ParseLocalDateTime(string(data)) + return err +} diff --git a/vendor/github.com/pelletier/go-toml/marshal.go b/vendor/github.com/pelletier/go-toml/marshal.go new file mode 100644 index 000000000..3443c3545 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal.go @@ -0,0 +1,1308 @@ +package toml + +import ( + "bytes" + "encoding" + "errors" + "fmt" + "io" + "reflect" + "sort" + "strconv" + "strings" + "time" +) + +const ( + tagFieldName = "toml" + tagFieldComment = "comment" + tagCommented = "commented" + tagMultiline = "multiline" + tagLiteral = "literal" + tagDefault = "default" +) + +type tomlOpts struct { + name string + nameFromTag bool + comment string + commented bool + multiline bool + literal bool + include bool + omitempty bool + defaultValue string +} + +type encOpts struct { + quoteMapKeys bool + arraysOneElementPerLine bool +} + +var encOptsDefaults = encOpts{ + quoteMapKeys: false, +} + +type annotation struct { + tag string + comment string + commented string + multiline string + literal string + defaultValue string +} + +var annotationDefault = annotation{ + tag: tagFieldName, + comment: tagFieldComment, + commented: tagCommented, + multiline: tagMultiline, + literal: tagLiteral, + defaultValue: tagDefault, +} + +type MarshalOrder int + +// Orders the Encoder can write the fields to the output stream. +const ( + // Sort fields alphabetically. + OrderAlphabetical MarshalOrder = iota + 1 + // Preserve the order the fields are encountered. For example, the order of fields in + // a struct. + OrderPreserve +) + +var timeType = reflect.TypeOf(time.Time{}) +var marshalerType = reflect.TypeOf(new(Marshaler)).Elem() +var unmarshalerType = reflect.TypeOf(new(Unmarshaler)).Elem() +var textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem() +var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem() +var localDateType = reflect.TypeOf(LocalDate{}) +var localTimeType = reflect.TypeOf(LocalTime{}) +var localDateTimeType = reflect.TypeOf(LocalDateTime{}) +var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{}) + +// Check if the given marshal type maps to a Tree primitive +func isPrimitive(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isPrimitive(mtype.Elem()) + case reflect.Bool: + return true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.String: + return true + case reflect.Struct: + return isTimeType(mtype) + default: + return false + } +} + +func isTimeType(mtype reflect.Type) bool { + return mtype == timeType || mtype == localDateType || mtype == localDateTimeType || mtype == localTimeType +} + +// Check if the given marshal type maps to a Tree slice or array +func isTreeSequence(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isTreeSequence(mtype.Elem()) + case reflect.Slice, reflect.Array: + return isTree(mtype.Elem()) + default: + return false + } +} + +// Check if the given marshal type maps to a slice or array of a custom marshaler type +func isCustomMarshalerSequence(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isCustomMarshalerSequence(mtype.Elem()) + case reflect.Slice, reflect.Array: + return isCustomMarshaler(mtype.Elem()) || isCustomMarshaler(reflect.New(mtype.Elem()).Type()) + default: + return false + } +} + +// Check if the given marshal type maps to a slice or array of a text marshaler type +func isTextMarshalerSequence(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isTextMarshalerSequence(mtype.Elem()) + case reflect.Slice, reflect.Array: + return isTextMarshaler(mtype.Elem()) || isTextMarshaler(reflect.New(mtype.Elem()).Type()) + default: + return false + } +} + +// Check if the given marshal type maps to a non-Tree slice or array +func isOtherSequence(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isOtherSequence(mtype.Elem()) + case reflect.Slice, reflect.Array: + return !isTreeSequence(mtype) + default: + return false + } +} + +// Check if the given marshal type maps to a Tree +func isTree(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isTree(mtype.Elem()) + case reflect.Map: + return true + case reflect.Struct: + return !isPrimitive(mtype) + default: + return false + } +} + +func isCustomMarshaler(mtype reflect.Type) bool { + return mtype.Implements(marshalerType) +} + +func callCustomMarshaler(mval reflect.Value) ([]byte, error) { + return mval.Interface().(Marshaler).MarshalTOML() +} + +func isTextMarshaler(mtype reflect.Type) bool { + return mtype.Implements(textMarshalerType) && !isTimeType(mtype) +} + +func callTextMarshaler(mval reflect.Value) ([]byte, error) { + return mval.Interface().(encoding.TextMarshaler).MarshalText() +} + +func isCustomUnmarshaler(mtype reflect.Type) bool { + return mtype.Implements(unmarshalerType) +} + +func callCustomUnmarshaler(mval reflect.Value, tval interface{}) error { + return mval.Interface().(Unmarshaler).UnmarshalTOML(tval) +} + +func isTextUnmarshaler(mtype reflect.Type) bool { + return mtype.Implements(textUnmarshalerType) +} + +func callTextUnmarshaler(mval reflect.Value, text []byte) error { + return mval.Interface().(encoding.TextUnmarshaler).UnmarshalText(text) +} + +// Marshaler is the interface implemented by types that +// can marshal themselves into valid TOML. +type Marshaler interface { + MarshalTOML() ([]byte, error) +} + +// Unmarshaler is the interface implemented by types that +// can unmarshal a TOML description of themselves. +type Unmarshaler interface { + UnmarshalTOML(interface{}) error +} + +/* +Marshal returns the TOML encoding of v. Behavior is similar to the Go json +encoder, except that there is no concept of a Marshaler interface or MarshalTOML +function for sub-structs, and currently only definite types can be marshaled +(i.e. no `interface{}`). + +The following struct annotations are supported: + + toml:"Field" Overrides the field's name to output. + omitempty When set, empty values and groups are not emitted. + comment:"comment" Emits a # comment on the same line. This supports new lines. + commented:"true" Emits the value as commented. + +Note that pointers are automatically assigned the "omitempty" option, as TOML +explicitly does not handle null values (saying instead the label should be +dropped). + +Tree structural types and corresponding marshal types: + + *Tree (*)struct, (*)map[string]interface{} + []*Tree (*)[](*)struct, (*)[](*)map[string]interface{} + []interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{}) + interface{} (*)primitive + +Tree primitive types and corresponding marshal types: + + uint64 uint, uint8-uint64, pointers to same + int64 int, int8-uint64, pointers to same + float64 float32, float64, pointers to same + string string, pointers to same + bool bool, pointers to same + time.LocalTime time.LocalTime{}, pointers to same + +For additional flexibility, use the Encoder API. +*/ +func Marshal(v interface{}) ([]byte, error) { + return NewEncoder(nil).marshal(v) +} + +// Encoder writes TOML values to an output stream. +type Encoder struct { + w io.Writer + encOpts + annotation + line int + col int + order MarshalOrder + promoteAnon bool + compactComments bool + indentation string +} + +// NewEncoder returns a new encoder that writes to w. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{ + w: w, + encOpts: encOptsDefaults, + annotation: annotationDefault, + line: 0, + col: 1, + order: OrderAlphabetical, + indentation: " ", + } +} + +// Encode writes the TOML encoding of v to the stream. +// +// See the documentation for Marshal for details. +func (e *Encoder) Encode(v interface{}) error { + b, err := e.marshal(v) + if err != nil { + return err + } + if _, err := e.w.Write(b); err != nil { + return err + } + return nil +} + +// QuoteMapKeys sets up the encoder to encode +// maps with string type keys with quoted TOML keys. +// +// This relieves the character limitations on map keys. +func (e *Encoder) QuoteMapKeys(v bool) *Encoder { + e.quoteMapKeys = v + return e +} + +// ArraysWithOneElementPerLine sets up the encoder to encode arrays +// with more than one element on multiple lines instead of one. +// +// For example: +// +// A = [1,2,3] +// +// Becomes +// +// A = [ +// 1, +// 2, +// 3, +// ] +func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder { + e.arraysOneElementPerLine = v + return e +} + +// Order allows to change in which order fields will be written to the output stream. +func (e *Encoder) Order(ord MarshalOrder) *Encoder { + e.order = ord + return e +} + +// Indentation allows to change indentation when marshalling. +func (e *Encoder) Indentation(indent string) *Encoder { + e.indentation = indent + return e +} + +// SetTagName allows changing default tag "toml" +func (e *Encoder) SetTagName(v string) *Encoder { + e.tag = v + return e +} + +// SetTagComment allows changing default tag "comment" +func (e *Encoder) SetTagComment(v string) *Encoder { + e.comment = v + return e +} + +// SetTagCommented allows changing default tag "commented" +func (e *Encoder) SetTagCommented(v string) *Encoder { + e.commented = v + return e +} + +// SetTagMultiline allows changing default tag "multiline" +func (e *Encoder) SetTagMultiline(v string) *Encoder { + e.multiline = v + return e +} + +// PromoteAnonymous allows to change how anonymous struct fields are marshaled. +// Usually, they are marshaled as if the inner exported fields were fields in +// the outer struct. However, if an anonymous struct field is given a name in +// its TOML tag, it is treated like a regular struct field with that name. +// rather than being anonymous. +// +// In case anonymous promotion is enabled, all anonymous structs are promoted +// and treated like regular struct fields. +func (e *Encoder) PromoteAnonymous(promote bool) *Encoder { + e.promoteAnon = promote + return e +} + +// CompactComments removes the new line before each comment in the tree. +func (e *Encoder) CompactComments(cc bool) *Encoder { + e.compactComments = cc + return e +} + +func (e *Encoder) marshal(v interface{}) ([]byte, error) { + // Check if indentation is valid + for _, char := range e.indentation { + if !isSpace(char) { + return []byte{}, fmt.Errorf("invalid indentation: must only contains space or tab characters") + } + } + + mtype := reflect.TypeOf(v) + if mtype == nil { + return []byte{}, errors.New("nil cannot be marshaled to TOML") + } + + switch mtype.Kind() { + case reflect.Struct, reflect.Map: + case reflect.Ptr: + if mtype.Elem().Kind() != reflect.Struct { + return []byte{}, errors.New("Only pointer to struct can be marshaled to TOML") + } + if reflect.ValueOf(v).IsNil() { + return []byte{}, errors.New("nil pointer cannot be marshaled to TOML") + } + default: + return []byte{}, errors.New("Only a struct or map can be marshaled to TOML") + } + + sval := reflect.ValueOf(v) + if isCustomMarshaler(mtype) { + return callCustomMarshaler(sval) + } + if isTextMarshaler(mtype) { + return callTextMarshaler(sval) + } + t, err := e.valueToTree(mtype, sval) + if err != nil { + return []byte{}, err + } + + var buf bytes.Buffer + _, err = t.writeToOrdered(&buf, "", "", 0, e.arraysOneElementPerLine, e.order, e.indentation, e.compactComments, false) + + return buf.Bytes(), err +} + +// Create next tree with a position based on Encoder.line +func (e *Encoder) nextTree() *Tree { + return newTreeWithPosition(Position{Line: e.line, Col: 1}) +} + +// Convert given marshal struct or map value to toml tree +func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, error) { + if mtype.Kind() == reflect.Ptr { + return e.valueToTree(mtype.Elem(), mval.Elem()) + } + tval := e.nextTree() + switch mtype.Kind() { + case reflect.Struct: + switch mval.Interface().(type) { + case Tree: + reflect.ValueOf(tval).Elem().Set(mval) + default: + for i := 0; i < mtype.NumField(); i++ { + mtypef, mvalf := mtype.Field(i), mval.Field(i) + opts := tomlOptions(mtypef, e.annotation) + if opts.include && ((mtypef.Type.Kind() != reflect.Interface && !opts.omitempty) || !isZero(mvalf)) { + val, err := e.valueToToml(mtypef.Type, mvalf) + if err != nil { + return nil, err + } + if tree, ok := val.(*Tree); ok && mtypef.Anonymous && !opts.nameFromTag && !e.promoteAnon { + e.appendTree(tval, tree) + } else { + val = e.wrapTomlValue(val, tval) + tval.SetPathWithOptions([]string{opts.name}, SetOptions{ + Comment: opts.comment, + Commented: opts.commented, + Multiline: opts.multiline, + Literal: opts.literal, + }, val) + } + } + } + } + case reflect.Map: + keys := mval.MapKeys() + if e.order == OrderPreserve && len(keys) > 0 { + // Sorting []reflect.Value is not straight forward. + // + // OrderPreserve will support deterministic results when string is used + // as the key to maps. + typ := keys[0].Type() + kind := keys[0].Kind() + if kind == reflect.String { + ikeys := make([]string, len(keys)) + for i := range keys { + ikeys[i] = keys[i].Interface().(string) + } + sort.Strings(ikeys) + for i := range ikeys { + keys[i] = reflect.ValueOf(ikeys[i]).Convert(typ) + } + } + } + for _, key := range keys { + mvalf := mval.MapIndex(key) + if (mtype.Elem().Kind() == reflect.Ptr || mtype.Elem().Kind() == reflect.Interface) && mvalf.IsNil() { + continue + } + val, err := e.valueToToml(mtype.Elem(), mvalf) + if err != nil { + return nil, err + } + val = e.wrapTomlValue(val, tval) + if e.quoteMapKeys { + keyStr, err := tomlValueStringRepresentation(key.String(), "", "", e.order, e.arraysOneElementPerLine) + if err != nil { + return nil, err + } + tval.SetPath([]string{keyStr}, val) + } else { + tval.SetPath([]string{key.String()}, val) + } + } + } + return tval, nil +} + +// Convert given marshal slice to slice of Toml trees +func (e *Encoder) valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) { + tval := make([]*Tree, mval.Len(), mval.Len()) + for i := 0; i < mval.Len(); i++ { + val, err := e.valueToTree(mtype.Elem(), mval.Index(i)) + if err != nil { + return nil, err + } + tval[i] = val + } + return tval, nil +} + +// Convert given marshal slice to slice of toml values +func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (interface{}, error) { + tval := make([]interface{}, mval.Len(), mval.Len()) + for i := 0; i < mval.Len(); i++ { + val, err := e.valueToToml(mtype.Elem(), mval.Index(i)) + if err != nil { + return nil, err + } + tval[i] = val + } + return tval, nil +} + +// Convert given marshal value to toml value +func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) { + if mtype.Kind() == reflect.Ptr { + switch { + case isCustomMarshaler(mtype): + return callCustomMarshaler(mval) + case isTextMarshaler(mtype): + b, err := callTextMarshaler(mval) + return string(b), err + default: + return e.valueToToml(mtype.Elem(), mval.Elem()) + } + } + if mtype.Kind() == reflect.Interface { + return e.valueToToml(mval.Elem().Type(), mval.Elem()) + } + switch { + case isCustomMarshaler(mtype): + return callCustomMarshaler(mval) + case isTextMarshaler(mtype): + b, err := callTextMarshaler(mval) + return string(b), err + case isTree(mtype): + return e.valueToTree(mtype, mval) + case isOtherSequence(mtype), isCustomMarshalerSequence(mtype), isTextMarshalerSequence(mtype): + return e.valueToOtherSlice(mtype, mval) + case isTreeSequence(mtype): + return e.valueToTreeSlice(mtype, mval) + default: + switch mtype.Kind() { + case reflect.Bool: + return mval.Bool(), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) { + return fmt.Sprint(mval), nil + } + return mval.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return mval.Uint(), nil + case reflect.Float32, reflect.Float64: + return mval.Float(), nil + case reflect.String: + return mval.String(), nil + case reflect.Struct: + return mval.Interface(), nil + default: + return nil, fmt.Errorf("Marshal can't handle %v(%v)", mtype, mtype.Kind()) + } + } +} + +func (e *Encoder) appendTree(t, o *Tree) error { + for key, value := range o.values { + if _, ok := t.values[key]; ok { + continue + } + if tomlValue, ok := value.(*tomlValue); ok { + tomlValue.position.Col = t.position.Col + } + t.values[key] = value + } + return nil +} + +// Create a toml value with the current line number as the position line +func (e *Encoder) wrapTomlValue(val interface{}, parent *Tree) interface{} { + _, isTree := val.(*Tree) + _, isTreeS := val.([]*Tree) + if isTree || isTreeS { + e.line++ + return val + } + + ret := &tomlValue{ + value: val, + position: Position{ + e.line, + parent.position.Col, + }, + } + e.line++ + return ret +} + +// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v. +// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for +// sub-structs, and only definite types can be unmarshaled. +func (t *Tree) Unmarshal(v interface{}) error { + d := Decoder{tval: t, tagName: tagFieldName} + return d.unmarshal(v) +} + +// Marshal returns the TOML encoding of Tree. +// See Marshal() documentation for types mapping table. +func (t *Tree) Marshal() ([]byte, error) { + var buf bytes.Buffer + _, err := t.WriteTo(&buf) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// Unmarshal parses the TOML-encoded data and stores the result in the value +// pointed to by v. Behavior is similar to the Go json encoder, except that there +// is no concept of an Unmarshaler interface or UnmarshalTOML function for +// sub-structs, and currently only definite types can be unmarshaled to (i.e. no +// `interface{}`). +// +// The following struct annotations are supported: +// +// toml:"Field" Overrides the field's name to map to. +// default:"foo" Provides a default value. +// +// For default values, only fields of the following types are supported: +// * string +// * bool +// * int +// * int64 +// * float64 +// +// See Marshal() documentation for types mapping table. +func Unmarshal(data []byte, v interface{}) error { + t, err := LoadReader(bytes.NewReader(data)) + if err != nil { + return err + } + return t.Unmarshal(v) +} + +// Decoder reads and decodes TOML values from an input stream. +type Decoder struct { + r io.Reader + tval *Tree + encOpts + tagName string + strict bool + visitor visitorState +} + +// NewDecoder returns a new decoder that reads from r. +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{ + r: r, + encOpts: encOptsDefaults, + tagName: tagFieldName, + } +} + +// Decode reads a TOML-encoded value from it's input +// and unmarshals it in the value pointed at by v. +// +// See the documentation for Marshal for details. +func (d *Decoder) Decode(v interface{}) error { + var err error + d.tval, err = LoadReader(d.r) + if err != nil { + return err + } + return d.unmarshal(v) +} + +// SetTagName allows changing default tag "toml" +func (d *Decoder) SetTagName(v string) *Decoder { + d.tagName = v + return d +} + +// Strict allows changing to strict decoding. Any fields that are found in the +// input data and do not have a corresponding struct member cause an error. +func (d *Decoder) Strict(strict bool) *Decoder { + d.strict = strict + return d +} + +func (d *Decoder) unmarshal(v interface{}) error { + mtype := reflect.TypeOf(v) + if mtype == nil { + return errors.New("nil cannot be unmarshaled from TOML") + } + if mtype.Kind() != reflect.Ptr { + return errors.New("only a pointer to struct or map can be unmarshaled from TOML") + } + + elem := mtype.Elem() + + switch elem.Kind() { + case reflect.Struct, reflect.Map: + case reflect.Interface: + elem = mapStringInterfaceType + default: + return errors.New("only a pointer to struct or map can be unmarshaled from TOML") + } + + if reflect.ValueOf(v).IsNil() { + return errors.New("nil pointer cannot be unmarshaled from TOML") + } + + vv := reflect.ValueOf(v).Elem() + + if d.strict { + d.visitor = newVisitorState(d.tval) + } + + sval, err := d.valueFromTree(elem, d.tval, &vv) + if err != nil { + return err + } + if err := d.visitor.validate(); err != nil { + return err + } + reflect.ValueOf(v).Elem().Set(sval) + return nil +} + +// Convert toml tree to marshal struct or map, using marshal type. When mval1 +// is non-nil, merge fields into the given value instead of allocating a new one. +func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.Value) (reflect.Value, error) { + if mtype.Kind() == reflect.Ptr { + return d.unwrapPointer(mtype, tval, mval1) + } + + // Check if pointer to value implements the Unmarshaler interface. + if mvalPtr := reflect.New(mtype); isCustomUnmarshaler(mvalPtr.Type()) { + d.visitor.visitAll() + + if tval == nil { + return mvalPtr.Elem(), nil + } + + if err := callCustomUnmarshaler(mvalPtr, tval.ToMap()); err != nil { + return reflect.ValueOf(nil), fmt.Errorf("unmarshal toml: %v", err) + } + return mvalPtr.Elem(), nil + } + + var mval reflect.Value + switch mtype.Kind() { + case reflect.Struct: + if mval1 != nil { + mval = *mval1 + } else { + mval = reflect.New(mtype).Elem() + } + + switch mval.Interface().(type) { + case Tree: + mval.Set(reflect.ValueOf(tval).Elem()) + default: + for i := 0; i < mtype.NumField(); i++ { + mtypef := mtype.Field(i) + an := annotation{tag: d.tagName} + opts := tomlOptions(mtypef, an) + if !opts.include { + continue + } + baseKey := opts.name + keysToTry := []string{ + baseKey, + strings.ToLower(baseKey), + strings.ToTitle(baseKey), + strings.ToLower(string(baseKey[0])) + baseKey[1:], + } + + found := false + if tval != nil { + for _, key := range keysToTry { + exists := tval.HasPath([]string{key}) + if !exists { + continue + } + + d.visitor.push(key) + val := tval.GetPath([]string{key}) + fval := mval.Field(i) + mvalf, err := d.valueFromToml(mtypef.Type, val, &fval) + if err != nil { + return mval, formatError(err, tval.GetPositionPath([]string{key})) + } + mval.Field(i).Set(mvalf) + found = true + d.visitor.pop() + break + } + } + + if !found && opts.defaultValue != "" { + mvalf := mval.Field(i) + var val interface{} + var err error + switch mvalf.Kind() { + case reflect.String: + val = opts.defaultValue + case reflect.Bool: + val, err = strconv.ParseBool(opts.defaultValue) + case reflect.Uint: + val, err = strconv.ParseUint(opts.defaultValue, 10, 0) + case reflect.Uint8: + val, err = strconv.ParseUint(opts.defaultValue, 10, 8) + case reflect.Uint16: + val, err = strconv.ParseUint(opts.defaultValue, 10, 16) + case reflect.Uint32: + val, err = strconv.ParseUint(opts.defaultValue, 10, 32) + case reflect.Uint64: + val, err = strconv.ParseUint(opts.defaultValue, 10, 64) + case reflect.Int: + val, err = strconv.ParseInt(opts.defaultValue, 10, 0) + case reflect.Int8: + val, err = strconv.ParseInt(opts.defaultValue, 10, 8) + case reflect.Int16: + val, err = strconv.ParseInt(opts.defaultValue, 10, 16) + case reflect.Int32: + val, err = strconv.ParseInt(opts.defaultValue, 10, 32) + case reflect.Int64: + // Check if the provided number has a non-numeric extension. + var hasExtension bool + if len(opts.defaultValue) > 0 { + lastChar := opts.defaultValue[len(opts.defaultValue)-1] + if lastChar < '0' || lastChar > '9' { + hasExtension = true + } + } + // If the value is a time.Duration with extension, parse as duration. + // If the value is an int64 or a time.Duration without extension, parse as number. + if hasExtension && mvalf.Type().String() == "time.Duration" { + val, err = time.ParseDuration(opts.defaultValue) + } else { + val, err = strconv.ParseInt(opts.defaultValue, 10, 64) + } + case reflect.Float32: + val, err = strconv.ParseFloat(opts.defaultValue, 32) + case reflect.Float64: + val, err = strconv.ParseFloat(opts.defaultValue, 64) + default: + return mvalf, fmt.Errorf("unsupported field type for default option") + } + + if err != nil { + return mvalf, err + } + mvalf.Set(reflect.ValueOf(val).Convert(mvalf.Type())) + } + + // save the old behavior above and try to check structs + if !found && opts.defaultValue == "" && mtypef.Type.Kind() == reflect.Struct { + tmpTval := tval + if !mtypef.Anonymous { + tmpTval = nil + } + fval := mval.Field(i) + v, err := d.valueFromTree(mtypef.Type, tmpTval, &fval) + if err != nil { + return v, err + } + mval.Field(i).Set(v) + } + } + } + case reflect.Map: + mval = reflect.MakeMap(mtype) + for _, key := range tval.Keys() { + d.visitor.push(key) + // TODO: path splits key + val := tval.GetPath([]string{key}) + mvalf, err := d.valueFromToml(mtype.Elem(), val, nil) + if err != nil { + return mval, formatError(err, tval.GetPositionPath([]string{key})) + } + mval.SetMapIndex(reflect.ValueOf(key).Convert(mtype.Key()), mvalf) + d.visitor.pop() + } + } + return mval, nil +} + +// Convert toml value to marshal struct/map slice, using marshal type +func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) { + mval, err := makeSliceOrArray(mtype, len(tval)) + if err != nil { + return mval, err + } + + for i := 0; i < len(tval); i++ { + d.visitor.push(strconv.Itoa(i)) + val, err := d.valueFromTree(mtype.Elem(), tval[i], nil) + if err != nil { + return mval, err + } + mval.Index(i).Set(val) + d.visitor.pop() + } + return mval, nil +} + +// Convert toml value to marshal primitive slice, using marshal type +func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) { + mval, err := makeSliceOrArray(mtype, len(tval)) + if err != nil { + return mval, err + } + + for i := 0; i < len(tval); i++ { + val, err := d.valueFromToml(mtype.Elem(), tval[i], nil) + if err != nil { + return mval, err + } + mval.Index(i).Set(val) + } + return mval, nil +} + +// Convert toml value to marshal primitive slice, using marshal type +func (d *Decoder) valueFromOtherSliceI(mtype reflect.Type, tval interface{}) (reflect.Value, error) { + val := reflect.ValueOf(tval) + length := val.Len() + + mval, err := makeSliceOrArray(mtype, length) + if err != nil { + return mval, err + } + + for i := 0; i < length; i++ { + val, err := d.valueFromToml(mtype.Elem(), val.Index(i).Interface(), nil) + if err != nil { + return mval, err + } + mval.Index(i).Set(val) + } + return mval, nil +} + +// Create a new slice or a new array with specified length +func makeSliceOrArray(mtype reflect.Type, tLength int) (reflect.Value, error) { + var mval reflect.Value + switch mtype.Kind() { + case reflect.Slice: + mval = reflect.MakeSlice(mtype, tLength, tLength) + case reflect.Array: + mval = reflect.New(reflect.ArrayOf(mtype.Len(), mtype.Elem())).Elem() + if tLength > mtype.Len() { + return mval, fmt.Errorf("unmarshal: TOML array length (%v) exceeds destination array length (%v)", tLength, mtype.Len()) + } + } + return mval, nil +} + +// Convert toml value to marshal value, using marshal type. When mval1 is non-nil +// and the given type is a struct value, merge fields into it. +func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *reflect.Value) (reflect.Value, error) { + if mtype.Kind() == reflect.Ptr { + return d.unwrapPointer(mtype, tval, mval1) + } + + switch t := tval.(type) { + case *Tree: + var mval11 *reflect.Value + if mtype.Kind() == reflect.Struct { + mval11 = mval1 + } + + if isTree(mtype) { + return d.valueFromTree(mtype, t, mval11) + } + + if mtype.Kind() == reflect.Interface { + if mval1 == nil || mval1.IsNil() { + return d.valueFromTree(reflect.TypeOf(map[string]interface{}{}), t, nil) + } else { + return d.valueFromToml(mval1.Elem().Type(), t, nil) + } + } + + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval) + case []*Tree: + if isTreeSequence(mtype) { + return d.valueFromTreeSlice(mtype, t) + } + if mtype.Kind() == reflect.Interface { + if mval1 == nil || mval1.IsNil() { + return d.valueFromTreeSlice(reflect.TypeOf([]map[string]interface{}{}), t) + } else { + ival := mval1.Elem() + return d.valueFromToml(mval1.Elem().Type(), t, &ival) + } + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval) + case []interface{}: + d.visitor.visit() + if isOtherSequence(mtype) { + return d.valueFromOtherSlice(mtype, t) + } + if mtype.Kind() == reflect.Interface { + if mval1 == nil || mval1.IsNil() { + return d.valueFromOtherSlice(reflect.TypeOf([]interface{}{}), t) + } else { + ival := mval1.Elem() + return d.valueFromToml(mval1.Elem().Type(), t, &ival) + } + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval) + default: + d.visitor.visit() + mvalPtr := reflect.New(mtype) + + // Check if pointer to value implements the Unmarshaler interface. + if isCustomUnmarshaler(mvalPtr.Type()) { + if err := callCustomUnmarshaler(mvalPtr, tval); err != nil { + return reflect.ValueOf(nil), fmt.Errorf("unmarshal toml: %v", err) + } + return mvalPtr.Elem(), nil + } + + // Check if pointer to value implements the encoding.TextUnmarshaler. + if isTextUnmarshaler(mvalPtr.Type()) && !isTimeType(mtype) { + if err := d.unmarshalText(tval, mvalPtr); err != nil { + return reflect.ValueOf(nil), fmt.Errorf("unmarshal text: %v", err) + } + return mvalPtr.Elem(), nil + } + + switch mtype.Kind() { + case reflect.Bool, reflect.Struct: + val := reflect.ValueOf(tval) + + switch val.Type() { + case localDateType: + localDate := val.Interface().(LocalDate) + switch mtype { + case timeType: + return reflect.ValueOf(time.Date(localDate.Year, localDate.Month, localDate.Day, 0, 0, 0, 0, time.Local)), nil + } + case localDateTimeType: + localDateTime := val.Interface().(LocalDateTime) + switch mtype { + case timeType: + return reflect.ValueOf(time.Date( + localDateTime.Date.Year, + localDateTime.Date.Month, + localDateTime.Date.Day, + localDateTime.Time.Hour, + localDateTime.Time.Minute, + localDateTime.Time.Second, + localDateTime.Time.Nanosecond, + time.Local)), nil + } + } + + // if this passes for when mtype is reflect.Struct, tval is a time.LocalTime + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.String: + val := reflect.ValueOf(tval) + // stupidly, int64 is convertible to string. So special case this. + if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + val := reflect.ValueOf(tval) + if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) && val.Kind() == reflect.String { + d, err := time.ParseDuration(val.String()) + if err != nil { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v. %s", tval, tval, mtype.String(), err) + } + return reflect.ValueOf(d), nil + } + if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Float64 { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Convert(reflect.TypeOf(int64(0))).Int()) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + val := reflect.ValueOf(tval) + if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Float64 { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + + if val.Convert(reflect.TypeOf(int(1))).Int() < 0 { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowUint(val.Convert(reflect.TypeOf(uint64(0))).Uint()) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Float32, reflect.Float64: + val := reflect.ValueOf(tval) + if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Convert(reflect.TypeOf(float64(0))).Float()) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Interface: + if mval1 == nil || mval1.IsNil() { + return reflect.ValueOf(tval), nil + } else { + ival := mval1.Elem() + return d.valueFromToml(mval1.Elem().Type(), t, &ival) + } + case reflect.Slice, reflect.Array: + if isOtherSequence(mtype) && isOtherSequence(reflect.TypeOf(t)) { + return d.valueFromOtherSliceI(mtype, t) + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind()) + default: + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind()) + } + } +} + +func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}, mval1 *reflect.Value) (reflect.Value, error) { + var melem *reflect.Value + + if mval1 != nil && !mval1.IsNil() && (mtype.Elem().Kind() == reflect.Struct || mtype.Elem().Kind() == reflect.Interface) { + elem := mval1.Elem() + melem = &elem + } + + val, err := d.valueFromToml(mtype.Elem(), tval, melem) + if err != nil { + return reflect.ValueOf(nil), err + } + mval := reflect.New(mtype.Elem()) + mval.Elem().Set(val) + return mval, nil +} + +func (d *Decoder) unmarshalText(tval interface{}, mval reflect.Value) error { + var buf bytes.Buffer + fmt.Fprint(&buf, tval) + return callTextUnmarshaler(mval, buf.Bytes()) +} + +func tomlOptions(vf reflect.StructField, an annotation) tomlOpts { + tag := vf.Tag.Get(an.tag) + parse := strings.Split(tag, ",") + var comment string + if c := vf.Tag.Get(an.comment); c != "" { + comment = c + } + commented, _ := strconv.ParseBool(vf.Tag.Get(an.commented)) + multiline, _ := strconv.ParseBool(vf.Tag.Get(an.multiline)) + literal, _ := strconv.ParseBool(vf.Tag.Get(an.literal)) + defaultValue := vf.Tag.Get(tagDefault) + result := tomlOpts{ + name: vf.Name, + nameFromTag: false, + comment: comment, + commented: commented, + multiline: multiline, + literal: literal, + include: true, + omitempty: false, + defaultValue: defaultValue, + } + if parse[0] != "" { + if parse[0] == "-" && len(parse) == 1 { + result.include = false + } else { + result.name = strings.Trim(parse[0], " ") + result.nameFromTag = true + } + } + if vf.PkgPath != "" { + result.include = false + } + if len(parse) > 1 && strings.Trim(parse[1], " ") == "omitempty" { + result.omitempty = true + } + if vf.Type.Kind() == reflect.Ptr { + result.omitempty = true + } + return result +} + +func isZero(val reflect.Value) bool { + switch val.Type().Kind() { + case reflect.Slice, reflect.Array, reflect.Map: + return val.Len() == 0 + default: + return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface()) + } +} + +func formatError(err error, pos Position) error { + if err.Error()[0] == '(' { // Error already contains position information + return err + } + return fmt.Errorf("%s: %s", pos, err) +} + +// visitorState keeps track of which keys were unmarshaled. +type visitorState struct { + tree *Tree + path []string + keys map[string]struct{} + active bool +} + +func newVisitorState(tree *Tree) visitorState { + path, result := []string{}, map[string]struct{}{} + insertKeys(path, result, tree) + return visitorState{ + tree: tree, + path: path[:0], + keys: result, + active: true, + } +} + +func (s *visitorState) push(key string) { + if s.active { + s.path = append(s.path, key) + } +} + +func (s *visitorState) pop() { + if s.active { + s.path = s.path[:len(s.path)-1] + } +} + +func (s *visitorState) visit() { + if s.active { + delete(s.keys, strings.Join(s.path, ".")) + } +} + +func (s *visitorState) visitAll() { + if s.active { + for k := range s.keys { + if strings.HasPrefix(k, strings.Join(s.path, ".")) { + delete(s.keys, k) + } + } + } +} + +func (s *visitorState) validate() error { + if !s.active { + return nil + } + undecoded := make([]string, 0, len(s.keys)) + for key := range s.keys { + undecoded = append(undecoded, key) + } + sort.Strings(undecoded) + if len(undecoded) > 0 { + return fmt.Errorf("undecoded keys: %q", undecoded) + } + return nil +} + +func insertKeys(path []string, m map[string]struct{}, tree *Tree) { + for k, v := range tree.values { + switch node := v.(type) { + case []*Tree: + for i, item := range node { + insertKeys(append(path, k, strconv.Itoa(i)), m, item) + } + case *Tree: + insertKeys(append(path, k), m, node) + case *tomlValue: + m[strings.Join(append(path, k), ".")] = struct{}{} + } + } +} diff --git a/vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml b/vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml new file mode 100644 index 000000000..792b72ed7 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml @@ -0,0 +1,39 @@ +title = "TOML Marshal Testing" + +[basic_lists] + floats = [12.3,45.6,78.9] + bools = [true,false,true] + dates = [1979-05-27T07:32:00Z,1980-05-27T07:32:00Z] + ints = [8001,8001,8002] + uints = [5002,5003] + strings = ["One","Two","Three"] + +[[subdocptrs]] + name = "Second" + +[basic_map] + one = "one" + two = "two" + +[subdoc] + + [subdoc.second] + name = "Second" + + [subdoc.first] + name = "First" + +[basic] + uint = 5001 + bool = true + float = 123.4 + float64 = 123.456782132399 + int = 5000 + string = "Bite me" + date = 1979-05-27T07:32:00Z + +[[subdoclist]] + name = "List.First" + +[[subdoclist]] + name = "List.Second" diff --git a/vendor/github.com/pelletier/go-toml/marshal_test.toml b/vendor/github.com/pelletier/go-toml/marshal_test.toml new file mode 100644 index 000000000..ba5e110bf --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal_test.toml @@ -0,0 +1,39 @@ +title = "TOML Marshal Testing" + +[basic] + bool = true + date = 1979-05-27T07:32:00Z + float = 123.4 + float64 = 123.456782132399 + int = 5000 + string = "Bite me" + uint = 5001 + +[basic_lists] + bools = [true,false,true] + dates = [1979-05-27T07:32:00Z,1980-05-27T07:32:00Z] + floats = [12.3,45.6,78.9] + ints = [8001,8001,8002] + strings = ["One","Two","Three"] + uints = [5002,5003] + +[basic_map] + one = "one" + two = "two" + +[subdoc] + + [subdoc.first] + name = "First" + + [subdoc.second] + name = "Second" + +[[subdoclist]] + name = "List.First" + +[[subdoclist]] + name = "List.Second" + +[[subdocptrs]] + name = "Second" diff --git a/vendor/github.com/pelletier/go-toml/parser.go b/vendor/github.com/pelletier/go-toml/parser.go new file mode 100644 index 000000000..f5e1a44fb --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/parser.go @@ -0,0 +1,508 @@ +// TOML Parser. + +package toml + +import ( + "errors" + "fmt" + "math" + "reflect" + "strconv" + "strings" + "time" +) + +type tomlParser struct { + flowIdx int + flow []token + tree *Tree + currentTable []string + seenTableKeys []string +} + +type tomlParserStateFn func() tomlParserStateFn + +// Formats and panics an error message based on a token +func (p *tomlParser) raiseError(tok *token, msg string, args ...interface{}) { + panic(tok.Position.String() + ": " + fmt.Sprintf(msg, args...)) +} + +func (p *tomlParser) run() { + for state := p.parseStart; state != nil; { + state = state() + } +} + +func (p *tomlParser) peek() *token { + if p.flowIdx >= len(p.flow) { + return nil + } + return &p.flow[p.flowIdx] +} + +func (p *tomlParser) assume(typ tokenType) { + tok := p.getToken() + if tok == nil { + p.raiseError(tok, "was expecting token %s, but token stream is empty", tok) + } + if tok.typ != typ { + p.raiseError(tok, "was expecting token %s, but got %s instead", typ, tok) + } +} + +func (p *tomlParser) getToken() *token { + tok := p.peek() + if tok == nil { + return nil + } + p.flowIdx++ + return tok +} + +func (p *tomlParser) parseStart() tomlParserStateFn { + tok := p.peek() + + // end of stream, parsing is finished + if tok == nil { + return nil + } + + switch tok.typ { + case tokenDoubleLeftBracket: + return p.parseGroupArray + case tokenLeftBracket: + return p.parseGroup + case tokenKey: + return p.parseAssign + case tokenEOF: + return nil + case tokenError: + p.raiseError(tok, "parsing error: %s", tok.String()) + default: + p.raiseError(tok, "unexpected token %s", tok.typ) + } + return nil +} + +func (p *tomlParser) parseGroupArray() tomlParserStateFn { + startToken := p.getToken() // discard the [[ + key := p.getToken() + if key.typ != tokenKeyGroupArray { + p.raiseError(key, "unexpected token %s, was expecting a table array key", key) + } + + // get or create table array element at the indicated part in the path + keys, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid table array key: %s", err) + } + p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries + destTree := p.tree.GetPath(keys) + var array []*Tree + if destTree == nil { + array = make([]*Tree, 0) + } else if target, ok := destTree.([]*Tree); ok && target != nil { + array = destTree.([]*Tree) + } else { + p.raiseError(key, "key %s is already assigned and not of type table array", key) + } + p.currentTable = keys + + // add a new tree to the end of the table array + newTree := newTree() + newTree.position = startToken.Position + array = append(array, newTree) + p.tree.SetPath(p.currentTable, array) + + // remove all keys that were children of this table array + prefix := key.val + "." + found := false + for ii := 0; ii < len(p.seenTableKeys); { + tableKey := p.seenTableKeys[ii] + if strings.HasPrefix(tableKey, prefix) { + p.seenTableKeys = append(p.seenTableKeys[:ii], p.seenTableKeys[ii+1:]...) + } else { + found = (tableKey == key.val) + ii++ + } + } + + // keep this key name from use by other kinds of assignments + if !found { + p.seenTableKeys = append(p.seenTableKeys, key.val) + } + + // move to next parser state + p.assume(tokenDoubleRightBracket) + return p.parseStart +} + +func (p *tomlParser) parseGroup() tomlParserStateFn { + startToken := p.getToken() // discard the [ + key := p.getToken() + if key.typ != tokenKeyGroup { + p.raiseError(key, "unexpected token %s, was expecting a table key", key) + } + for _, item := range p.seenTableKeys { + if item == key.val { + p.raiseError(key, "duplicated tables") + } + } + + p.seenTableKeys = append(p.seenTableKeys, key.val) + keys, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid table array key: %s", err) + } + if err := p.tree.createSubTree(keys, startToken.Position); err != nil { + p.raiseError(key, "%s", err) + } + destTree := p.tree.GetPath(keys) + if target, ok := destTree.(*Tree); ok && target != nil && target.inline { + p.raiseError(key, "could not re-define exist inline table or its sub-table : %s", + strings.Join(keys, ".")) + } + p.assume(tokenRightBracket) + p.currentTable = keys + return p.parseStart +} + +func (p *tomlParser) parseAssign() tomlParserStateFn { + key := p.getToken() + p.assume(tokenEqual) + + parsedKey, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid key: %s", err.Error()) + } + + value := p.parseRvalue() + var tableKey []string + if len(p.currentTable) > 0 { + tableKey = p.currentTable + } else { + tableKey = []string{} + } + + prefixKey := parsedKey[0 : len(parsedKey)-1] + tableKey = append(tableKey, prefixKey...) + + // find the table to assign, looking out for arrays of tables + var targetNode *Tree + switch node := p.tree.GetPath(tableKey).(type) { + case []*Tree: + targetNode = node[len(node)-1] + case *Tree: + targetNode = node + case nil: + // create intermediate + if err := p.tree.createSubTree(tableKey, key.Position); err != nil { + p.raiseError(key, "could not create intermediate group: %s", err) + } + targetNode = p.tree.GetPath(tableKey).(*Tree) + default: + p.raiseError(key, "Unknown table type for path: %s", + strings.Join(tableKey, ".")) + } + + if targetNode.inline { + p.raiseError(key, "could not add key or sub-table to exist inline table or its sub-table : %s", + strings.Join(tableKey, ".")) + } + + // assign value to the found table + keyVal := parsedKey[len(parsedKey)-1] + localKey := []string{keyVal} + finalKey := append(tableKey, keyVal) + if targetNode.GetPath(localKey) != nil { + p.raiseError(key, "The following key was defined twice: %s", + strings.Join(finalKey, ".")) + } + var toInsert interface{} + + switch value.(type) { + case *Tree, []*Tree: + toInsert = value + default: + toInsert = &tomlValue{value: value, position: key.Position} + } + targetNode.values[keyVal] = toInsert + return p.parseStart +} + +var errInvalidUnderscore = errors.New("invalid use of _ in number") + +func numberContainsInvalidUnderscore(value string) error { + // For large numbers, you may use underscores between digits to enhance + // readability. Each underscore must be surrounded by at least one digit on + // each side. + + hasBefore := false + for idx, r := range value { + if r == '_' { + if !hasBefore || idx+1 >= len(value) { + // can't end with an underscore + return errInvalidUnderscore + } + } + hasBefore = isDigit(r) + } + return nil +} + +var errInvalidUnderscoreHex = errors.New("invalid use of _ in hex number") + +func hexNumberContainsInvalidUnderscore(value string) error { + hasBefore := false + for idx, r := range value { + if r == '_' { + if !hasBefore || idx+1 >= len(value) { + // can't end with an underscore + return errInvalidUnderscoreHex + } + } + hasBefore = isHexDigit(r) + } + return nil +} + +func cleanupNumberToken(value string) string { + cleanedVal := strings.Replace(value, "_", "", -1) + return cleanedVal +} + +func (p *tomlParser) parseRvalue() interface{} { + tok := p.getToken() + if tok == nil || tok.typ == tokenEOF { + p.raiseError(tok, "expecting a value") + } + + switch tok.typ { + case tokenString: + return tok.val + case tokenTrue: + return true + case tokenFalse: + return false + case tokenInf: + if tok.val[0] == '-' { + return math.Inf(-1) + } + return math.Inf(1) + case tokenNan: + return math.NaN() + case tokenInteger: + cleanedVal := cleanupNumberToken(tok.val) + var err error + var val int64 + if len(cleanedVal) >= 3 && cleanedVal[0] == '0' { + switch cleanedVal[1] { + case 'x': + err = hexNumberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 16, 64) + case 'o': + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 8, 64) + case 'b': + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 2, 64) + default: + panic("invalid base") // the lexer should catch this first + } + } else { + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal, 10, 64) + } + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenFloat: + err := numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + cleanedVal := cleanupNumberToken(tok.val) + val, err := strconv.ParseFloat(cleanedVal, 64) + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenLocalTime: + val, err := ParseLocalTime(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenLocalDate: + // a local date may be followed by: + // * nothing: this is a local date + // * a local time: this is a local date-time + + next := p.peek() + if next == nil || next.typ != tokenLocalTime { + val, err := ParseLocalDate(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + } + + localDate := tok + localTime := p.getToken() + + next = p.peek() + if next == nil || next.typ != tokenTimeOffset { + v := localDate.val + "T" + localTime.val + val, err := ParseLocalDateTime(v) + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + } + + offset := p.getToken() + + layout := time.RFC3339Nano + v := localDate.val + "T" + localTime.val + offset.val + val, err := time.ParseInLocation(layout, v, time.UTC) + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenLeftBracket: + return p.parseArray() + case tokenLeftCurlyBrace: + return p.parseInlineTable() + case tokenEqual: + p.raiseError(tok, "cannot have multiple equals for the same key") + case tokenError: + p.raiseError(tok, "%s", tok) + default: + panic(fmt.Errorf("unhandled token: %v", tok)) + } + + return nil +} + +func tokenIsComma(t *token) bool { + return t != nil && t.typ == tokenComma +} + +func (p *tomlParser) parseInlineTable() *Tree { + tree := newTree() + var previous *token +Loop: + for { + follow := p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated inline table") + } + switch follow.typ { + case tokenRightCurlyBrace: + p.getToken() + break Loop + case tokenKey, tokenInteger, tokenString: + if !tokenIsComma(previous) && previous != nil { + p.raiseError(follow, "comma expected between fields in inline table") + } + key := p.getToken() + p.assume(tokenEqual) + + parsedKey, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid key: %s", err) + } + + value := p.parseRvalue() + tree.SetPath(parsedKey, value) + case tokenComma: + if tokenIsComma(previous) { + p.raiseError(follow, "need field between two commas in inline table") + } + p.getToken() + default: + p.raiseError(follow, "unexpected token type in inline table: %s", follow.String()) + } + previous = follow + } + if tokenIsComma(previous) { + p.raiseError(previous, "trailing comma at the end of inline table") + } + tree.inline = true + return tree +} + +func (p *tomlParser) parseArray() interface{} { + var array []interface{} + arrayType := reflect.TypeOf(newTree()) + for { + follow := p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated array") + } + if follow.typ == tokenRightBracket { + p.getToken() + break + } + val := p.parseRvalue() + if reflect.TypeOf(val) != arrayType { + arrayType = nil + } + array = append(array, val) + follow = p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated array") + } + if follow.typ != tokenRightBracket && follow.typ != tokenComma { + p.raiseError(follow, "missing comma") + } + if follow.typ == tokenComma { + p.getToken() + } + } + + // if the array is a mixed-type array or its length is 0, + // don't convert it to a table array + if len(array) <= 0 { + arrayType = nil + } + // An array of Trees is actually an array of inline + // tables, which is a shorthand for a table array. If the + // array was not converted from []interface{} to []*Tree, + // the two notations would not be equivalent. + if arrayType == reflect.TypeOf(newTree()) { + tomlArray := make([]*Tree, len(array)) + for i, v := range array { + tomlArray[i] = v.(*Tree) + } + return tomlArray + } + return array +} + +func parseToml(flow []token) *Tree { + result := newTree() + result.position = Position{1, 1} + parser := &tomlParser{ + flowIdx: 0, + flow: flow, + tree: result, + currentTable: make([]string, 0), + seenTableKeys: make([]string, 0), + } + parser.run() + return result +} diff --git a/vendor/github.com/pelletier/go-toml/position.go b/vendor/github.com/pelletier/go-toml/position.go new file mode 100644 index 000000000..c17bff87b --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/position.go @@ -0,0 +1,29 @@ +// Position support for go-toml + +package toml + +import ( + "fmt" +) + +// Position of a document element within a TOML document. +// +// Line and Col are both 1-indexed positions for the element's line number and +// column number, respectively. Values of zero or less will cause Invalid(), +// to return true. +type Position struct { + Line int // line within the document + Col int // column within the line +} + +// String representation of the position. +// Displays 1-indexed line and column numbers. +func (p Position) String() string { + return fmt.Sprintf("(%d, %d)", p.Line, p.Col) +} + +// Invalid returns whether or not the position is valid (i.e. with negative or +// null values) +func (p Position) Invalid() bool { + return p.Line <= 0 || p.Col <= 0 +} diff --git a/vendor/github.com/pelletier/go-toml/token.go b/vendor/github.com/pelletier/go-toml/token.go new file mode 100644 index 000000000..b437fdd3b --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/token.go @@ -0,0 +1,136 @@ +package toml + +import "fmt" + +// Define tokens +type tokenType int + +const ( + eof = -(iota + 1) +) + +const ( + tokenError tokenType = iota + tokenEOF + tokenComment + tokenKey + tokenString + tokenInteger + tokenTrue + tokenFalse + tokenFloat + tokenInf + tokenNan + tokenEqual + tokenLeftBracket + tokenRightBracket + tokenLeftCurlyBrace + tokenRightCurlyBrace + tokenLeftParen + tokenRightParen + tokenDoubleLeftBracket + tokenDoubleRightBracket + tokenLocalDate + tokenLocalTime + tokenTimeOffset + tokenKeyGroup + tokenKeyGroupArray + tokenComma + tokenColon + tokenDollar + tokenStar + tokenQuestion + tokenDot + tokenDotDot + tokenEOL +) + +var tokenTypeNames = []string{ + "Error", + "EOF", + "Comment", + "Key", + "String", + "Integer", + "True", + "False", + "Float", + "Inf", + "NaN", + "=", + "[", + "]", + "{", + "}", + "(", + ")", + "]]", + "[[", + "LocalDate", + "LocalTime", + "TimeOffset", + "KeyGroup", + "KeyGroupArray", + ",", + ":", + "$", + "*", + "?", + ".", + "..", + "EOL", +} + +type token struct { + Position + typ tokenType + val string +} + +func (tt tokenType) String() string { + idx := int(tt) + if idx < len(tokenTypeNames) { + return tokenTypeNames[idx] + } + return "Unknown" +} + +func (t token) String() string { + switch t.typ { + case tokenEOF: + return "EOF" + case tokenError: + return t.val + } + + return fmt.Sprintf("%q", t.val) +} + +func isSpace(r rune) bool { + return r == ' ' || r == '\t' +} + +func isAlphanumeric(r rune) bool { + return 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || r == '_' +} + +func isKeyChar(r rune) bool { + // Keys start with the first character that isn't whitespace or [ and end + // with the last non-whitespace character before the equals sign. Keys + // cannot contain a # character." + return !(r == '\r' || r == '\n' || r == eof || r == '=') +} + +func isKeyStartChar(r rune) bool { + return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '[') +} + +func isDigit(r rune) bool { + return '0' <= r && r <= '9' +} + +func isHexDigit(r rune) bool { + return isDigit(r) || + (r >= 'a' && r <= 'f') || + (r >= 'A' && r <= 'F') +} diff --git a/vendor/github.com/pelletier/go-toml/toml.go b/vendor/github.com/pelletier/go-toml/toml.go new file mode 100644 index 000000000..6d82587c4 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/toml.go @@ -0,0 +1,533 @@ +package toml + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "runtime" + "strings" +) + +type tomlValue struct { + value interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list + comment string + commented bool + multiline bool + literal bool + position Position +} + +// Tree is the result of the parsing of a TOML file. +type Tree struct { + values map[string]interface{} // string -> *tomlValue, *Tree, []*Tree + comment string + commented bool + inline bool + position Position +} + +func newTree() *Tree { + return newTreeWithPosition(Position{}) +} + +func newTreeWithPosition(pos Position) *Tree { + return &Tree{ + values: make(map[string]interface{}), + position: pos, + } +} + +// TreeFromMap initializes a new Tree object using the given map. +func TreeFromMap(m map[string]interface{}) (*Tree, error) { + result, err := toTree(m) + if err != nil { + return nil, err + } + return result.(*Tree), nil +} + +// Position returns the position of the tree. +func (t *Tree) Position() Position { + return t.position +} + +// Has returns a boolean indicating if the given key exists. +func (t *Tree) Has(key string) bool { + if key == "" { + return false + } + return t.HasPath(strings.Split(key, ".")) +} + +// HasPath returns true if the given path of keys exists, false otherwise. +func (t *Tree) HasPath(keys []string) bool { + return t.GetPath(keys) != nil +} + +// Keys returns the keys of the toplevel tree (does not recurse). +func (t *Tree) Keys() []string { + keys := make([]string, len(t.values)) + i := 0 + for k := range t.values { + keys[i] = k + i++ + } + return keys +} + +// Get the value at key in the Tree. +// Key is a dot-separated path (e.g. a.b.c) without single/double quoted strings. +// If you need to retrieve non-bare keys, use GetPath. +// Returns nil if the path does not exist in the tree. +// If keys is of length zero, the current tree is returned. +func (t *Tree) Get(key string) interface{} { + if key == "" { + return t + } + return t.GetPath(strings.Split(key, ".")) +} + +// GetPath returns the element in the tree indicated by 'keys'. +// If keys is of length zero, the current tree is returned. +func (t *Tree) GetPath(keys []string) interface{} { + if len(keys) == 0 { + return t + } + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + value, exists := subtree.values[intermediateKey] + if !exists { + return nil + } + switch node := value.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + return nil + } + subtree = node[len(node)-1] + default: + return nil // cannot navigate through other node types + } + } + // branch based on final node type + switch node := subtree.values[keys[len(keys)-1]].(type) { + case *tomlValue: + return node.value + default: + return node + } +} + +// GetArray returns the value at key in the Tree. +// It returns []string, []int64, etc type if key has homogeneous lists +// Key is a dot-separated path (e.g. a.b.c) without single/double quoted strings. +// Returns nil if the path does not exist in the tree. +// If keys is of length zero, the current tree is returned. +func (t *Tree) GetArray(key string) interface{} { + if key == "" { + return t + } + return t.GetArrayPath(strings.Split(key, ".")) +} + +// GetArrayPath returns the element in the tree indicated by 'keys'. +// If keys is of length zero, the current tree is returned. +func (t *Tree) GetArrayPath(keys []string) interface{} { + if len(keys) == 0 { + return t + } + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + value, exists := subtree.values[intermediateKey] + if !exists { + return nil + } + switch node := value.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + return nil + } + subtree = node[len(node)-1] + default: + return nil // cannot navigate through other node types + } + } + // branch based on final node type + switch node := subtree.values[keys[len(keys)-1]].(type) { + case *tomlValue: + switch n := node.value.(type) { + case []interface{}: + return getArray(n) + default: + return node.value + } + default: + return node + } +} + +// if homogeneous array, then return slice type object over []interface{} +func getArray(n []interface{}) interface{} { + var s []string + var i64 []int64 + var f64 []float64 + var bl []bool + for _, value := range n { + switch v := value.(type) { + case string: + s = append(s, v) + case int64: + i64 = append(i64, v) + case float64: + f64 = append(f64, v) + case bool: + bl = append(bl, v) + default: + return n + } + } + if len(s) == len(n) { + return s + } else if len(i64) == len(n) { + return i64 + } else if len(f64) == len(n) { + return f64 + } else if len(bl) == len(n) { + return bl + } + return n +} + +// GetPosition returns the position of the given key. +func (t *Tree) GetPosition(key string) Position { + if key == "" { + return t.position + } + return t.GetPositionPath(strings.Split(key, ".")) +} + +// SetPositionPath sets the position of element in the tree indicated by 'keys'. +// If keys is of length zero, the current tree position is set. +func (t *Tree) SetPositionPath(keys []string, pos Position) { + if len(keys) == 0 { + t.position = pos + return + } + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + value, exists := subtree.values[intermediateKey] + if !exists { + return + } + switch node := value.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + return + } + subtree = node[len(node)-1] + default: + return + } + } + // branch based on final node type + switch node := subtree.values[keys[len(keys)-1]].(type) { + case *tomlValue: + node.position = pos + return + case *Tree: + node.position = pos + return + case []*Tree: + // go to most recent element + if len(node) == 0 { + return + } + node[len(node)-1].position = pos + return + } +} + +// GetPositionPath returns the element in the tree indicated by 'keys'. +// If keys is of length zero, the current tree is returned. +func (t *Tree) GetPositionPath(keys []string) Position { + if len(keys) == 0 { + return t.position + } + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + value, exists := subtree.values[intermediateKey] + if !exists { + return Position{0, 0} + } + switch node := value.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + return Position{0, 0} + } + subtree = node[len(node)-1] + default: + return Position{0, 0} + } + } + // branch based on final node type + switch node := subtree.values[keys[len(keys)-1]].(type) { + case *tomlValue: + return node.position + case *Tree: + return node.position + case []*Tree: + // go to most recent element + if len(node) == 0 { + return Position{0, 0} + } + return node[len(node)-1].position + default: + return Position{0, 0} + } +} + +// GetDefault works like Get but with a default value +func (t *Tree) GetDefault(key string, def interface{}) interface{} { + val := t.Get(key) + if val == nil { + return def + } + return val +} + +// SetOptions arguments are supplied to the SetWithOptions and SetPathWithOptions functions to modify marshalling behaviour. +// The default values within the struct are valid default options. +type SetOptions struct { + Comment string + Commented bool + Multiline bool + Literal bool +} + +// SetWithOptions is the same as Set, but allows you to provide formatting +// instructions to the key, that will be used by Marshal(). +func (t *Tree) SetWithOptions(key string, opts SetOptions, value interface{}) { + t.SetPathWithOptions(strings.Split(key, "."), opts, value) +} + +// SetPathWithOptions is the same as SetPath, but allows you to provide +// formatting instructions to the key, that will be reused by Marshal(). +func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interface{}) { + subtree := t + for i, intermediateKey := range keys[:len(keys)-1] { + nextTree, exists := subtree.values[intermediateKey] + if !exists { + nextTree = newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}) + subtree.values[intermediateKey] = nextTree // add new element here + } + switch node := nextTree.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + // create element if it does not exist + node = append(node, newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col})) + subtree.values[intermediateKey] = node + } + subtree = node[len(node)-1] + } + } + + var toInsert interface{} + + switch v := value.(type) { + case *Tree: + v.comment = opts.Comment + v.commented = opts.Commented + toInsert = value + case []*Tree: + for i := range v { + v[i].commented = opts.Commented + } + toInsert = value + case *tomlValue: + v.comment = opts.Comment + v.commented = opts.Commented + v.multiline = opts.Multiline + v.literal = opts.Literal + toInsert = v + default: + toInsert = &tomlValue{value: value, + comment: opts.Comment, + commented: opts.Commented, + multiline: opts.Multiline, + literal: opts.Literal, + position: Position{Line: subtree.position.Line + len(subtree.values) + 1, Col: subtree.position.Col}} + } + + subtree.values[keys[len(keys)-1]] = toInsert +} + +// Set an element in the tree. +// Key is a dot-separated path (e.g. a.b.c). +// Creates all necessary intermediate trees, if needed. +func (t *Tree) Set(key string, value interface{}) { + t.SetWithComment(key, "", false, value) +} + +// SetWithComment is the same as Set, but allows you to provide comment +// information to the key, that will be reused by Marshal(). +func (t *Tree) SetWithComment(key string, comment string, commented bool, value interface{}) { + t.SetPathWithComment(strings.Split(key, "."), comment, commented, value) +} + +// SetPath sets an element in the tree. +// Keys is an array of path elements (e.g. {"a","b","c"}). +// Creates all necessary intermediate trees, if needed. +func (t *Tree) SetPath(keys []string, value interface{}) { + t.SetPathWithComment(keys, "", false, value) +} + +// SetPathWithComment is the same as SetPath, but allows you to provide comment +// information to the key, that will be reused by Marshal(). +func (t *Tree) SetPathWithComment(keys []string, comment string, commented bool, value interface{}) { + t.SetPathWithOptions(keys, SetOptions{Comment: comment, Commented: commented}, value) +} + +// Delete removes a key from the tree. +// Key is a dot-separated path (e.g. a.b.c). +func (t *Tree) Delete(key string) error { + keys, err := parseKey(key) + if err != nil { + return err + } + return t.DeletePath(keys) +} + +// DeletePath removes a key from the tree. +// Keys is an array of path elements (e.g. {"a","b","c"}). +func (t *Tree) DeletePath(keys []string) error { + keyLen := len(keys) + if keyLen == 1 { + delete(t.values, keys[0]) + return nil + } + tree := t.GetPath(keys[:keyLen-1]) + item := keys[keyLen-1] + switch node := tree.(type) { + case *Tree: + delete(node.values, item) + return nil + } + return errors.New("no such key to delete") +} + +// createSubTree takes a tree and a key and create the necessary intermediate +// subtrees to create a subtree at that point. In-place. +// +// e.g. passing a.b.c will create (assuming tree is empty) tree[a], tree[a][b] +// and tree[a][b][c] +// +// Returns nil on success, error object on failure +func (t *Tree) createSubTree(keys []string, pos Position) error { + subtree := t + for i, intermediateKey := range keys { + nextTree, exists := subtree.values[intermediateKey] + if !exists { + tree := newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}) + tree.position = pos + tree.inline = subtree.inline + subtree.values[intermediateKey] = tree + nextTree = tree + } + + switch node := nextTree.(type) { + case []*Tree: + subtree = node[len(node)-1] + case *Tree: + subtree = node + default: + return fmt.Errorf("unknown type for path %s (%s): %T (%#v)", + strings.Join(keys, "."), intermediateKey, nextTree, nextTree) + } + } + return nil +} + +// LoadBytes creates a Tree from a []byte. +func LoadBytes(b []byte) (tree *Tree, err error) { + defer func() { + if r := recover(); r != nil { + if _, ok := r.(runtime.Error); ok { + panic(r) + } + err = errors.New(r.(string)) + } + }() + + if len(b) >= 4 && (hasUTF32BigEndianBOM4(b) || hasUTF32LittleEndianBOM4(b)) { + b = b[4:] + } else if len(b) >= 3 && hasUTF8BOM3(b) { + b = b[3:] + } else if len(b) >= 2 && (hasUTF16BigEndianBOM2(b) || hasUTF16LittleEndianBOM2(b)) { + b = b[2:] + } + + tree = parseToml(lexToml(b)) + return +} + +func hasUTF16BigEndianBOM2(b []byte) bool { + return b[0] == 0xFE && b[1] == 0xFF +} + +func hasUTF16LittleEndianBOM2(b []byte) bool { + return b[0] == 0xFF && b[1] == 0xFE +} + +func hasUTF8BOM3(b []byte) bool { + return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF +} + +func hasUTF32BigEndianBOM4(b []byte) bool { + return b[0] == 0x00 && b[1] == 0x00 && b[2] == 0xFE && b[3] == 0xFF +} + +func hasUTF32LittleEndianBOM4(b []byte) bool { + return b[0] == 0xFF && b[1] == 0xFE && b[2] == 0x00 && b[3] == 0x00 +} + +// LoadReader creates a Tree from any io.Reader. +func LoadReader(reader io.Reader) (tree *Tree, err error) { + inputBytes, err := ioutil.ReadAll(reader) + if err != nil { + return + } + tree, err = LoadBytes(inputBytes) + return +} + +// Load creates a Tree from a string. +func Load(content string) (tree *Tree, err error) { + return LoadBytes([]byte(content)) +} + +// LoadFile creates a Tree from a file. +func LoadFile(path string) (tree *Tree, err error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + return LoadReader(file) +} diff --git a/vendor/github.com/pelletier/go-toml/tomlpub.go b/vendor/github.com/pelletier/go-toml/tomlpub.go new file mode 100644 index 000000000..4136b4625 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomlpub.go @@ -0,0 +1,71 @@ +package toml + +// PubTOMLValue wrapping tomlValue in order to access all properties from outside. +type PubTOMLValue = tomlValue + +func (ptv *PubTOMLValue) Value() interface{} { + return ptv.value +} +func (ptv *PubTOMLValue) Comment() string { + return ptv.comment +} +func (ptv *PubTOMLValue) Commented() bool { + return ptv.commented +} +func (ptv *PubTOMLValue) Multiline() bool { + return ptv.multiline +} +func (ptv *PubTOMLValue) Position() Position { + return ptv.position +} + +func (ptv *PubTOMLValue) SetValue(v interface{}) { + ptv.value = v +} +func (ptv *PubTOMLValue) SetComment(s string) { + ptv.comment = s +} +func (ptv *PubTOMLValue) SetCommented(c bool) { + ptv.commented = c +} +func (ptv *PubTOMLValue) SetMultiline(m bool) { + ptv.multiline = m +} +func (ptv *PubTOMLValue) SetPosition(p Position) { + ptv.position = p +} + +// PubTree wrapping Tree in order to access all properties from outside. +type PubTree = Tree + +func (pt *PubTree) Values() map[string]interface{} { + return pt.values +} + +func (pt *PubTree) Comment() string { + return pt.comment +} + +func (pt *PubTree) Commented() bool { + return pt.commented +} + +func (pt *PubTree) Inline() bool { + return pt.inline +} + +func (pt *PubTree) SetValues(v map[string]interface{}) { + pt.values = v +} + +func (pt *PubTree) SetComment(c string) { + pt.comment = c +} + +func (pt *PubTree) SetCommented(c bool) { + pt.commented = c +} + +func (pt *PubTree) SetInline(i bool) { + pt.inline = i +} diff --git a/vendor/github.com/pelletier/go-toml/tomltree_create.go b/vendor/github.com/pelletier/go-toml/tomltree_create.go new file mode 100644 index 000000000..80353500a --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomltree_create.go @@ -0,0 +1,155 @@ +package toml + +import ( + "fmt" + "reflect" + "time" +) + +var kindToType = [reflect.String + 1]reflect.Type{ + reflect.Bool: reflect.TypeOf(true), + reflect.String: reflect.TypeOf(""), + reflect.Float32: reflect.TypeOf(float64(1)), + reflect.Float64: reflect.TypeOf(float64(1)), + reflect.Int: reflect.TypeOf(int64(1)), + reflect.Int8: reflect.TypeOf(int64(1)), + reflect.Int16: reflect.TypeOf(int64(1)), + reflect.Int32: reflect.TypeOf(int64(1)), + reflect.Int64: reflect.TypeOf(int64(1)), + reflect.Uint: reflect.TypeOf(uint64(1)), + reflect.Uint8: reflect.TypeOf(uint64(1)), + reflect.Uint16: reflect.TypeOf(uint64(1)), + reflect.Uint32: reflect.TypeOf(uint64(1)), + reflect.Uint64: reflect.TypeOf(uint64(1)), +} + +// typeFor returns a reflect.Type for a reflect.Kind, or nil if none is found. +// supported values: +// string, bool, int64, uint64, float64, time.Time, int, int8, int16, int32, uint, uint8, uint16, uint32, float32 +func typeFor(k reflect.Kind) reflect.Type { + if k > 0 && int(k) < len(kindToType) { + return kindToType[k] + } + return nil +} + +func simpleValueCoercion(object interface{}) (interface{}, error) { + switch original := object.(type) { + case string, bool, int64, uint64, float64, time.Time: + return original, nil + case int: + return int64(original), nil + case int8: + return int64(original), nil + case int16: + return int64(original), nil + case int32: + return int64(original), nil + case uint: + return uint64(original), nil + case uint8: + return uint64(original), nil + case uint16: + return uint64(original), nil + case uint32: + return uint64(original), nil + case float32: + return float64(original), nil + case fmt.Stringer: + return original.String(), nil + case []interface{}: + value := reflect.ValueOf(original) + length := value.Len() + arrayValue := reflect.MakeSlice(value.Type(), 0, length) + for i := 0; i < length; i++ { + val := value.Index(i).Interface() + simpleValue, err := simpleValueCoercion(val) + if err != nil { + return nil, err + } + arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue)) + } + return arrayValue.Interface(), nil + default: + return nil, fmt.Errorf("cannot convert type %T to Tree", object) + } +} + +func sliceToTree(object interface{}) (interface{}, error) { + // arrays are a bit tricky, since they can represent either a + // collection of simple values, which is represented by one + // *tomlValue, or an array of tables, which is represented by an + // array of *Tree. + + // holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice + value := reflect.ValueOf(object) + insideType := value.Type().Elem() + length := value.Len() + if length > 0 { + insideType = reflect.ValueOf(value.Index(0).Interface()).Type() + } + if insideType.Kind() == reflect.Map { + // this is considered as an array of tables + tablesArray := make([]*Tree, 0, length) + for i := 0; i < length; i++ { + table := value.Index(i) + tree, err := toTree(table.Interface()) + if err != nil { + return nil, err + } + tablesArray = append(tablesArray, tree.(*Tree)) + } + return tablesArray, nil + } + + sliceType := typeFor(insideType.Kind()) + if sliceType == nil { + sliceType = insideType + } + + arrayValue := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, length) + + for i := 0; i < length; i++ { + val := value.Index(i).Interface() + simpleValue, err := simpleValueCoercion(val) + if err != nil { + return nil, err + } + arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue)) + } + return &tomlValue{value: arrayValue.Interface(), position: Position{}}, nil +} + +func toTree(object interface{}) (interface{}, error) { + value := reflect.ValueOf(object) + + if value.Kind() == reflect.Map { + values := map[string]interface{}{} + keys := value.MapKeys() + for _, key := range keys { + if key.Kind() != reflect.String { + if _, ok := key.Interface().(string); !ok { + return nil, fmt.Errorf("map key needs to be a string, not %T (%v)", key.Interface(), key.Kind()) + } + } + + v := value.MapIndex(key) + newValue, err := toTree(v.Interface()) + if err != nil { + return nil, err + } + values[key.String()] = newValue + } + return &Tree{values: values, position: Position{}}, nil + } + + if value.Kind() == reflect.Array || value.Kind() == reflect.Slice { + return sliceToTree(object) + } + + simpleValue, err := simpleValueCoercion(object) + if err != nil { + return nil, err + } + return &tomlValue{value: simpleValue, position: Position{}}, nil +} diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write.go b/vendor/github.com/pelletier/go-toml/tomltree_write.go new file mode 100644 index 000000000..c9afbdab7 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomltree_write.go @@ -0,0 +1,552 @@ +package toml + +import ( + "bytes" + "fmt" + "io" + "math" + "math/big" + "reflect" + "sort" + "strconv" + "strings" + "time" +) + +type valueComplexity int + +const ( + valueSimple valueComplexity = iota + 1 + valueComplex +) + +type sortNode struct { + key string + complexity valueComplexity +} + +// Encodes a string to a TOML-compliant multi-line string value +// This function is a clone of the existing encodeTomlString function, except that whitespace characters +// are preserved. Quotation marks and backslashes are also not escaped. +func encodeMultilineTomlString(value string, commented string) string { + var b bytes.Buffer + adjacentQuoteCount := 0 + + b.WriteString(commented) + for i, rr := range value { + if rr != '"' { + adjacentQuoteCount = 0 + } else { + adjacentQuoteCount++ + } + switch rr { + case '\b': + b.WriteString(`\b`) + case '\t': + b.WriteString("\t") + case '\n': + b.WriteString("\n" + commented) + case '\f': + b.WriteString(`\f`) + case '\r': + b.WriteString("\r") + case '"': + if adjacentQuoteCount >= 3 || i == len(value)-1 { + adjacentQuoteCount = 0 + b.WriteString(`\"`) + } else { + b.WriteString(`"`) + } + case '\\': + b.WriteString(`\`) + default: + intRr := uint16(rr) + if intRr < 0x001F { + b.WriteString(fmt.Sprintf("\\u%0.4X", intRr)) + } else { + b.WriteRune(rr) + } + } + } + return b.String() +} + +// Encodes a string to a TOML-compliant string value +func encodeTomlString(value string) string { + var b bytes.Buffer + + for _, rr := range value { + switch rr { + case '\b': + b.WriteString(`\b`) + case '\t': + b.WriteString(`\t`) + case '\n': + b.WriteString(`\n`) + case '\f': + b.WriteString(`\f`) + case '\r': + b.WriteString(`\r`) + case '"': + b.WriteString(`\"`) + case '\\': + b.WriteString(`\\`) + default: + intRr := uint16(rr) + if intRr < 0x001F { + b.WriteString(fmt.Sprintf("\\u%0.4X", intRr)) + } else { + b.WriteRune(rr) + } + } + } + return b.String() +} + +func tomlTreeStringRepresentation(t *Tree, ord MarshalOrder) (string, error) { + var orderedVals []sortNode + switch ord { + case OrderPreserve: + orderedVals = sortByLines(t) + default: + orderedVals = sortAlphabetical(t) + } + + var values []string + for _, node := range orderedVals { + k := node.key + v := t.values[k] + + repr, err := tomlValueStringRepresentation(v, "", "", ord, false) + if err != nil { + return "", err + } + values = append(values, quoteKeyIfNeeded(k)+" = "+repr) + } + return "{ " + strings.Join(values, ", ") + " }", nil +} + +func tomlValueStringRepresentation(v interface{}, commented string, indent string, ord MarshalOrder, arraysOneElementPerLine bool) (string, error) { + // this interface check is added to dereference the change made in the writeTo function. + // That change was made to allow this function to see formatting options. + tv, ok := v.(*tomlValue) + if ok { + v = tv.value + } else { + tv = &tomlValue{} + } + + switch value := v.(type) { + case uint64: + return strconv.FormatUint(value, 10), nil + case int64: + return strconv.FormatInt(value, 10), nil + case float64: + // Default bit length is full 64 + bits := 64 + // Float panics if nan is used + if !math.IsNaN(value) { + // if 32 bit accuracy is enough to exactly show, use 32 + _, acc := big.NewFloat(value).Float32() + if acc == big.Exact { + bits = 32 + } + } + if math.Trunc(value) == value { + return strings.ToLower(strconv.FormatFloat(value, 'f', 1, bits)), nil + } + return strings.ToLower(strconv.FormatFloat(value, 'f', -1, bits)), nil + case string: + if tv.multiline { + if tv.literal { + b := strings.Builder{} + b.WriteString("'''\n") + b.Write([]byte(value)) + b.WriteString("\n'''") + return b.String(), nil + } else { + return "\"\"\"\n" + encodeMultilineTomlString(value, commented) + "\"\"\"", nil + } + } + return "\"" + encodeTomlString(value) + "\"", nil + case []byte: + b, _ := v.([]byte) + return string(b), nil + case bool: + if value { + return "true", nil + } + return "false", nil + case time.Time: + return value.Format(time.RFC3339), nil + case LocalDate: + return value.String(), nil + case LocalDateTime: + return value.String(), nil + case LocalTime: + return value.String(), nil + case *Tree: + return tomlTreeStringRepresentation(value, ord) + case nil: + return "", nil + } + + rv := reflect.ValueOf(v) + + if rv.Kind() == reflect.Slice { + var values []string + for i := 0; i < rv.Len(); i++ { + item := rv.Index(i).Interface() + itemRepr, err := tomlValueStringRepresentation(item, commented, indent, ord, arraysOneElementPerLine) + if err != nil { + return "", err + } + values = append(values, itemRepr) + } + if arraysOneElementPerLine && len(values) > 1 { + stringBuffer := bytes.Buffer{} + valueIndent := indent + ` ` // TODO: move that to a shared encoder state + + stringBuffer.WriteString("[\n") + + for _, value := range values { + stringBuffer.WriteString(valueIndent) + stringBuffer.WriteString(commented + value) + stringBuffer.WriteString(`,`) + stringBuffer.WriteString("\n") + } + + stringBuffer.WriteString(indent + commented + "]") + + return stringBuffer.String(), nil + } + return "[" + strings.Join(values, ", ") + "]", nil + } + return "", fmt.Errorf("unsupported value type %T: %v", v, v) +} + +func getTreeArrayLine(trees []*Tree) (line int) { + // Prevent returning 0 for empty trees + line = int(^uint(0) >> 1) + // get lowest line number >= 0 + for _, tv := range trees { + if tv.position.Line < line || line == 0 { + line = tv.position.Line + } + } + return +} + +func sortByLines(t *Tree) (vals []sortNode) { + var ( + line int + lines []int + tv *Tree + tom *tomlValue + node sortNode + ) + vals = make([]sortNode, 0) + m := make(map[int]sortNode) + + for k := range t.values { + v := t.values[k] + switch v.(type) { + case *Tree: + tv = v.(*Tree) + line = tv.position.Line + node = sortNode{key: k, complexity: valueComplex} + case []*Tree: + line = getTreeArrayLine(v.([]*Tree)) + node = sortNode{key: k, complexity: valueComplex} + default: + tom = v.(*tomlValue) + line = tom.position.Line + node = sortNode{key: k, complexity: valueSimple} + } + lines = append(lines, line) + vals = append(vals, node) + m[line] = node + } + sort.Ints(lines) + + for i, line := range lines { + vals[i] = m[line] + } + + return vals +} + +func sortAlphabetical(t *Tree) (vals []sortNode) { + var ( + node sortNode + simpVals []string + compVals []string + ) + vals = make([]sortNode, 0) + m := make(map[string]sortNode) + + for k := range t.values { + v := t.values[k] + switch v.(type) { + case *Tree, []*Tree: + node = sortNode{key: k, complexity: valueComplex} + compVals = append(compVals, node.key) + default: + node = sortNode{key: k, complexity: valueSimple} + simpVals = append(simpVals, node.key) + } + vals = append(vals, node) + m[node.key] = node + } + + // Simples first to match previous implementation + sort.Strings(simpVals) + i := 0 + for _, key := range simpVals { + vals[i] = m[key] + i++ + } + + sort.Strings(compVals) + for _, key := range compVals { + vals[i] = m[key] + i++ + } + + return vals +} + +func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) { + return t.writeToOrdered(w, indent, keyspace, bytesCount, arraysOneElementPerLine, OrderAlphabetical, " ", false, false) +} + +func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool, ord MarshalOrder, indentString string, compactComments, parentCommented bool) (int64, error) { + var orderedVals []sortNode + + switch ord { + case OrderPreserve: + orderedVals = sortByLines(t) + default: + orderedVals = sortAlphabetical(t) + } + + for _, node := range orderedVals { + switch node.complexity { + case valueComplex: + k := node.key + v := t.values[k] + + combinedKey := quoteKeyIfNeeded(k) + if keyspace != "" { + combinedKey = keyspace + "." + combinedKey + } + + switch node := v.(type) { + // node has to be of those two types given how keys are sorted above + case *Tree: + tv, ok := t.values[k].(*Tree) + if !ok { + return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k]) + } + if tv.comment != "" { + comment := strings.Replace(tv.comment, "\n", "\n"+indent+"#", -1) + start := "# " + if strings.HasPrefix(comment, "#") { + start = "" + } + writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment) + bytesCount += int64(writtenBytesCountComment) + if errc != nil { + return bytesCount, errc + } + } + + var commented string + if parentCommented || t.commented || tv.commented { + commented = "# " + } + writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + bytesCount, err = node.writeToOrdered(w, indent+indentString, combinedKey, bytesCount, arraysOneElementPerLine, ord, indentString, compactComments, parentCommented || t.commented || tv.commented) + if err != nil { + return bytesCount, err + } + case []*Tree: + for _, subTree := range node { + var commented string + if parentCommented || t.commented || subTree.commented { + commented = "# " + } + writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[[", combinedKey, "]]\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + + bytesCount, err = subTree.writeToOrdered(w, indent+indentString, combinedKey, bytesCount, arraysOneElementPerLine, ord, indentString, compactComments, parentCommented || t.commented || subTree.commented) + if err != nil { + return bytesCount, err + } + } + } + default: // Simple + k := node.key + v, ok := t.values[k].(*tomlValue) + if !ok { + return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k]) + } + + var commented string + if parentCommented || t.commented || v.commented { + commented = "# " + } + repr, err := tomlValueStringRepresentation(v, commented, indent, ord, arraysOneElementPerLine) + if err != nil { + return bytesCount, err + } + + if v.comment != "" { + comment := strings.Replace(v.comment, "\n", "\n"+indent+"#", -1) + start := "# " + if strings.HasPrefix(comment, "#") { + start = "" + } + if !compactComments { + writtenBytesCountComment, errc := writeStrings(w, "\n") + bytesCount += int64(writtenBytesCountComment) + if errc != nil { + return bytesCount, errc + } + } + writtenBytesCountComment, errc := writeStrings(w, indent, start, comment, "\n") + bytesCount += int64(writtenBytesCountComment) + if errc != nil { + return bytesCount, errc + } + } + + quotedKey := quoteKeyIfNeeded(k) + writtenBytesCount, err := writeStrings(w, indent, commented, quotedKey, " = ", repr, "\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + } + } + + return bytesCount, nil +} + +// quote a key if it does not fit the bare key format (A-Za-z0-9_-) +// quoted keys use the same rules as strings +func quoteKeyIfNeeded(k string) string { + // when encoding a map with the 'quoteMapKeys' option enabled, the tree will contain + // keys that have already been quoted. + // not an ideal situation, but good enough of a stop gap. + if len(k) >= 2 && k[0] == '"' && k[len(k)-1] == '"' { + return k + } + isBare := true + for _, r := range k { + if !isValidBareChar(r) { + isBare = false + break + } + } + if isBare { + return k + } + return quoteKey(k) +} + +func quoteKey(k string) string { + return "\"" + encodeTomlString(k) + "\"" +} + +func writeStrings(w io.Writer, s ...string) (int, error) { + var n int + for i := range s { + b, err := io.WriteString(w, s[i]) + n += b + if err != nil { + return n, err + } + } + return n, nil +} + +// WriteTo encode the Tree as Toml and writes it to the writer w. +// Returns the number of bytes written in case of success, or an error if anything happened. +func (t *Tree) WriteTo(w io.Writer) (int64, error) { + return t.writeTo(w, "", "", 0, false) +} + +// ToTomlString generates a human-readable representation of the current tree. +// Output spans multiple lines, and is suitable for ingest by a TOML parser. +// If the conversion cannot be performed, ToString returns a non-nil error. +func (t *Tree) ToTomlString() (string, error) { + b, err := t.Marshal() + if err != nil { + return "", err + } + return string(b), nil +} + +// String generates a human-readable representation of the current tree. +// Alias of ToString. Present to implement the fmt.Stringer interface. +func (t *Tree) String() string { + result, _ := t.ToTomlString() + return result +} + +// ToMap recursively generates a representation of the tree using Go built-in structures. +// The following types are used: +// +// * bool +// * float64 +// * int64 +// * string +// * uint64 +// * time.Time +// * map[string]interface{} (where interface{} is any of this list) +// * []interface{} (where interface{} is any of this list) +func (t *Tree) ToMap() map[string]interface{} { + result := map[string]interface{}{} + + for k, v := range t.values { + switch node := v.(type) { + case []*Tree: + var array []interface{} + for _, item := range node { + array = append(array, item.ToMap()) + } + result[k] = array + case *Tree: + result[k] = node.ToMap() + case *tomlValue: + result[k] = tomlValueToGo(node.value) + } + } + return result +} + +func tomlValueToGo(v interface{}) interface{} { + if tree, ok := v.(*Tree); ok { + return tree.ToMap() + } + + rv := reflect.ValueOf(v) + + if rv.Kind() != reflect.Slice { + return v + } + values := make([]interface{}, rv.Len()) + for i := 0; i < rv.Len(); i++ { + item := rv.Index(i).Interface() + values[i] = tomlValueToGo(item) + } + return values +} diff --git a/vendor/github.com/pelletier/go-toml/tomltree_writepub.go b/vendor/github.com/pelletier/go-toml/tomltree_writepub.go new file mode 100644 index 000000000..fa326308c --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomltree_writepub.go @@ -0,0 +1,6 @@ +package toml + +// ValueStringRepresentation transforms an interface{} value into its toml string representation. +func ValueStringRepresentation(v interface{}, commented string, indent string, ord MarshalOrder, arraysOneElementPerLine bool) (string, error) { + return tomlValueStringRepresentation(v, commented, indent, ord, arraysOneElementPerLine) +} diff --git a/vendor/github.com/weppos/publicsuffix-go/publicsuffix/rules.go b/vendor/github.com/weppos/publicsuffix-go/publicsuffix/rules.go index 1514f9c5f..a3f887e00 100644 --- a/vendor/github.com/weppos/publicsuffix-go/publicsuffix/rules.go +++ b/vendor/github.com/weppos/publicsuffix-go/publicsuffix/rules.go @@ -3,13 +3,13 @@ package publicsuffix -const defaultListVersion = "PSL version 598c63 (Thu May 6 04:03:10 2021)" +const defaultListVersion = "PSL version fd5650 (Sun Mar 27 15:19:06 2022)" -func DefaultRules() [9169]Rule { +func DefaultRules() [9333]Rule { return r } -var r = [9169]Rule{ +var r = [9333]Rule{ {1, "ac", 1, false}, {1, "com.ac", 2, false}, {1, "edu.ac", 2, false}, @@ -153,15 +153,19 @@ var r = [9169]Rule{ {1, "it.ao", 2, false}, {1, "aq", 1, false}, {1, "ar", 1, false}, + {1, "bet.ar", 2, false}, {1, "com.ar", 2, false}, + {1, "coop.ar", 2, false}, {1, "edu.ar", 2, false}, {1, "gob.ar", 2, false}, {1, "gov.ar", 2, false}, {1, "int.ar", 2, false}, {1, "mil.ar", 2, false}, {1, "musica.ar", 2, false}, + {1, "mutual.ar", 2, false}, {1, "net.ar", 2, false}, {1, "org.ar", 2, false}, + {1, "senasa.ar", 2, false}, {1, "tur.ar", 2, false}, {1, "arpa", 1, false}, {1, "e164.arpa", 2, false}, @@ -598,7 +602,6 @@ var r = [9169]Rule{ {2, "ck", 2, false}, {3, "www.ck", 2, false}, {1, "cl", 1, false}, - {1, "aprendemas.cl", 2, false}, {1, "co.cl", 2, false}, {1, "gob.cl", 2, false}, {1, "gov.cl", 2, false}, @@ -685,6 +688,11 @@ var r = [9169]Rule{ {1, "gov.cu", 2, false}, {1, "inf.cu", 2, false}, {1, "cv", 1, false}, + {1, "com.cv", 2, false}, + {1, "edu.cv", 2, false}, + {1, "int.cv", 2, false}, + {1, "nome.cv", 2, false}, + {1, "org.cv", 2, false}, {1, "cw", 1, false}, {1, "com.cw", 2, false}, {1, "edu.cw", 2, false}, @@ -699,10 +707,9 @@ var r = [9169]Rule{ {1, "ekloges.cy", 2, false}, {1, "gov.cy", 2, false}, {1, "ltd.cy", 2, false}, - {1, "name.cy", 2, false}, + {1, "mil.cy", 2, false}, {1, "net.cy", 2, false}, {1, "org.cy", 2, false}, - {1, "parliament.cy", 2, false}, {1, "press.cy", 2, false}, {1, "pro.cy", 2, false}, {1, "tm.cy", 2, false}, @@ -3387,11 +3394,10 @@ var r = [9169]Rule{ {1, "net.kw", 2, false}, {1, "org.kw", 2, false}, {1, "ky", 1, false}, - {1, "edu.ky", 2, false}, - {1, "gov.ky", 2, false}, {1, "com.ky", 2, false}, - {1, "org.ky", 2, false}, + {1, "edu.ky", 2, false}, {1, "net.ky", 2, false}, + {1, "org.ky", 2, false}, {1, "kz", 1, false}, {1, "org.kz", 2, false}, {1, "edu.kz", 2, false}, @@ -5567,21 +5573,14 @@ var r = [9169]Rule{ {1, "fin.tn", 2, false}, {1, "gov.tn", 2, false}, {1, "ind.tn", 2, false}, + {1, "info.tn", 2, false}, {1, "intl.tn", 2, false}, + {1, "mincom.tn", 2, false}, {1, "nat.tn", 2, false}, {1, "net.tn", 2, false}, {1, "org.tn", 2, false}, - {1, "info.tn", 2, false}, {1, "perso.tn", 2, false}, {1, "tourism.tn", 2, false}, - {1, "edunet.tn", 2, false}, - {1, "rnrt.tn", 2, false}, - {1, "rns.tn", 2, false}, - {1, "rnu.tn", 2, false}, - {1, "mincom.tn", 2, false}, - {1, "agrinet.tn", 2, false}, - {1, "defense.tn", 2, false}, - {1, "turen.tn", 2, false}, {1, "to", 1, false}, {1, "com.to", 2, false}, {1, "gov.to", 2, false}, @@ -6008,6 +6007,7 @@ var r = [9169]Rule{ {1, "edu.vc", 2, false}, {1, "ve", 1, false}, {1, "arts.ve", 2, false}, + {1, "bib.ve", 2, false}, {1, "co.ve", 2, false}, {1, "com.ve", 2, false}, {1, "e12.ve", 2, false}, @@ -6019,7 +6019,9 @@ var r = [9169]Rule{ {1, "int.ve", 2, false}, {1, "mil.ve", 2, false}, {1, "net.ve", 2, false}, + {1, "nom.ve", 2, false}, {1, "org.ve", 2, false}, + {1, "rar.ve", 2, false}, {1, "rec.ve", 2, false}, {1, "store.ve", 2, false}, {1, "tec.ve", 2, false}, @@ -6209,7 +6211,6 @@ var r = [9169]Rule{ {1, "adult", 1, false}, {1, "aeg", 1, false}, {1, "aetna", 1, false}, - {1, "afamilycompany", 1, false}, {1, "afl", 1, false}, {1, "africa", 1, false}, {1, "agakhan", 1, false}, @@ -6330,7 +6331,6 @@ var r = [9169]Rule{ {1, "broker", 1, false}, {1, "brother", 1, false}, {1, "brussels", 1, false}, - {1, "budapest", 1, false}, {1, "bugatti", 1, false}, {1, "build", 1, false}, {1, "builders", 1, false}, @@ -6434,7 +6434,6 @@ var r = [9169]Rule{ {1, "crs", 1, false}, {1, "cruise", 1, false}, {1, "cruises", 1, false}, - {1, "csc", 1, false}, {1, "cuisinella", 1, false}, {1, "cymru", 1, false}, {1, "cyou", 1, false}, @@ -6482,7 +6481,6 @@ var r = [9169]Rule{ {1, "drive", 1, false}, {1, "dtv", 1, false}, {1, "dubai", 1, false}, - {1, "duck", 1, false}, {1, "dunlop", 1, false}, {1, "dupont", 1, false}, {1, "durban", 1, false}, @@ -6592,7 +6590,6 @@ var r = [9169]Rule{ {1, "gifts", 1, false}, {1, "gives", 1, false}, {1, "giving", 1, false}, - {1, "glade", 1, false}, {1, "glass", 1, false}, {1, "gle", 1, false}, {1, "global", 1, false}, @@ -6718,6 +6715,7 @@ var r = [9169]Rule{ {1, "kerryproperties", 1, false}, {1, "kfh", 1, false}, {1, "kia", 1, false}, + {1, "kids", 1, false}, {1, "kim", 1, false}, {1, "kinder", 1, false}, {1, "kindle", 1, false}, @@ -6769,7 +6767,6 @@ var r = [9169]Rule{ {1, "lipsy", 1, false}, {1, "live", 1, false}, {1, "living", 1, false}, - {1, "lixil", 1, false}, {1, "llc", 1, false}, {1, "llp", 1, false}, {1, "loan", 1, false}, @@ -6843,6 +6840,7 @@ var r = [9169]Rule{ {1, "msd", 1, false}, {1, "mtn", 1, false}, {1, "mtr", 1, false}, + {1, "music", 1, false}, {1, "mutual", 1, false}, {1, "nab", 1, false}, {1, "nagoya", 1, false}, @@ -6880,7 +6878,6 @@ var r = [9169]Rule{ {1, "nyc", 1, false}, {1, "obi", 1, false}, {1, "observer", 1, false}, - {1, "off", 1, false}, {1, "office", 1, false}, {1, "okinawa", 1, false}, {1, "olayan", 1, false}, @@ -6960,10 +6957,8 @@ var r = [9169]Rule{ {1, "qpon", 1, false}, {1, "quebec", 1, false}, {1, "quest", 1, false}, - {1, "qvc", 1, false}, {1, "racing", 1, false}, {1, "radio", 1, false}, - {1, "raid", 1, false}, {1, "read", 1, false}, {1, "realestate", 1, false}, {1, "realtor", 1, false}, @@ -6994,7 +6989,6 @@ var r = [9169]Rule{ {1, "ril", 1, false}, {1, "rio", 1, false}, {1, "rip", 1, false}, - {1, "rmit", 1, false}, {1, "rocher", 1, false}, {1, "rocks", 1, false}, {1, "rodeo", 1, false}, @@ -7033,7 +7027,6 @@ var r = [9169]Rule{ {1, "schule", 1, false}, {1, "schwarz", 1, false}, {1, "science", 1, false}, - {1, "scjohnson", 1, false}, {1, "scot", 1, false}, {1, "search", 1, false}, {1, "seat", 1, false}, @@ -7110,7 +7103,6 @@ var r = [9169]Rule{ {1, "surgery", 1, false}, {1, "suzuki", 1, false}, {1, "swatch", 1, false}, - {1, "swiftcover", 1, false}, {1, "swiss", 1, false}, {1, "sydney", 1, false}, {1, "systems", 1, false}, @@ -7250,7 +7242,6 @@ var r = [9169]Rule{ {1, "xn--30rr7y", 1, false}, {1, "xn--3bst00m", 1, false}, {1, "xn--3ds443g", 1, false}, - {1, "xn--3oq18vl8pn36a", 1, false}, {1, "xn--3pxu8k", 1, false}, {1, "xn--42c2d9a", 1, false}, {1, "xn--45q11c", 1, false}, @@ -7361,9 +7352,16 @@ var r = [9169]Rule{ {1, "graphox.us", 2, true}, {2, "devcdnaccesso.com", 3, true}, {1, "adobeaemcloud.com", 2, true}, - {1, "adobeaemcloud.net", 2, true}, {2, "dev.adobeaemcloud.com", 4, true}, + {1, "hlx.live", 2, true}, + {1, "adobeaemcloud.net", 2, true}, + {1, "hlx.page", 2, true}, + {1, "hlx3.page", 2, true}, {1, "beep.pl", 2, true}, + {1, "airkitapps.com", 2, true}, + {1, "airkitapps-au.com", 2, true}, + {1, "airkitapps.eu", 2, true}, + {1, "aivencloud.com", 2, true}, {1, "barsy.ca", 2, true}, {2, "compute.estate", 3, true}, {2, "alces.network", 3, true}, @@ -7452,12 +7450,13 @@ var r = [9169]Rule{ {1, "s3-website.eu-west-2.amazonaws.com", 4, true}, {1, "s3-website.eu-west-3.amazonaws.com", 4, true}, {1, "s3-website.us-east-2.amazonaws.com", 4, true}, - {1, "amsw.nl", 2, true}, {1, "t3l3p0rt.net", 2, true}, {1, "tele.amune.org", 3, true}, {1, "apigee.io", 2, true}, + {1, "siiites.com", 2, true}, {1, "appspacehosted.com", 2, true}, {1, "appspaceusercontent.com", 2, true}, + {1, "appudo.net", 2, true}, {1, "on-aptible.com", 2, true}, {1, "user.aseinet.ne.jp", 4, true}, {1, "gv.vc", 2, true}, @@ -7468,19 +7467,37 @@ var r = [9169]Rule{ {1, "potager.org", 2, true}, {1, "sweetpepper.org", 2, true}, {1, "myasustor.com", 2, true}, + {1, "cdn.prod.atlassian-dev.net", 4, true}, + {1, "translated.page", 2, true}, {1, "myfritz.net", 2, true}, + {1, "onavstack.net", 2, true}, {2, "awdev.ca", 3, true}, {2, "advisor.ws", 3, true}, + {1, "ecommerce-shop.pl", 2, true}, {1, "b-data.io", 2, true}, {1, "backplaneapp.io", 2, true}, {1, "balena-devices.com", 2, true}, + {1, "rs.ba", 2, true}, {2, "banzai.cloud", 3, true}, {1, "app.banzaicloud.io", 3, true}, {2, "backyards.banzaicloud.io", 4, true}, + {1, "base.ec", 2, true}, + {1, "official.ec", 2, true}, + {1, "buyshop.jp", 2, true}, + {1, "fashionstore.jp", 2, true}, + {1, "handcrafted.jp", 2, true}, + {1, "kawaiishop.jp", 2, true}, + {1, "supersale.jp", 2, true}, + {1, "theshop.jp", 2, true}, + {1, "shopselect.net", 2, true}, + {1, "base.shop", 2, true}, + {2, "beget.app", 3, true}, {1, "betainabox.com", 2, true}, {1, "bnr.la", 2, true}, + {1, "bitbucket.io", 2, true}, {1, "blackbaudcdn.net", 2, true}, {1, "of.je", 2, true}, + {1, "bluebite.io", 2, true}, {1, "boomla.net", 2, true}, {1, "boutir.com", 2, true}, {1, "boxfuse.io", 2, true}, @@ -7490,15 +7507,18 @@ var r = [9169]Rule{ {1, "square7.de", 2, true}, {1, "bplaced.net", 2, true}, {1, "square7.net", 2, true}, + {1, "shop.brendly.rs", 3, true}, {1, "browsersafetymark.io", 2, true}, {1, "uk0.bigv.io", 3, true}, {1, "dh.bytemark.co.uk", 4, true}, {1, "vm.bytemark.co.uk", 4, true}, {1, "cafjs.com", 2, true}, {1, "mycd.eu", 2, true}, + {1, "drr.ac", 2, true}, + {1, "uwu.ai", 2, true}, {1, "carrd.co", 2, true}, {1, "crd.co", 2, true}, - {1, "uwu.ai", 2, true}, + {1, "ju.mp", 2, true}, {1, "ae.org", 2, true}, {1, "br.com", 2, true}, {1, "cn.com", 2, true}, @@ -7520,7 +7540,6 @@ var r = [9169]Rule{ {1, "za.bz", 2, true}, {1, "za.com", 2, true}, {1, "ar.com", 2, true}, - {1, "gb.com", 2, true}, {1, "hu.com", 2, true}, {1, "kr.com", 2, true}, {1, "no.com", 2, true}, @@ -7541,13 +7560,13 @@ var r = [9169]Rule{ {1, "cx.ua", 2, true}, {1, "discourse.group", 2, true}, {1, "discourse.team", 2, true}, - {1, "virtueeldomein.nl", 2, true}, {1, "cleverapps.io", 2, true}, + {1, "clerk.app", 2, true}, + {1, "clerkstage.app", 2, true}, {2, "lcl.dev", 3, true}, {2, "lclstage.dev", 3, true}, {2, "stg.dev", 3, true}, {2, "stgstage.dev", 3, true}, - {1, "clic2000.net", 2, true}, {1, "clickrising.net", 2, true}, {1, "c66.me", 2, true}, {1, "cloud66.ws", 2, true}, @@ -7559,7 +7578,7 @@ var r = [9169]Rule{ {1, "cloudaccess.net", 2, true}, {1, "cloudcontrolled.com", 2, true}, {1, "cloudcontrolapp.com", 2, true}, - {1, "cloudera.site", 2, true}, + {2, "cloudera.site", 3, true}, {1, "pages.dev", 2, true}, {1, "trycloudflare.com", 2, true}, {1, "workers.dev", 2, true}, @@ -7584,6 +7603,7 @@ var r = [9169]Rule{ {1, "cloudns.pw", 2, true}, {1, "cloudns.us", 2, true}, {1, "cnpy.gdn", 2, true}, + {1, "codeberg.page", 2, true}, {1, "co.nl", 2, true}, {1, "co.no", 2, true}, {1, "webhosting.be", 2, true}, @@ -7607,8 +7627,6 @@ var r = [9169]Rule{ {2, "cryptonomic.net", 3, true}, {1, "cupcake.is", 2, true}, {1, "curv.dev", 2, true}, - {1, "multibaas.app", 2, true}, - {1, "multibaas.com", 2, true}, {2, "customer-oci.com", 3, true}, {2, "oci.customer-oci.com", 4, true}, {2, "ocp.customer-oci.com", 4, true}, @@ -7635,11 +7653,20 @@ var r = [9169]Rule{ {2, "dapps.earth", 3, true}, {2, "bzz.dapps.earth", 4, true}, {1, "builtwithdark.com", 2, true}, + {1, "demo.datadetect.com", 3, true}, + {1, "instance.datadetect.com", 3, true}, {1, "edgestack.me", 2, true}, + {1, "ddns5.com", 2, true}, {1, "debian.net", 2, true}, {1, "deno.dev", 2, true}, {1, "deno-staging.dev", 2, true}, {1, "dedyn.io", 2, true}, + {1, "deta.app", 2, true}, + {1, "deta.dev", 2, true}, + {2, "rss.my.id", 4, true}, + {2, "diher.solutions", 3, true}, + {1, "discordsays.com", 2, true}, + {1, "discordsez.com", 2, true}, {1, "jozi.biz", 2, true}, {1, "dnshome.de", 2, true}, {1, "online.th", 2, true}, @@ -7946,6 +7973,7 @@ var r = [9169]Rule{ {1, "definima.net", 2, true}, {1, "definima.io", 2, true}, {1, "ondigitalocean.app", 2, true}, + {2, "digitaloceanspaces.com", 3, true}, {1, "bci.dnstrace.pro", 3, true}, {1, "ddnsfree.com", 2, true}, {1, "ddnsgeek.com", 2, true}, @@ -7966,13 +7994,18 @@ var r = [9169]Rule{ {1, "blogsite.xyz", 2, true}, {1, "dynv6.net", 2, true}, {1, "e4.cz", 2, true}, + {1, "eero.online", 2, true}, + {1, "eero-stage.online", 2, true}, + {1, "elementor.cloud", 2, true}, + {1, "elementor.cool", 2, true}, {1, "en-root.fr", 2, true}, {1, "mytuleap.com", 2, true}, + {1, "tuleap-partners.com", 2, true}, + {1, "encr.app", 2, true}, + {1, "encoreapi.com", 2, true}, {1, "onred.one", 2, true}, {1, "staging.onred.one", 3, true}, - {1, "service.one", 2, true}, - {1, "enonic.io", 2, true}, - {1, "customer.enonic.io", 3, true}, + {1, "eu.encoway.cloud", 3, true}, {1, "eu.org", 2, true}, {1, "al.eu.org", 3, true}, {1, "asso.eu.org", 3, true}, @@ -8140,8 +8173,6 @@ var r = [9169]Rule{ {1, "cloud.fedoraproject.org", 3, true}, {1, "app.os.fedoraproject.org", 4, true}, {1, "app.os.stg.fedoraproject.org", 5, true}, - {1, "couk.me", 2, true}, - {1, "ukco.me", 2, true}, {1, "conn.uk", 2, true}, {1, "copro.uk", 2, true}, {1, "hosp.uk", 2, true}, @@ -8157,14 +8188,17 @@ var r = [9169]Rule{ {1, "firebaseapp.com", 2, true}, {1, "fireweb.app", 2, true}, {1, "flap.id", 2, true}, + {1, "onflashdrive.app", 2, true}, + {1, "fldrv.com", 2, true}, {1, "fly.dev", 2, true}, {1, "edgeapp.net", 2, true}, {1, "shw.io", 2, true}, {1, "flynnhosting.net", 2, true}, {1, "forgeblocks.com", 2, true}, - {2, "id.forgerock.io", 4, true}, + {1, "id.forgerock.io", 3, true}, {1, "framer.app", 2, true}, {1, "framercanvas.com", 2, true}, + {2, "frusky.de", 3, true}, {1, "ravpage.co.il", 3, true}, {1, "0e.vc", 2, true}, {1, "freebox-os.com", 2, true}, @@ -8184,7 +8218,16 @@ var r = [9169]Rule{ {2, "ex.ortsinfo.at", 4, true}, {2, "kunden.ortsinfo.at", 4, true}, {2, "statics.cloud", 3, true}, + {1, "independent-commission.uk", 2, true}, + {1, "independent-inquest.uk", 2, true}, + {1, "independent-inquiry.uk", 2, true}, + {1, "independent-panel.uk", 2, true}, + {1, "independent-review.uk", 2, true}, + {1, "public-inquiry.uk", 2, true}, + {1, "royal-commission.uk", 2, true}, + {1, "campaign.gov.uk", 3, true}, {1, "service.gov.uk", 3, true}, + {1, "api.gov.uk", 3, true}, {1, "gehirn.ne.jp", 3, true}, {1, "usercontent.jp", 2, true}, {1, "gentapps.com", 2, true}, @@ -8194,16 +8237,121 @@ var r = [9169]Rule{ {1, "ghost.io", 2, true}, {1, "gsj.bz", 2, true}, {1, "githubusercontent.com", 2, true}, - {1, "github.dev", 2, true}, {1, "githubpreview.dev", 2, true}, {1, "github.io", 2, true}, {1, "gitlab.io", 2, true}, {1, "gitapp.si", 2, true}, {1, "gitpage.si", 2, true}, {1, "glitch.me", 2, true}, + {1, "nog.community", 2, true}, {1, "co.ro", 2, true}, {1, "shop.ro", 2, true}, {1, "lolipop.io", 2, true}, + {1, "angry.jp", 2, true}, + {1, "babyblue.jp", 2, true}, + {1, "babymilk.jp", 2, true}, + {1, "backdrop.jp", 2, true}, + {1, "bambina.jp", 2, true}, + {1, "bitter.jp", 2, true}, + {1, "blush.jp", 2, true}, + {1, "boo.jp", 2, true}, + {1, "boy.jp", 2, true}, + {1, "boyfriend.jp", 2, true}, + {1, "but.jp", 2, true}, + {1, "candypop.jp", 2, true}, + {1, "capoo.jp", 2, true}, + {1, "catfood.jp", 2, true}, + {1, "cheap.jp", 2, true}, + {1, "chicappa.jp", 2, true}, + {1, "chillout.jp", 2, true}, + {1, "chips.jp", 2, true}, + {1, "chowder.jp", 2, true}, + {1, "chu.jp", 2, true}, + {1, "ciao.jp", 2, true}, + {1, "cocotte.jp", 2, true}, + {1, "coolblog.jp", 2, true}, + {1, "cranky.jp", 2, true}, + {1, "cutegirl.jp", 2, true}, + {1, "daa.jp", 2, true}, + {1, "deca.jp", 2, true}, + {1, "deci.jp", 2, true}, + {1, "digick.jp", 2, true}, + {1, "egoism.jp", 2, true}, + {1, "fakefur.jp", 2, true}, + {1, "fem.jp", 2, true}, + {1, "flier.jp", 2, true}, + {1, "floppy.jp", 2, true}, + {1, "fool.jp", 2, true}, + {1, "frenchkiss.jp", 2, true}, + {1, "girlfriend.jp", 2, true}, + {1, "girly.jp", 2, true}, + {1, "gloomy.jp", 2, true}, + {1, "gonna.jp", 2, true}, + {1, "greater.jp", 2, true}, + {1, "hacca.jp", 2, true}, + {1, "heavy.jp", 2, true}, + {1, "her.jp", 2, true}, + {1, "hiho.jp", 2, true}, + {1, "hippy.jp", 2, true}, + {1, "holy.jp", 2, true}, + {1, "hungry.jp", 2, true}, + {1, "icurus.jp", 2, true}, + {1, "itigo.jp", 2, true}, + {1, "jellybean.jp", 2, true}, + {1, "kikirara.jp", 2, true}, + {1, "kill.jp", 2, true}, + {1, "kilo.jp", 2, true}, + {1, "kuron.jp", 2, true}, + {1, "littlestar.jp", 2, true}, + {1, "lolitapunk.jp", 2, true}, + {1, "lomo.jp", 2, true}, + {1, "lovepop.jp", 2, true}, + {1, "lovesick.jp", 2, true}, + {1, "main.jp", 2, true}, + {1, "mods.jp", 2, true}, + {1, "mond.jp", 2, true}, + {1, "mongolian.jp", 2, true}, + {1, "moo.jp", 2, true}, + {1, "namaste.jp", 2, true}, + {1, "nikita.jp", 2, true}, + {1, "nobushi.jp", 2, true}, + {1, "noor.jp", 2, true}, + {1, "oops.jp", 2, true}, + {1, "parallel.jp", 2, true}, + {1, "parasite.jp", 2, true}, + {1, "pecori.jp", 2, true}, + {1, "peewee.jp", 2, true}, + {1, "penne.jp", 2, true}, + {1, "pepper.jp", 2, true}, + {1, "perma.jp", 2, true}, + {1, "pigboat.jp", 2, true}, + {1, "pinoko.jp", 2, true}, + {1, "punyu.jp", 2, true}, + {1, "pupu.jp", 2, true}, + {1, "pussycat.jp", 2, true}, + {1, "pya.jp", 2, true}, + {1, "raindrop.jp", 2, true}, + {1, "readymade.jp", 2, true}, + {1, "sadist.jp", 2, true}, + {1, "schoolbus.jp", 2, true}, + {1, "secret.jp", 2, true}, + {1, "staba.jp", 2, true}, + {1, "stripper.jp", 2, true}, + {1, "sub.jp", 2, true}, + {1, "sunnyday.jp", 2, true}, + {1, "thick.jp", 2, true}, + {1, "tonkotsu.jp", 2, true}, + {1, "under.jp", 2, true}, + {1, "upper.jp", 2, true}, + {1, "velvet.jp", 2, true}, + {1, "verse.jp", 2, true}, + {1, "versus.jp", 2, true}, + {1, "vivian.jp", 2, true}, + {1, "watson.jp", 2, true}, + {1, "weblike.jp", 2, true}, + {1, "whitesnow.jp", 2, true}, + {1, "zombie.jp", 2, true}, + {1, "heteml.net", 2, true}, {1, "cloudapps.digital", 2, true}, {1, "london.cloudapps.digital", 3, true}, {1, "pymnt.uk", 2, true}, @@ -8226,6 +8374,7 @@ var r = [9169]Rule{ {2, "gateway.dev", 3, true}, {1, "cloud.goog", 2, true}, {1, "translate.goog", 2, true}, + {2, "usercontent.goog", 3, true}, {1, "cloudfunctions.net", 2, true}, {1, "blogspot.ae", 2, true}, {1, "blogspot.al", 2, true}, @@ -8315,15 +8464,19 @@ var r = [9169]Rule{ {1, "hashbang.sh", 2, true}, {1, "hasura.app", 2, true}, {1, "hasura-app.io", 2, true}, + {1, "pages.it.hs-heilbronn.de", 4, true}, {1, "hepforge.org", 2, true}, {1, "herokuapp.com", 2, true}, {1, "herokussl.com", 2, true}, + {1, "ravendb.cloud", 2, true}, {1, "myravendb.com", 2, true}, {1, "ravendb.community", 2, true}, {1, "ravendb.me", 2, true}, {1, "development.run", 2, true}, {1, "ravendb.run", 2, true}, + {1, "homesklep.pl", 2, true}, {1, "secaas.hk", 2, true}, + {1, "hoplix.shop", 2, true}, {1, "orx.biz", 2, true}, {1, "biz.gl", 2, true}, {1, "col.ng", 2, true}, @@ -8483,15 +8636,19 @@ var r = [9169]Rule{ {2, "landing.myjino.ru", 4, true}, {2, "spectrum.myjino.ru", 4, true}, {2, "vps.myjino.ru", 4, true}, + {1, "jotelulu.cloud", 2, true}, {2, "triton.zone", 3, true}, {2, "cns.joyent.com", 4, true}, {1, "js.org", 2, true}, {1, "kaas.gg", 2, true}, {1, "khplay.nl", 2, true}, + {1, "ktistory.com", 2, true}, + {1, "kapsi.fi", 2, true}, {1, "keymachine.de", 2, true}, {1, "kinghost.net", 2, true}, {1, "uni5.net", 2, true}, {1, "knightpoint.systems", 2, true}, + {1, "koobin.events", 2, true}, {1, "oya.to", 2, true}, {1, "kuleuven.cloud", 2, true}, {1, "ezproxy.kuleuven.be", 3, true}, @@ -8519,13 +8676,16 @@ var r = [9169]Rule{ {1, "members.linode.com", 3, true}, {2, "nodebalancer.linode.com", 4, true}, {2, "linodeobjects.com", 3, true}, + {1, "ip.linodeusercontent.com", 3, true}, {1, "we.bs", 2, true}, + {2, "user.localcert.dev", 4, true}, {1, "localzone.xyz", 2, true}, {1, "loginline.app", 2, true}, {1, "loginline.dev", 2, true}, {1, "loginline.io", 2, true}, {1, "loginline.services", 2, true}, {1, "loginline.site", 2, true}, + {1, "servers.run", 2, true}, {1, "lohmus.me", 2, true}, {1, "krasnik.pl", 2, true}, {1, "leczna.pl", 2, true}, @@ -8555,6 +8715,7 @@ var r = [9169]Rule{ {1, "barsy.org", 2, true}, {1, "barsy.pro", 2, true}, {1, "barsy.pub", 2, true}, + {1, "barsy.ro", 2, true}, {1, "barsy.shop", 2, true}, {1, "barsy.site", 2, true}, {1, "barsy.support", 2, true}, @@ -8570,6 +8731,8 @@ var r = [9169]Rule{ {1, "mcdir.ru", 2, true}, {1, "mcpre.ru", 2, true}, {1, "vps.mcdir.ru", 3, true}, + {1, "mediatech.by", 2, true}, + {1, "mediatech.dev", 2, true}, {1, "hra.health", 2, true}, {1, "miniserver.com", 2, true}, {1, "memset.net", 2, true}, @@ -8628,7 +8791,7 @@ var r = [9169]Rule{ {1, "that.win", 2, true}, {1, "from.work", 2, true}, {1, "to.work", 2, true}, - {1, "nctu.me", 2, true}, + {1, "cloud.nospamproxy.com", 3, true}, {1, "netlify.app", 2, true}, {1, "4u.com", 2, true}, {1, "ngrok.io", 2, true}, @@ -8637,7 +8800,10 @@ var r = [9169]Rule{ {2, "developer.app", 3, true}, {1, "noop.app", 2, true}, {2, "northflank.app", 3, true}, + {2, "build.run", 3, true}, {2, "code.run", 3, true}, + {2, "database.run", 3, true}, + {2, "migration.run", 3, true}, {1, "noticeable.news", 2, true}, {1, "dnsking.ch", 2, true}, {1, "mypi.co", 2, true}, @@ -8752,71 +8918,20 @@ var r = [9169]Rule{ {1, "webhop.me", 2, true}, {1, "zapto.org", 2, true}, {1, "stage.nodeart.io", 3, true}, - {1, "nodum.co", 2, true}, - {1, "nodum.io", 2, true}, {1, "pcloud.host", 2, true}, {1, "nyc.mn", 2, true}, - {1, "nom.ae", 2, true}, - {1, "nom.af", 2, true}, - {1, "nom.ai", 2, true}, - {1, "nom.al", 2, true}, - {1, "nym.by", 2, true}, - {1, "nom.bz", 2, true}, - {1, "nym.bz", 2, true}, - {1, "nom.cl", 2, true}, - {1, "nym.ec", 2, true}, - {1, "nom.gd", 2, true}, - {1, "nom.ge", 2, true}, - {1, "nom.gl", 2, true}, - {1, "nym.gr", 2, true}, - {1, "nom.gt", 2, true}, - {1, "nym.gy", 2, true}, - {1, "nym.hk", 2, true}, - {1, "nom.hn", 2, true}, - {1, "nym.ie", 2, true}, - {1, "nom.im", 2, true}, - {1, "nom.ke", 2, true}, - {1, "nym.kz", 2, true}, - {1, "nym.la", 2, true}, - {1, "nym.lc", 2, true}, - {1, "nom.li", 2, true}, - {1, "nym.li", 2, true}, - {1, "nym.lt", 2, true}, - {1, "nym.lu", 2, true}, - {1, "nom.lv", 2, true}, - {1, "nym.me", 2, true}, - {1, "nom.mk", 2, true}, - {1, "nym.mn", 2, true}, - {1, "nym.mx", 2, true}, - {1, "nom.nu", 2, true}, - {1, "nym.nz", 2, true}, - {1, "nym.pe", 2, true}, - {1, "nym.pt", 2, true}, - {1, "nom.pw", 2, true}, - {1, "nom.qa", 2, true}, - {1, "nym.ro", 2, true}, - {1, "nom.rs", 2, true}, - {1, "nom.si", 2, true}, - {1, "nym.sk", 2, true}, - {1, "nom.st", 2, true}, - {1, "nym.su", 2, true}, - {1, "nym.sx", 2, true}, - {1, "nom.tj", 2, true}, - {1, "nym.tw", 2, true}, - {1, "nom.ug", 2, true}, - {1, "nom.uy", 2, true}, - {1, "nom.vc", 2, true}, - {1, "nom.vg", 2, true}, {1, "static.observableusercontent.com", 3, true}, {1, "cya.gg", 2, true}, {1, "omg.lol", 2, true}, {1, "cloudycluster.net", 2, true}, {1, "omniwe.site", 2, true}, + {1, "service.one", 2, true}, {1, "nid.io", 2, true}, {1, "opensocial.site", 2, true}, {1, "opencraft.hosting", 2, true}, {1, "orsites.com", 2, true}, {1, "operaunite.com", 2, true}, + {1, "tech.orange", 2, true}, {1, "authgear-staging.com", 2, true}, {1, "authgearapps.com", 2, true}, {1, "skygearapp.com", 2, true}, @@ -8847,8 +8962,6 @@ var r = [9169]Rule{ {1, "mypep.link", 2, true}, {1, "perspecta.cloud", 2, true}, {1, "lk3.ru", 2, true}, - {1, "ra-ru.ru", 2, true}, - {1, "zsew.ru", 2, true}, {1, "on-web.fr", 2, true}, {1, "bc.platform.sh", 3, true}, {1, "ent.platform.sh", 3, true}, @@ -8863,7 +8976,13 @@ var r = [9169]Rule{ {1, "plesk.page", 2, true}, {1, "pleskns.com", 2, true}, {1, "dyn53.io", 2, true}, + {1, "onporter.run", 2, true}, {1, "co.bn", 2, true}, + {1, "postman-echo.com", 2, true}, + {1, "pstmn.io", 2, true}, + {1, "mock.pstmn.io", 3, true}, + {1, "httpbin.org", 2, true}, + {1, "prequalifyme.today", 2, true}, {1, "xen.prgmr.com", 3, true}, {1, "priv.at", 2, true}, {1, "prvcy.page", 2, true}, @@ -8878,6 +8997,7 @@ var r = [9169]Rule{ {1, "qualifioapp.com", 2, true}, {1, "qbuser.com", 2, true}, {1, "cloudsite.builders", 2, true}, + {1, "instances.spawn.cc", 3, true}, {1, "instantcloud.cn", 2, true}, {1, "ras.ru", 2, true}, {1, "qa2.com", 2, true}, @@ -8907,7 +9027,10 @@ var r = [9169]Rule{ {1, "hzc.io", 2, true}, {1, "wellbeingzone.eu", 2, true}, {1, "wellbeingzone.co.uk", 3, true}, + {1, "adimo.co.uk", 3, true}, + {1, "itcouldbewor.se", 2, true}, {1, "git-pages.rit.edu", 3, true}, + {1, "rocky.page", 2, true}, {1, "xn--90amc.xn--p1acf", 2, true}, {1, "xn--j1aef.xn--p1acf", 2, true}, {1, "xn--j1ael8b.xn--p1acf", 2, true}, @@ -8936,7 +9059,9 @@ var r = [9169]Rule{ {1, "myfirewall.org", 2, true}, {1, "spdns.org", 2, true}, {1, "seidat.net", 2, true}, + {1, "sellfy.store", 2, true}, {1, "senseering.net", 2, true}, + {1, "minisite.ms", 2, true}, {1, "magnet.page", 2, true}, {1, "biz.ua", 2, true}, {1, "co.ua", 2, true}, @@ -8959,9 +9084,12 @@ var r = [9169]Rule{ {1, "alpha.bounty-full.com", 3, true}, {1, "beta.bounty-full.com", 3, true}, {1, "small-web.org", 2, true}, + {1, "vp4.me", 2, true}, {1, "try-snowplow.com", 2, true}, {1, "srht.site", 2, true}, {1, "stackhero-network.com", 2, true}, + {1, "musician.io", 2, true}, + {1, "novecore.site", 2, true}, {1, "static.land", 2, true}, {1, "dev.static.land", 3, true}, {1, "sites.static.land", 3, true}, @@ -8975,12 +9103,35 @@ var r = [9169]Rule{ {2, "stolos.io", 3, true}, {1, "spacekit.io", 2, true}, {1, "customer.speedpartner.de", 3, true}, + {1, "myspreadshop.at", 2, true}, + {1, "myspreadshop.com.au", 3, true}, + {1, "myspreadshop.be", 2, true}, + {1, "myspreadshop.ca", 2, true}, + {1, "myspreadshop.ch", 2, true}, + {1, "myspreadshop.com", 2, true}, + {1, "myspreadshop.de", 2, true}, + {1, "myspreadshop.dk", 2, true}, + {1, "myspreadshop.es", 2, true}, + {1, "myspreadshop.fi", 2, true}, + {1, "myspreadshop.fr", 2, true}, + {1, "myspreadshop.ie", 2, true}, + {1, "myspreadshop.it", 2, true}, + {1, "myspreadshop.net", 2, true}, + {1, "myspreadshop.nl", 2, true}, + {1, "myspreadshop.no", 2, true}, + {1, "myspreadshop.pl", 2, true}, + {1, "myspreadshop.se", 2, true}, + {1, "myspreadshop.co.uk", 3, true}, {1, "api.stdlib.com", 3, true}, {1, "storj.farm", 2, true}, {1, "utwente.io", 2, true}, {1, "soc.srcf.net", 3, true}, {1, "user.srcf.net", 3, true}, {1, "temp-dns.com", 2, true}, + {1, "supabase.co", 2, true}, + {1, "supabase.in", 2, true}, + {1, "supabase.net", 2, true}, + {1, "su.paba.se", 3, true}, {2, "s5y.io", 3, true}, {2, "sensiosite.cloud", 3, true}, {1, "syncloud.it", 2, true}, @@ -8999,24 +9150,34 @@ var r = [9169]Rule{ {1, "synology.me", 2, true}, {1, "vpnplus.to", 2, true}, {1, "direct.quickconnect.to", 3, true}, + {1, "tabitorder.co.il", 3, true}, {1, "taifun-dns.de", 2, true}, + {1, "beta.tailscale.net", 3, true}, + {1, "ts.net", 2, true}, {1, "gda.pl", 2, true}, {1, "gdansk.pl", 2, true}, {1, "gdynia.pl", 2, true}, {1, "med.pl", 2, true}, {1, "sopot.pl", 2, true}, - {1, "edugit.org", 2, true}, + {1, "site.tb-hosting.com", 3, true}, + {1, "edugit.io", 2, true}, + {1, "s3.teckids.org", 3, true}, {1, "telebit.app", 2, true}, {1, "telebit.io", 2, true}, {2, "telebit.xyz", 3, true}, {1, "gwiddle.co.uk", 3, true}, + {2, "firenet.ch", 3, true}, + {2, "svc.firenet.ch", 4, true}, + {1, "reservd.com", 2, true}, {1, "thingdustdata.com", 2, true}, {1, "cust.dev.thingdust.io", 4, true}, {1, "cust.disrec.thingdust.io", 4, true}, {1, "cust.prod.thingdust.io", 4, true}, {1, "cust.testing.thingdust.io", 4, true}, - {2, "firenet.ch", 3, true}, - {2, "svc.firenet.ch", 4, true}, + {1, "reservd.dev.thingdust.io", 4, true}, + {1, "reservd.disrec.thingdust.io", 4, true}, + {1, "reservd.testing.thingdust.io", 4, true}, + {1, "tickets.io", 2, true}, {1, "arvo.network", 2, true}, {1, "azimuth.network", 2, true}, {1, "tlon.network", 2, true}, @@ -9047,6 +9208,7 @@ var r = [9169]Rule{ {2, "transurl.be", 3, true}, {2, "transurl.eu", 3, true}, {2, "transurl.nl", 3, true}, + {1, "site.transip.me", 3, true}, {1, "tuxfamily.org", 2, true}, {1, "dd-dns.de", 2, true}, {1, "diskstation.eu", 2, true}, @@ -9061,6 +9223,8 @@ var r = [9169]Rule{ {1, "syno-ds.de", 2, true}, {1, "synology-diskstation.de", 2, true}, {1, "synology-ds.de", 2, true}, + {1, "typedream.app", 2, true}, + {1, "pro.typeform.com", 3, true}, {1, "uber.space", 2, true}, {2, "uberspace.de", 3, true}, {1, "hk.com", 2, true}, @@ -9069,6 +9233,7 @@ var r = [9169]Rule{ {1, "inc.hk", 2, true}, {1, "virtualuser.de", 2, true}, {1, "virtual-user.de", 2, true}, + {1, "upli.io", 2, true}, {1, "urown.cloud", 2, true}, {1, "dnsupdate.info", 2, true}, {1, "lib.de.us", 3, true}, @@ -9108,7 +9273,6 @@ var r = [9169]Rule{ {1, "de.md", 2, true}, {1, "jp.md", 2, true}, {1, "to.md", 2, true}, - {1, "uwu.nu", 2, true}, {1, "indie.porn", 2, true}, {1, "vxl.sh", 2, true}, {1, "ch.tc", 2, true}, @@ -9120,13 +9284,8 @@ var r = [9169]Rule{ {1, "dev.vu", 2, true}, {1, "me.vu", 2, true}, {1, "v.ua", 2, true}, + {2, "vultrobjects.com", 3, true}, {1, "wafflecell.com", 2, true}, - {1, "idnblogger.com", 2, true}, - {1, "indowapblog.com", 2, true}, - {1, "bloger.id", 2, true}, - {1, "wblog.id", 2, true}, - {1, "wbq.me", 2, true}, - {1, "fastblog.net", 2, true}, {2, "webhare.dev", 3, true}, {1, "reserve-online.net", 2, true}, {1, "reserve-online.com", 2, true}, @@ -9142,12 +9301,16 @@ var r = [9169]Rule{ {1, "wmcloud.org", 2, true}, {1, "panel.gg", 2, true}, {1, "daemon.panel.gg", 3, true}, + {1, "messwithdns.com", 2, true}, {1, "woltlab-demo.com", 2, true}, {1, "myforum.community", 2, true}, {1, "community-pro.de", 2, true}, {1, "diskussionsbereich.de", 2, true}, {1, "community-pro.net", 2, true}, {1, "meinforum.net", 2, true}, + {1, "affinitylottery.org.uk", 3, true}, + {1, "raffleentry.org.uk", 3, true}, + {1, "weeklylottery.org.uk", 3, true}, {1, "wpenginepowered.com", 2, true}, {1, "js.wpenginepowered.com", 3, true}, {1, "wixsite.com", 2, true}, @@ -9171,6 +9334,7 @@ var r = [9169]Rule{ {1, "ybo.review", 2, true}, {1, "ybo.science", 2, true}, {1, "ybo.trade", 2, true}, + {1, "ynh.fr", 2, true}, {1, "nohost.me", 2, true}, {1, "noho.st", 2, true}, {1, "za.net", 2, true}, diff --git a/vendor/github.com/zmap/zcrypto/cryptobyte/NOTICE.md b/vendor/github.com/zmap/zcrypto/cryptobyte/NOTICE.md new file mode 100644 index 000000000..fce84acf9 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/cryptobyte/NOTICE.md @@ -0,0 +1,2 @@ +Forked from golang.org/x/crypto/cryptobyte in order to support +permissive asn1 parsing. \ No newline at end of file diff --git a/vendor/github.com/zmap/zcrypto/cryptobyte/asn1.go b/vendor/github.com/zmap/zcrypto/cryptobyte/asn1.go new file mode 100644 index 000000000..a755e56ea --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/cryptobyte/asn1.go @@ -0,0 +1,752 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cryptobyte + +import ( + "fmt" + "math/big" + "reflect" + "time" + + "github.com/zmap/zcrypto/cryptobyte/asn1" + encoding_asn1 "github.com/zmap/zcrypto/encoding/asn1" +) + +// This file contains ASN.1-related methods for String and Builder. + +// Builder + +// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER. +func (b *Builder) AddASN1Int64(v int64) { + b.addASN1Signed(asn1.INTEGER, v) +} + +// AddASN1Int64WithTag appends a DER-encoded ASN.1 INTEGER with the +// given tag. +func (b *Builder) AddASN1Int64WithTag(v int64, tag asn1.Tag) { + b.addASN1Signed(tag, v) +} + +// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION. +func (b *Builder) AddASN1Enum(v int64) { + b.addASN1Signed(asn1.ENUM, v) +} + +func (b *Builder) addASN1Signed(tag asn1.Tag, v int64) { + b.AddASN1(tag, func(c *Builder) { + length := 1 + for i := v; i >= 0x80 || i < -0x80; i >>= 8 { + length++ + } + + for ; length > 0; length-- { + i := v >> uint((length-1)*8) & 0xff + c.AddUint8(uint8(i)) + } + }) +} + +// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER. +func (b *Builder) AddASN1Uint64(v uint64) { + b.AddASN1(asn1.INTEGER, func(c *Builder) { + length := 1 + for i := v; i >= 0x80; i >>= 8 { + length++ + } + + for ; length > 0; length-- { + i := v >> uint((length-1)*8) & 0xff + c.AddUint8(uint8(i)) + } + }) +} + +// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER. +func (b *Builder) AddASN1BigInt(n *big.Int) { + if b.err != nil { + return + } + + b.AddASN1(asn1.INTEGER, func(c *Builder) { + if n.Sign() < 0 { + // A negative number has to be converted to two's-complement form. So we + // invert and subtract 1. If the most-significant-bit isn't set then + // we'll need to pad the beginning with 0xff in order to keep the number + // negative. + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bytes := nMinus1.Bytes() + for i := range bytes { + bytes[i] ^= 0xff + } + if len(bytes) == 0 || bytes[0]&0x80 == 0 { + c.add(0xff) + } + c.add(bytes...) + } else if n.Sign() == 0 { + c.add(0) + } else { + bytes := n.Bytes() + if bytes[0]&0x80 != 0 { + c.add(0) + } + c.add(bytes...) + } + }) +} + +// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING. +func (b *Builder) AddASN1OctetString(bytes []byte) { + b.AddASN1(asn1.OCTET_STRING, func(c *Builder) { + c.AddBytes(bytes) + }) +} + +const generalizedTimeFormatStr = "20060102150405Z0700" + +// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME. +func (b *Builder) AddASN1GeneralizedTime(t time.Time) { + if t.Year() < 0 || t.Year() > 9999 { + b.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", t) + return + } + b.AddASN1(asn1.GeneralizedTime, func(c *Builder) { + c.AddBytes([]byte(t.Format(generalizedTimeFormatStr))) + }) +} + +// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not +// support BIT STRINGs that are not a whole number of bytes. +func (b *Builder) AddASN1BitString(data []byte) { + b.AddASN1(asn1.BIT_STRING, func(b *Builder) { + b.AddUint8(0) + b.AddBytes(data) + }) +} + +func (b *Builder) addBase128Int(n int64) { + var length int + if n == 0 { + length = 1 + } else { + for i := n; i > 0; i >>= 7 { + length++ + } + } + + for i := length - 1; i >= 0; i-- { + o := byte(n >> uint(i*7)) + o &= 0x7f + if i != 0 { + o |= 0x80 + } + + b.add(o) + } +} + +func isValidOID(oid encoding_asn1.ObjectIdentifier) bool { + if len(oid) < 2 { + return false + } + + if oid[0] > 2 || (oid[0] <= 1 && oid[1] >= 40) { + return false + } + + for _, v := range oid { + if v < 0 { + return false + } + } + + return true +} + +func (b *Builder) AddASN1ObjectIdentifier(oid encoding_asn1.ObjectIdentifier) { + b.AddASN1(asn1.OBJECT_IDENTIFIER, func(b *Builder) { + if !isValidOID(oid) { + b.err = fmt.Errorf("cryptobyte: invalid OID: %v", oid) + return + } + + b.addBase128Int(int64(oid[0])*40 + int64(oid[1])) + for _, v := range oid[2:] { + b.addBase128Int(int64(v)) + } + }) +} + +func (b *Builder) AddASN1Boolean(v bool) { + b.AddASN1(asn1.BOOLEAN, func(b *Builder) { + if v { + b.AddUint8(0xff) + } else { + b.AddUint8(0) + } + }) +} + +func (b *Builder) AddASN1NULL() { + b.add(uint8(asn1.NULL), 0) +} + +// MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if +// successful or records an error if one occurred. +func (b *Builder) MarshalASN1(v interface{}) { + // NOTE(martinkr): This is somewhat of a hack to allow propagation of + // encoding_asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a + // value embedded into a struct, its tag information is lost. + if b.err != nil { + return + } + bytes, err := encoding_asn1.Marshal(v) + if err != nil { + b.err = err + return + } + b.AddBytes(bytes) +} + +// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag. +// Tags greater than 30 are not supported and result in an error (i.e. +// low-tag-number form only). The child builder passed to the +// BuilderContinuation can be used to build the content of the ASN.1 object. +func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) { + if b.err != nil { + return + } + // Identifiers with the low five bits set indicate high-tag-number format + // (two or more octets), which we don't support. + if tag&0x1f == 0x1f { + b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag) + return + } + b.AddUint8(uint8(tag)) + b.addLengthPrefixed(1, true, f) +} + +// String + +// ReadASN1Boolean decodes an ASN.1 BOOLEAN and converts it to a boolean +// representation into out and advances. It reports whether the read +// was successful. +func (s *String) ReadASN1Boolean(out *bool) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.BOOLEAN) || len(bytes) != 1 { + return false + } + + switch bytes[0] { + case 0: + *out = false + case 0xff: + *out = true + default: + return false + } + + return true +} + +var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem() + +// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does +// not point to an integer or to a big.Int, it panics. It reports whether the +// read was successful. +func (s *String) ReadASN1Integer(out interface{}) bool { + if reflect.TypeOf(out).Kind() != reflect.Ptr { + panic("out is not a pointer") + } + switch reflect.ValueOf(out).Elem().Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + var i int64 + if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) { + return false + } + reflect.ValueOf(out).Elem().SetInt(i) + return true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + var u uint64 + if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) { + return false + } + reflect.ValueOf(out).Elem().SetUint(u) + return true + case reflect.Struct: + if reflect.TypeOf(out).Elem() == bigIntType { + return s.readASN1BigInt(out.(*big.Int)) + } + } + panic("out does not point to an integer type") +} + +func checkASN1Integer(bytes []byte) bool { + if len(bytes) == 0 { + // An INTEGER is encoded with at least one octet. + return false + } + if len(bytes) == 1 { + return true + } + if bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 { + // Value is not minimally encoded. + return false + } + return true +} + +var bigOne = big.NewInt(1) + +func (s *String) readASN1BigInt(out *big.Int) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) { + return false + } + if bytes[0]&0x80 == 0x80 { + // Negative number. + neg := make([]byte, len(bytes)) + for i, b := range bytes { + neg[i] = ^b + } + out.SetBytes(neg) + out.Add(out, bigOne) + out.Neg(out) + } else { + out.SetBytes(bytes) + } + return true +} + +func (s *String) readASN1Int64(out *int64) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) { + return false + } + return true +} + +func asn1Signed(out *int64, n []byte) bool { + length := len(n) + if length > 8 { + return false + } + for i := 0; i < length; i++ { + *out <<= 8 + *out |= int64(n[i]) + } + // Shift up and down in order to sign extend the result. + *out <<= 64 - uint8(length)*8 + *out >>= 64 - uint8(length)*8 + return true +} + +func (s *String) readASN1Uint64(out *uint64) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) { + return false + } + return true +} + +func asn1Unsigned(out *uint64, n []byte) bool { + length := len(n) + if length > 9 || length == 9 && n[0] != 0 { + // Too large for uint64. + return false + } + if n[0]&0x80 != 0 { + // Negative number. + return false + } + for i := 0; i < length; i++ { + *out <<= 8 + *out |= uint64(n[i]) + } + return true +} + +// ReadASN1Int64WithTag decodes an ASN.1 INTEGER with the given tag into out +// and advances. It reports whether the read was successful and resulted in a +// value that can be represented in an int64. +func (s *String) ReadASN1Int64WithTag(out *int64, tag asn1.Tag) bool { + var bytes String + return s.ReadASN1(&bytes, tag) && checkASN1Integer(bytes) && asn1Signed(out, bytes) +} + +// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It reports +// whether the read was successful. +func (s *String) ReadASN1Enum(out *int) bool { + var bytes String + var i int64 + if !s.ReadASN1(&bytes, asn1.ENUM) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) { + return false + } + if int64(int(i)) != i { + return false + } + *out = int(i) + return true +} + +func (s *String) readBase128Int(out *int) bool { + ret := 0 + for i := 0; len(*s) > 0; i++ { + if i == 4 { + return false + } + ret <<= 7 + b := s.read(1)[0] + ret |= int(b & 0x7f) + if b&0x80 == 0 { + *out = ret + return true + } + } + return false // truncated +} + +// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and +// advances. It reports whether the read was successful. +func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 { + return false + } + + // In the worst case, we get two elements from the first byte (which is + // encoded differently) and then every varint is a single byte long. + components := make([]int, len(bytes)+1) + + // The first varint is 40*value1 + value2: + // According to this packing, value1 can take the values 0, 1 and 2 only. + // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, + // then there are no restrictions on value2. + var v int + if !bytes.readBase128Int(&v) { + return false + } + if v < 80 { + components[0] = v / 40 + components[1] = v % 40 + } else { + components[0] = 2 + components[1] = v - 80 + } + + i := 2 + for ; len(bytes) > 0; i++ { + if !bytes.readBase128Int(&v) { + return false + } + components[i] = v + } + *out = components[:i] + return true +} + +// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and +// advances. It reports whether the read was successful. +func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.GeneralizedTime) { + return false + } + t := string(bytes) + res, err := time.Parse(generalizedTimeFormatStr, t) + if err != nil { + return false + } + if serialized := res.Format(generalizedTimeFormatStr); serialized != t { + return false + } + *out = res + return true +} + +// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. +// It reports whether the read was successful. +func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 || + len(bytes)*8/8 != len(bytes) { + return false + } + + paddingBits := uint8(bytes[0]) + bytes = bytes[1:] + if paddingBits > 7 || + len(bytes) == 0 && paddingBits != 0 || + len(bytes) > 0 && bytes[len(bytes)-1]&(1< 4 || len(*s) < int(2+lenLen) { + return false + } + + lenBytes := String((*s)[2 : 2+lenLen]) + if !lenBytes.readUnsigned(&len32, int(lenLen)) { + return false + } + + // ITU-T X.690 section 10.1 (DER length forms) requires encoding the length + // with the minimum number of octets. + if len32 < 128 { + // Length should have used short-form encoding. + return false + } + if len32>>((lenLen-1)*8) == 0 { + // Leading octet is 0. Length should have been at least one byte shorter. + return false + } + + headerLen = 2 + uint32(lenLen) + if headerLen+len32 < len32 { + // Overflow. + return false + } + length = headerLen + len32 + } + + if int(length) < 0 || !s.ReadBytes((*[]byte)(out), int(length)) { + return false + } + if skipHeader && !out.Skip(int(headerLen)) { + panic("cryptobyte: internal error") + } + + return true +} diff --git a/vendor/github.com/zmap/zcrypto/cryptobyte/asn1/asn1.go b/vendor/github.com/zmap/zcrypto/cryptobyte/asn1/asn1.go new file mode 100644 index 000000000..90ef6a241 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/cryptobyte/asn1/asn1.go @@ -0,0 +1,46 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package asn1 contains supporting types for parsing and building ASN.1 +// messages with the cryptobyte package. +package asn1 + +// Tag represents an ASN.1 identifier octet, consisting of a tag number +// (indicating a type) and class (such as context-specific or constructed). +// +// Methods in the cryptobyte package only support the low-tag-number form, i.e. +// a single identifier octet with bits 7-8 encoding the class and bits 1-6 +// encoding the tag number. +type Tag uint8 + +const ( + classConstructed = 0x20 + classContextSpecific = 0x80 +) + +// Constructed returns t with the constructed class bit set. +func (t Tag) Constructed() Tag { return t | classConstructed } + +// ContextSpecific returns t with the context-specific class bit set. +func (t Tag) ContextSpecific() Tag { return t | classContextSpecific } + +// The following is a list of standard tag and class combinations. +const ( + BOOLEAN = Tag(1) + INTEGER = Tag(2) + BIT_STRING = Tag(3) + OCTET_STRING = Tag(4) + NULL = Tag(5) + OBJECT_IDENTIFIER = Tag(6) + ENUM = Tag(10) + UTF8String = Tag(12) + SEQUENCE = Tag(16 | classConstructed) + SET = Tag(17 | classConstructed) + PrintableString = Tag(19) + T61String = Tag(20) + IA5String = Tag(22) + UTCTime = Tag(23) + GeneralizedTime = Tag(24) + GeneralString = Tag(27) +) diff --git a/vendor/github.com/zmap/zcrypto/cryptobyte/builder.go b/vendor/github.com/zmap/zcrypto/cryptobyte/builder.go new file mode 100644 index 000000000..ca7b1db5c --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/cryptobyte/builder.go @@ -0,0 +1,337 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cryptobyte + +import ( + "errors" + "fmt" +) + +// A Builder builds byte strings from fixed-length and length-prefixed values. +// Builders either allocate space as needed, or are ‘fixed’, which means that +// they write into a given buffer and produce an error if it's exhausted. +// +// The zero value is a usable Builder that allocates space as needed. +// +// Simple values are marshaled and appended to a Builder using methods on the +// Builder. Length-prefixed values are marshaled by providing a +// BuilderContinuation, which is a function that writes the inner contents of +// the value to a given Builder. See the documentation for BuilderContinuation +// for details. +type Builder struct { + err error + result []byte + fixedSize bool + child *Builder + offset int + pendingLenLen int + pendingIsASN1 bool + inContinuation *bool +} + +// NewBuilder creates a Builder that appends its output to the given buffer. +// Like append(), the slice will be reallocated if its capacity is exceeded. +// Use Bytes to get the final buffer. +func NewBuilder(buffer []byte) *Builder { + return &Builder{ + result: buffer, + } +} + +// NewFixedBuilder creates a Builder that appends its output into the given +// buffer. This builder does not reallocate the output buffer. Writes that +// would exceed the buffer's capacity are treated as an error. +func NewFixedBuilder(buffer []byte) *Builder { + return &Builder{ + result: buffer, + fixedSize: true, + } +} + +// SetError sets the value to be returned as the error from Bytes. Writes +// performed after calling SetError are ignored. +func (b *Builder) SetError(err error) { + b.err = err +} + +// Bytes returns the bytes written by the builder or an error if one has +// occurred during building. +func (b *Builder) Bytes() ([]byte, error) { + if b.err != nil { + return nil, b.err + } + return b.result[b.offset:], nil +} + +// BytesOrPanic returns the bytes written by the builder or panics if an error +// has occurred during building. +func (b *Builder) BytesOrPanic() []byte { + if b.err != nil { + panic(b.err) + } + return b.result[b.offset:] +} + +// AddUint8 appends an 8-bit value to the byte string. +func (b *Builder) AddUint8(v uint8) { + b.add(byte(v)) +} + +// AddUint16 appends a big-endian, 16-bit value to the byte string. +func (b *Builder) AddUint16(v uint16) { + b.add(byte(v>>8), byte(v)) +} + +// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest +// byte of the 32-bit input value is silently truncated. +func (b *Builder) AddUint24(v uint32) { + b.add(byte(v>>16), byte(v>>8), byte(v)) +} + +// AddUint32 appends a big-endian, 32-bit value to the byte string. +func (b *Builder) AddUint32(v uint32) { + b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) +} + +// AddBytes appends a sequence of bytes to the byte string. +func (b *Builder) AddBytes(v []byte) { + b.add(v...) +} + +// BuilderContinuation is a continuation-passing interface for building +// length-prefixed byte sequences. Builder methods for length-prefixed +// sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation +// supplied to them. The child builder passed to the continuation can be used +// to build the content of the length-prefixed sequence. For example: +// +// parent := cryptobyte.NewBuilder() +// parent.AddUint8LengthPrefixed(func (child *Builder) { +// child.AddUint8(42) +// child.AddUint8LengthPrefixed(func (grandchild *Builder) { +// grandchild.AddUint8(5) +// }) +// }) +// +// It is an error to write more bytes to the child than allowed by the reserved +// length prefix. After the continuation returns, the child must be considered +// invalid, i.e. users must not store any copies or references of the child +// that outlive the continuation. +// +// If the continuation panics with a value of type BuildError then the inner +// error will be returned as the error from Bytes. If the child panics +// otherwise then Bytes will repanic with the same value. +type BuilderContinuation func(child *Builder) + +// BuildError wraps an error. If a BuilderContinuation panics with this value, +// the panic will be recovered and the inner error will be returned from +// Builder.Bytes. +type BuildError struct { + Err error +} + +// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence. +func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(1, false, f) +} + +// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence. +func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(2, false, f) +} + +// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence. +func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(3, false, f) +} + +// AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence. +func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(4, false, f) +} + +func (b *Builder) callContinuation(f BuilderContinuation, arg *Builder) { + if !*b.inContinuation { + *b.inContinuation = true + + defer func() { + *b.inContinuation = false + + r := recover() + if r == nil { + return + } + + if buildError, ok := r.(BuildError); ok { + b.err = buildError.Err + } else { + panic(r) + } + }() + } + + f(arg) +} + +func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) { + // Subsequent writes can be ignored if the builder has encountered an error. + if b.err != nil { + return + } + + offset := len(b.result) + b.add(make([]byte, lenLen)...) + + if b.inContinuation == nil { + b.inContinuation = new(bool) + } + + b.child = &Builder{ + result: b.result, + fixedSize: b.fixedSize, + offset: offset, + pendingLenLen: lenLen, + pendingIsASN1: isASN1, + inContinuation: b.inContinuation, + } + + b.callContinuation(f, b.child) + b.flushChild() + if b.child != nil { + panic("cryptobyte: internal error") + } +} + +func (b *Builder) flushChild() { + if b.child == nil { + return + } + b.child.flushChild() + child := b.child + b.child = nil + + if child.err != nil { + b.err = child.err + return + } + + length := len(child.result) - child.pendingLenLen - child.offset + + if length < 0 { + panic("cryptobyte: internal error") // result unexpectedly shrunk + } + + if child.pendingIsASN1 { + // For ASN.1, we reserved a single byte for the length. If that turned out + // to be incorrect, we have to move the contents along in order to make + // space. + if child.pendingLenLen != 1 { + panic("cryptobyte: internal error") + } + var lenLen, lenByte uint8 + if int64(length) > 0xfffffffe { + b.err = errors.New("pending ASN.1 child too long") + return + } else if length > 0xffffff { + lenLen = 5 + lenByte = 0x80 | 4 + } else if length > 0xffff { + lenLen = 4 + lenByte = 0x80 | 3 + } else if length > 0xff { + lenLen = 3 + lenByte = 0x80 | 2 + } else if length > 0x7f { + lenLen = 2 + lenByte = 0x80 | 1 + } else { + lenLen = 1 + lenByte = uint8(length) + length = 0 + } + + // Insert the initial length byte, make space for successive length bytes, + // and adjust the offset. + child.result[child.offset] = lenByte + extraBytes := int(lenLen - 1) + if extraBytes != 0 { + child.add(make([]byte, extraBytes)...) + childStart := child.offset + child.pendingLenLen + copy(child.result[childStart+extraBytes:], child.result[childStart:]) + } + child.offset++ + child.pendingLenLen = extraBytes + } + + l := length + for i := child.pendingLenLen - 1; i >= 0; i-- { + child.result[child.offset+i] = uint8(l) + l >>= 8 + } + if l != 0 { + b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen) + return + } + + if b.fixedSize && &b.result[0] != &child.result[0] { + panic("cryptobyte: BuilderContinuation reallocated a fixed-size buffer") + } + + b.result = child.result +} + +func (b *Builder) add(bytes ...byte) { + if b.err != nil { + return + } + if b.child != nil { + panic("cryptobyte: attempted write while child is pending") + } + if len(b.result)+len(bytes) < len(bytes) { + b.err = errors.New("cryptobyte: length overflow") + } + if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) { + b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer") + return + } + b.result = append(b.result, bytes...) +} + +// Unwrite rolls back n bytes written directly to the Builder. An attempt by a +// child builder passed to a continuation to unwrite bytes from its parent will +// panic. +func (b *Builder) Unwrite(n int) { + if b.err != nil { + return + } + if b.child != nil { + panic("cryptobyte: attempted unwrite while child is pending") + } + length := len(b.result) - b.pendingLenLen - b.offset + if length < 0 { + panic("cryptobyte: internal error") + } + if n > length { + panic("cryptobyte: attempted to unwrite more than was written") + } + b.result = b.result[:len(b.result)-n] +} + +// A MarshalingValue marshals itself into a Builder. +type MarshalingValue interface { + // Marshal is called by Builder.AddValue. It receives a pointer to a builder + // to marshal itself into. It may return an error that occurred during + // marshaling, such as unset or invalid values. + Marshal(b *Builder) error +} + +// AddValue calls Marshal on v, passing a pointer to the builder to append to. +// If Marshal returns an error, it is set on the Builder so that subsequent +// appends don't have an effect. +func (b *Builder) AddValue(v MarshalingValue) { + err := v.Marshal(b) + if err != nil { + b.err = err + } +} diff --git a/vendor/github.com/zmap/zcrypto/cryptobyte/string.go b/vendor/github.com/zmap/zcrypto/cryptobyte/string.go new file mode 100644 index 000000000..a3ecf6382 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/cryptobyte/string.go @@ -0,0 +1,161 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cryptobyte contains types that help with parsing and constructing +// length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage +// contains useful ASN.1 constants.) +// +// The String type is for parsing. It wraps a []byte slice and provides helper +// functions for consuming structures, value by value. +// +// The Builder type is for constructing messages. It providers helper functions +// for appending values and also for appending length-prefixed submessages – +// without having to worry about calculating the length prefix ahead of time. +// +// See the documentation and examples for the Builder and String types to get +// started. +package cryptobyte + +// String represents a string of bytes. It provides methods for parsing +// fixed-length and length-prefixed values from it. +type String []byte + +// read advances a String by n bytes and returns them. If less than n bytes +// remain, it returns nil. +func (s *String) read(n int) []byte { + if len(*s) < n || n < 0 { + return nil + } + v := (*s)[:n] + *s = (*s)[n:] + return v +} + +// Skip advances the String by n byte and reports whether it was successful. +func (s *String) Skip(n int) bool { + return s.read(n) != nil +} + +// ReadUint8 decodes an 8-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint8(out *uint8) bool { + v := s.read(1) + if v == nil { + return false + } + *out = uint8(v[0]) + return true +} + +// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint16(out *uint16) bool { + v := s.read(2) + if v == nil { + return false + } + *out = uint16(v[0])<<8 | uint16(v[1]) + return true +} + +// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint24(out *uint32) bool { + v := s.read(3) + if v == nil { + return false + } + *out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2]) + return true +} + +// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint32(out *uint32) bool { + v := s.read(4) + if v == nil { + return false + } + *out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3]) + return true +} + +func (s *String) readUnsigned(out *uint32, length int) bool { + v := s.read(length) + if v == nil { + return false + } + var result uint32 + for i := 0; i < length; i++ { + result <<= 8 + result |= uint32(v[i]) + } + *out = result + return true +} + +func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool { + lenBytes := s.read(lenLen) + if lenBytes == nil { + return false + } + var length uint32 + for _, b := range lenBytes { + length = length << 8 + length = length | uint32(b) + } + v := s.read(int(length)) + if v == nil { + return false + } + *outChild = v + return true +} + +// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value +// into out and advances over it. It reports whether the read was successful. +func (s *String) ReadUint8LengthPrefixed(out *String) bool { + return s.readLengthPrefixed(1, out) +} + +// ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit +// length-prefixed value into out and advances over it. It reports whether the +// read was successful. +func (s *String) ReadUint16LengthPrefixed(out *String) bool { + return s.readLengthPrefixed(2, out) +} + +// ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit +// length-prefixed value into out and advances over it. It reports whether +// the read was successful. +func (s *String) ReadUint24LengthPrefixed(out *String) bool { + return s.readLengthPrefixed(3, out) +} + +// ReadBytes reads n bytes into out and advances over them. It reports +// whether the read was successful. +func (s *String) ReadBytes(out *[]byte, n int) bool { + v := s.read(n) + if v == nil { + return false + } + *out = v + return true +} + +// CopyBytes copies len(out) bytes into out and advances over them. It reports +// whether the copy operation was successful +func (s *String) CopyBytes(out []byte) bool { + n := len(out) + v := s.read(n) + if v == nil { + return false + } + return copy(out, v) == n +} + +// Empty reports whether the string does not contain any bytes. +func (s String) Empty() bool { + return len(s) == 0 +} diff --git a/vendor/github.com/zmap/zcrypto/encoding/asn1/README.md b/vendor/github.com/zmap/zcrypto/encoding/asn1/README.md new file mode 100644 index 000000000..41d78f3fe --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/encoding/asn1/README.md @@ -0,0 +1 @@ +Forked from standard "encoding/asn1" to allow more permissive decoding \ No newline at end of file diff --git a/vendor/github.com/zmap/zcrypto/encoding/asn1/asn1.go b/vendor/github.com/zmap/zcrypto/encoding/asn1/asn1.go new file mode 100644 index 000000000..87b9eddb3 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/encoding/asn1/asn1.go @@ -0,0 +1,1146 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package asn1 implements parsing of DER-encoded ASN.1 data structures, +// as defined in ITU-T Rec X.690. +// +// See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,'' +// http://luca.ntop.org/Teaching/Appunti/asn1.html. +package asn1 + +// ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc +// are different encoding formats for those objects. Here, we'll be dealing +// with DER, the Distinguished Encoding Rules. DER is used in X.509 because +// it's fast to parse and, unlike BER, has a unique encoding for every object. +// When calculating hashes over objects, it's important that the resulting +// bytes be the same at both ends and DER removes this margin of error. +// +// ASN.1 is very complex and this package doesn't attempt to implement +// everything by any means. + +import ( + "errors" + "fmt" + "math" + "math/big" + "reflect" + "strconv" + "time" + "unicode/utf16" + "unicode/utf8" +) + +// AllowPermissiveParsing is a custom ZCrypto option to allow permissive parsing for X509 certificates +var AllowPermissiveParsing = false + +// A StructuralError suggests that the ASN.1 data is valid, but the Go type +// which is receiving it doesn't match. +type StructuralError struct { + Msg string +} + +func (e StructuralError) Error() string { return "asn1: structure error: " + e.Msg } + +// A SyntaxError suggests that the ASN.1 data is invalid. +type SyntaxError struct { + Msg string +} + +func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg } + +// We start by dealing with each of the primitive types in turn. + +// BOOLEAN + +func parseBool(bytes []byte) (ret bool, err error) { + if len(bytes) != 1 { + err = SyntaxError{"invalid boolean"} + return + } + + // DER demands that "If the encoding represents the boolean value TRUE, + // its single contents octet shall have all eight bits set to one." + // Thus only 0 and 255 are valid encoded values. + switch bytes[0] { + case 0: + ret = false + case 0xff: + ret = true + default: + err = SyntaxError{"invalid boolean"} + } + + return +} + +// INTEGER + +// checkInteger returns nil if the given bytes are a valid DER-encoded +// INTEGER and an error otherwise. +func checkInteger(bytes []byte) error { + if len(bytes) == 0 { + return StructuralError{"empty integer"} + } + if len(bytes) == 1 { + return nil + } + if !AllowPermissiveParsing { + if (bytes[0] == 0 && bytes[1]&0x80 == 0) || (bytes[0] == 0xff && bytes[1]&0x80 == 0x80) { + return StructuralError{"integer not minimally-encoded"} + } + } + return nil +} + +// parseInt64 treats the given bytes as a big-endian, signed integer and +// returns the result. +func parseInt64(bytes []byte) (ret int64, err error) { + err = checkInteger(bytes) + if err != nil { + return + } + if len(bytes) > 8 { + // We'll overflow an int64 in this case. + err = StructuralError{"integer too large"} + return + } + for bytesRead := 0; bytesRead < len(bytes); bytesRead++ { + ret <<= 8 + ret |= int64(bytes[bytesRead]) + } + + // Shift up and down in order to sign extend the result. + ret <<= 64 - uint8(len(bytes))*8 + ret >>= 64 - uint8(len(bytes))*8 + return +} + +// parseInt treats the given bytes as a big-endian, signed integer and returns +// the result. +func parseInt32(bytes []byte) (int32, error) { + if err := checkInteger(bytes); err != nil { + return 0, err + } + ret64, err := parseInt64(bytes) + if err != nil { + return 0, err + } + if ret64 != int64(int32(ret64)) { + return 0, StructuralError{"integer too large"} + } + return int32(ret64), nil +} + +var bigOne = big.NewInt(1) + +// parseBigInt treats the given bytes as a big-endian, signed integer and returns +// the result. +func parseBigInt(bytes []byte) (*big.Int, error) { + if err := checkInteger(bytes); err != nil { + return nil, err + } + ret := new(big.Int) + if len(bytes) > 0 && bytes[0]&0x80 == 0x80 { + // This is a negative number. + notBytes := make([]byte, len(bytes)) + for i := range notBytes { + notBytes[i] = ^bytes[i] + } + ret.SetBytes(notBytes) + ret.Add(ret, bigOne) + ret.Neg(ret) + return ret, nil + } + ret.SetBytes(bytes) + return ret, nil +} + +// BIT STRING + +// BitString is the structure to use when you want an ASN.1 BIT STRING type. A +// bit string is padded up to the nearest byte in memory and the number of +// valid bits is recorded. Padding bits will be zero. +type BitString struct { + Bytes []byte // bits packed into bytes. + BitLength int // length in bits. +} + +// At returns the bit at the given index. If the index is out of range it +// returns false. +func (b BitString) At(i int) int { + if i < 0 || i >= b.BitLength { + return 0 + } + x := i / 8 + y := 7 - uint(i%8) + return int(b.Bytes[x]>>y) & 1 +} + +// RightAlign returns a slice where the padding bits are at the beginning. The +// slice may share memory with the BitString. +func (b BitString) RightAlign() []byte { + shift := uint(8 - (b.BitLength % 8)) + if shift == 8 || len(b.Bytes) == 0 { + return b.Bytes + } + + a := make([]byte, len(b.Bytes)) + a[0] = b.Bytes[0] >> shift + for i := 1; i < len(b.Bytes); i++ { + a[i] = b.Bytes[i-1] << (8 - shift) + a[i] |= b.Bytes[i] >> shift + } + + return a +} + +// parseBitString parses an ASN.1 bit string from the given byte slice and returns it. +func parseBitString(bytes []byte) (ret BitString, err error) { + if len(bytes) == 0 { + err = SyntaxError{"zero length BIT STRING"} + return + } + paddingBits := int(bytes[0]) + if paddingBits > 7 || + len(bytes) == 1 && paddingBits > 0 || + bytes[len(bytes)-1]&((1< 0 { + s += "." + } + s += strconv.Itoa(v) + } + + return s +} + +// parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and +// returns it. An object identifier is a sequence of variable length integers +// that are assigned in a hierarchy. +func parseObjectIdentifier(bytes []byte) (s ObjectIdentifier, err error) { + if len(bytes) == 0 { + err = SyntaxError{"zero length OBJECT IDENTIFIER"} + return + } + + // In the worst case, we get two elements from the first byte (which is + // encoded differently) and then every varint is a single byte long. + s = make([]int, len(bytes)+1) + + // The first varint is 40*value1 + value2: + // According to this packing, value1 can take the values 0, 1 and 2 only. + // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, + // then there are no restrictions on value2. + v, offset, err := parseBase128Int(bytes, 0) + if err != nil { + return + } + if v < 80 { + s[0] = v / 40 + s[1] = v % 40 + } else { + s[0] = 2 + s[1] = v - 80 + } + + i := 2 + for ; offset < len(bytes); i++ { + v, offset, err = parseBase128Int(bytes, offset) + if err != nil { + return + } + s[i] = v + } + s = s[0:i] + return +} + +// ENUMERATED + +// An Enumerated is represented as a plain int. +type Enumerated int + +// FLAG + +// A Flag accepts any data and is set to true if present. +type Flag bool + +// parseBase128Int parses a base-128 encoded int from the given offset in the +// given byte slice. It returns the value and the new offset. +func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) { + offset = initOffset + var ret64 int64 + for shifted := 0; offset < len(bytes); shifted++ { + // 5 * 7 bits per byte == 35 bits of data + // Thus the representation is either non-minimal or too large for an int32 + if shifted == 5 { + err = StructuralError{"base 128 integer too large"} + return + } + ret64 <<= 7 + b := bytes[offset] + // integers should be minimally encoded, so the leading octet should + // never be 0x80 + if shifted == 0 && b == 0x80 { + err = SyntaxError{"integer is not minimally encoded"} + return + } + ret64 |= int64(b & 0x7f) + offset++ + if b&0x80 == 0 { + ret = int(ret64) + // Ensure that the returned value fits in an int on all platforms + if ret64 > math.MaxInt32 { + err = StructuralError{"base 128 integer too large"} + } + return + } + } + err = SyntaxError{"truncated base 128 integer"} + return +} + +// UTCTime + +func parseUTCTime(bytes []byte) (ret time.Time, err error) { + s := string(bytes) + + formatStr := "0601021504Z0700" + ret, err = time.Parse(formatStr, s) + if err != nil { + formatStr = "060102150405Z0700" + ret, err = time.Parse(formatStr, s) + } + if err != nil { + return + } + + // ZCrypto: Allow to parse + if !AllowPermissiveParsing { + if serialized := ret.Format(formatStr); serialized != s { + err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized) + return + } + } + + if ret.Year() >= 2050 { + // UTCTime only encodes times prior to 2050. See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 + ret = ret.AddDate(-100, 0, 0) + } + + return +} + +// parseGeneralizedTime parses the GeneralizedTime from the given byte slice +// and returns the resulting time. +func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) { + const formatStr = "20060102150405Z0700" + s := string(bytes) + + if ret, err = time.Parse(formatStr, s); err != nil { + return + } + + // ZCrypto: Allow to parse + if !AllowPermissiveParsing { + if serialized := ret.Format(formatStr); serialized != s { + err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized) + } + } + return +} + +// NumericString + +// parseNumericString parses an ASN.1 NumericString from the given byte array +// and returns it. +func parseNumericString(bytes []byte) (ret string, err error) { + if !AllowPermissiveParsing { + for _, b := range bytes { + if !isNumeric(b) { + return "", SyntaxError{"NumericString contains invalid character"} + } + } + } + return string(bytes), nil +} + +// isNumeric reports whether the given b is in the ASN.1 NumericString set. +func isNumeric(b byte) bool { + return '0' <= b && b <= '9' || + b == ' ' +} + +// PrintableString + +// parsePrintableString parses an ASN.1 PrintableString from the given byte +// array and returns it. +func parsePrintableString(bytes []byte) (ret string, err error) { + // ZCrypto: allow to parse some non-printable characters + if !AllowPermissiveParsing { + for _, b := range bytes { + if !isPrintable(b, allowAsterisk, allowAmpersand) { + err = SyntaxError{"PrintableString contains invalid character"} + return + } + } + } + ret = string(bytes) + return +} + +type asteriskFlag bool +type ampersandFlag bool + +const ( + allowAsterisk asteriskFlag = true + rejectAsterisk asteriskFlag = false + + allowAmpersand ampersandFlag = true + rejectAmpersand ampersandFlag = false +) + +// isPrintable reports whether the given b is in the ASN.1 PrintableString set. +// If asterisk is allowAsterisk then '*' is also allowed, reflecting existing +// practice. If ampersand is allowAmpersand then '&' is allowed as well. +func isPrintable(b byte, asterisk asteriskFlag, ampersand ampersandFlag) bool { + return 'a' <= b && b <= 'z' || + 'A' <= b && b <= 'Z' || + '0' <= b && b <= '9' || + '\'' <= b && b <= ')' || + '+' <= b && b <= '/' || + b == ' ' || + b == ':' || + b == '=' || + b == '?' || + // This is technically not allowed in a PrintableString. + // However, x509 certificates with wildcard strings don't + // always use the correct string type so we permit it. + (bool(asterisk) && b == '*') || + // This is not technically allowed either. However, not + // only is it relatively common, but there are also a + // handful of CA certificates that contain it. At least + // one of which will not expire until 2027. + (bool(ampersand) && b == '&') +} + +// IA5String + +// parseIA5String parses an ASN.1 IA5String (ASCII string) from the given +// byte slice and returns it. +func parseIA5String(bytes []byte) (ret string, err error) { + if !AllowPermissiveParsing { + for _, b := range bytes { + if b >= utf8.RuneSelf { + err = SyntaxError{"IA5String contains invalid character"} + return + } + } + } + ret = string(bytes) + return +} + +// T61String + +// parseT61String parses an ASN.1 T61String (8-bit clean string) from the given +// byte slice and returns it. +func parseT61String(bytes []byte) (ret string, err error) { + return string(bytes), nil +} + +// UTF8String + +// parseUTF8String parses an ASN.1 UTF8String (raw UTF-8) from the given byte +// array and returns it. +func parseUTF8String(bytes []byte) (ret string, err error) { + if !utf8.Valid(bytes) { + if !AllowPermissiveParsing { + return "", errors.New("asn1: invalid UTF-8 string") + } + } + return string(bytes), nil +} + +// BMPString + +// parseBMPString parses an ASN.1 BMPString (Basic Multilingual Plane of +// ISO/IEC/ITU 10646-1) from the given byte slice and returns it. +func parseBMPString(bmpString []byte) (string, error) { + if len(bmpString)%2 != 0 { + return "", errors.New("pkcs12: odd-length BMP string") + } + + // Strip terminator if present. + if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 { + bmpString = bmpString[:l-2] + } + + s := make([]uint16, 0, len(bmpString)/2) + for len(bmpString) > 0 { + s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1])) + bmpString = bmpString[2:] + } + + return string(utf16.Decode(s)), nil +} + +// A RawValue represents an undecoded ASN.1 object. +type RawValue struct { + Class, Tag int + IsCompound bool + Bytes []byte + FullBytes []byte // includes the tag and length +} + +// RawContent is used to signal that the undecoded, DER data needs to be +// preserved for a struct. To use it, the first field of the struct must have +// this type. It's an error for any of the other fields to have this type. +type RawContent []byte + +// Tagging + +// parseTagAndLength parses an ASN.1 tag and length pair from the given offset +// into a byte slice. It returns the parsed data and the new offset. SET and +// SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we +// don't distinguish between ordered and unordered objects in this code. +func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) { + offset = initOffset + // parseTagAndLength should not be called without at least a single + // byte to read. Thus this check is for robustness: + if offset >= len(bytes) { + err = errors.New("asn1: internal error in parseTagAndLength") + return + } + b := bytes[offset] + offset++ + ret.class = int(b >> 6) + ret.isCompound = b&0x20 == 0x20 + ret.tag = int(b & 0x1f) + + // If the bottom five bits are set, then the tag number is actually base 128 + // encoded afterwards + if ret.tag == 0x1f { + ret.tag, offset, err = parseBase128Int(bytes, offset) + if err != nil { + return + } + // Tags should be encoded in minimal form. + if ret.tag < 0x1f { + err = SyntaxError{"non-minimal tag"} + return + } + } + if offset >= len(bytes) { + err = SyntaxError{"truncated tag or length"} + return + } + b = bytes[offset] + offset++ + if b&0x80 == 0 { + // The length is encoded in the bottom 7 bits. + ret.length = int(b & 0x7f) + } else { + // Bottom 7 bits give the number of length bytes to follow. + numBytes := int(b & 0x7f) + if numBytes == 0 { + err = SyntaxError{"indefinite length found (not DER)"} + return + } + ret.length = 0 + for i := 0; i < numBytes; i++ { + if offset >= len(bytes) { + err = SyntaxError{"truncated tag or length"} + return + } + b = bytes[offset] + offset++ + if ret.length >= 1<<23 { + // We can't shift ret.length up without + // overflowing. + err = StructuralError{"length too large"} + return + } + ret.length <<= 8 + ret.length |= int(b) + if ret.length == 0 { + // DER requires that lengths be minimal. + err = StructuralError{"superfluous leading zeros in length"} + return + } + } + + if !AllowPermissiveParsing { + // Short lengths must be encoded in short form. + if ret.length < 0x80 { + err = StructuralError{"non-minimal length"} + return + } + } + } + + return +} + +// parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse +// a number of ASN.1 values from the given byte slice and returns them as a +// slice of Go values of the given type. +func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err error) { + matchAny, expectedTag, compoundType, ok := getUniversalType(elemType) + if !ok { + err = StructuralError{"unknown Go type for slice"} + return + } + + // First we iterate over the input and count the number of elements, + // checking that the types are correct in each case. + numElements := 0 + for offset := 0; offset < len(bytes); { + var t tagAndLength + t, offset, err = parseTagAndLength(bytes, offset) + if err != nil { + return + } + switch t.tag { + case TagIA5String, TagGeneralString, TagT61String, TagUTF8String, TagNumericString, TagBMPString: + // We pretend that various other string types are + // PRINTABLE STRINGs so that a sequence of them can be + // parsed into a []string. + t.tag = TagPrintableString + case TagGeneralizedTime, TagUTCTime: + // Likewise, both time types are treated the same. + t.tag = TagUTCTime + } + + if !matchAny && (t.class != ClassUniversal || t.isCompound != compoundType || t.tag != expectedTag) { + err = StructuralError{"sequence tag mismatch"} + return + } + if invalidLength(offset, t.length, len(bytes)) { + err = SyntaxError{"truncated sequence"} + return + } + offset += t.length + numElements++ + } + ret = reflect.MakeSlice(sliceType, numElements, numElements) + params := fieldParameters{} + offset := 0 + for i := 0; i < numElements; i++ { + offset, err = parseField(ret.Index(i), bytes, offset, params) + if err != nil { + return + } + } + return +} + +var ( + bitStringType = reflect.TypeOf(BitString{}) + objectIdentifierType = reflect.TypeOf(ObjectIdentifier{}) + enumeratedType = reflect.TypeOf(Enumerated(0)) + flagType = reflect.TypeOf(Flag(false)) + timeType = reflect.TypeOf(time.Time{}) + rawValueType = reflect.TypeOf(RawValue{}) + rawContentsType = reflect.TypeOf(RawContent(nil)) + bigIntType = reflect.TypeOf(new(big.Int)) +) + +// invalidLength reports whether offset + length > sliceLength, or if the +// addition would overflow. +func invalidLength(offset, length, sliceLength int) bool { + return offset+length < offset || offset+length > sliceLength +} + +// parseField is the main parsing function. Given a byte slice and an offset +// into the array, it will try to parse a suitable ASN.1 value out and store it +// in the given Value. +func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err error) { + offset = initOffset + fieldType := v.Type() + + // log.Printf("field: %x\ntype: %v, %s\n\n", bytes, fieldType, v.Type().Name()) + + // If we have run out of data, it may be that there are optional elements at the end. + if offset == len(bytes) { + if !setDefaultValue(v, params) { + err = SyntaxError{"sequence truncated"} + } + return + } + + // Deal with the ANY type. + if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 { + var t tagAndLength + t, offset, err = parseTagAndLength(bytes, offset) + if err != nil { + return + } + if invalidLength(offset, t.length, len(bytes)) { + err = SyntaxError{"data truncated"} + return + } + var result interface{} + if !t.isCompound && t.class == ClassUniversal { + innerBytes := bytes[offset : offset+t.length] + switch t.tag { + case TagPrintableString: + result, err = parsePrintableString(innerBytes) + case TagNumericString: + result, err = parseNumericString(innerBytes) + case TagIA5String: + result, err = parseIA5String(innerBytes) + case TagT61String: + result, err = parseT61String(innerBytes) + case TagUTF8String: + result, err = parseUTF8String(innerBytes) + case TagInteger: + result, err = parseInt64(innerBytes) + case TagBitString: + result, err = parseBitString(innerBytes) + case TagOID: + result, err = parseObjectIdentifier(innerBytes) + case TagUTCTime: + result, err = parseUTCTime(innerBytes) + case TagGeneralizedTime: + result, err = parseGeneralizedTime(innerBytes) + case TagOctetString: + result = innerBytes + case TagBMPString: + result, err = parseBMPString(innerBytes) + default: + // If we don't know how to handle the type, we just leave Value as nil. + } + } + offset += t.length + if err != nil { + return + } + if result != nil { + v.Set(reflect.ValueOf(result)) + } + return + } + + t, offset, err := parseTagAndLength(bytes, offset) + if err != nil { + return + } + if params.explicit { + expectedClass := ClassContextSpecific + if params.application { + expectedClass = ClassApplication + } + if offset == len(bytes) { + err = StructuralError{"explicit tag has no child"} + return + } + if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) { + if fieldType == rawValueType { + // The inner element should not be parsed for RawValues. + } else if t.length > 0 { + t, offset, err = parseTagAndLength(bytes, offset) + if err != nil { + return + } + } else { + if fieldType != flagType { + err = StructuralError{"zero length explicit tag was not an asn1.Flag"} + return + } + v.SetBool(true) + return + } + } else { + // The tags didn't match, it might be an optional element. + ok := setDefaultValue(v, params) + if ok { + offset = initOffset + } else { + err = StructuralError{"explicitly tagged member didn't match"} + } + return + } + } + + matchAny, universalTag, compoundType, ok1 := getUniversalType(fieldType) + if !ok1 { + err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)} + return + } + + // Special case for strings: all the ASN.1 string types map to the Go + // type string. getUniversalType returns the tag for PrintableString + // when it sees a string, so if we see a different string type on the + // wire, we change the universal type to match. + if universalTag == TagPrintableString { + if t.class == ClassUniversal { + switch t.tag { + case TagIA5String, TagGeneralString, TagT61String, TagUTF8String, TagNumericString, TagBMPString: + universalTag = t.tag + } + } else if params.stringType != 0 { + universalTag = params.stringType + } + } + + // Special case for time: UTCTime and GeneralizedTime both map to the + // Go type time.Time. + if universalTag == TagUTCTime && t.tag == TagGeneralizedTime && t.class == ClassUniversal { + universalTag = TagGeneralizedTime + } + + if params.set { + universalTag = TagSet + } + + matchAnyClassAndTag := matchAny + expectedClass := ClassUniversal + expectedTag := universalTag + + if !params.explicit && params.tag != nil { + expectedClass = ClassContextSpecific + expectedTag = *params.tag + matchAnyClassAndTag = false + } + + if !params.explicit && params.application && params.tag != nil { + expectedClass = ClassApplication + expectedTag = *params.tag + matchAnyClassAndTag = false + } + + if !params.explicit && params.private && params.tag != nil { + expectedClass = ClassPrivate + expectedTag = *params.tag + matchAnyClassAndTag = false + } + + // We have unwrapped any explicit tagging at this point. + if !matchAnyClassAndTag && (t.class != expectedClass || t.tag != expectedTag) || + (!matchAny && t.isCompound != compoundType) { + // Tags don't match. Again, it could be an optional element. + ok := setDefaultValue(v, params) + if ok { + offset = initOffset + } else { + err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)} + } + return + } + if invalidLength(offset, t.length, len(bytes)) { + err = SyntaxError{"data truncated"} + return + } + innerBytes := bytes[offset : offset+t.length] + offset += t.length + + // We deal with the structures defined in this package first. + switch v := v.Addr().Interface().(type) { + case *RawValue: + *v = RawValue{t.class, t.tag, t.isCompound, innerBytes, bytes[initOffset:offset]} + return + case *ObjectIdentifier: + *v, err = parseObjectIdentifier(innerBytes) + return + case *BitString: + *v, err = parseBitString(innerBytes) + return + case *time.Time: + if universalTag == TagUTCTime { + *v, err = parseUTCTime(innerBytes) + return + } + *v, err = parseGeneralizedTime(innerBytes) + return + case *Enumerated: + parsedInt, err1 := parseInt32(innerBytes) + if err1 == nil { + *v = Enumerated(parsedInt) + } + err = err1 + return + case *Flag: + *v = true + return + case **big.Int: + parsedInt, err1 := parseBigInt(innerBytes) + if err1 == nil { + *v = parsedInt + } + err = err1 + return + } + switch val := v; val.Kind() { + case reflect.Bool: + parsedBool, err1 := parseBool(innerBytes) + if err1 == nil { + val.SetBool(parsedBool) + } + err = err1 + return + case reflect.Int, reflect.Int32, reflect.Int64: + if val.Type().Size() == 4 { + parsedInt, err1 := parseInt32(innerBytes) + if err1 == nil { + val.SetInt(int64(parsedInt)) + } + err = err1 + } else { + parsedInt, err1 := parseInt64(innerBytes) + if err1 == nil { + val.SetInt(parsedInt) + } + err = err1 + } + return + // TODO(dfc) Add support for the remaining integer types + case reflect.Struct: + structType := fieldType + + for i := 0; i < structType.NumField(); i++ { + if structType.Field(i).PkgPath != "" { + err = StructuralError{"struct contains unexported fields"} + return + } + } + + if structType.NumField() > 0 && + structType.Field(0).Type == rawContentsType { + bytes := bytes[initOffset:offset] + val.Field(0).Set(reflect.ValueOf(RawContent(bytes))) + } + + innerOffset := 0 + for i := 0; i < structType.NumField(); i++ { + field := structType.Field(i) + if i == 0 && field.Type == rawContentsType { + continue + } + innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1"))) + if err != nil { + return + } + } + // We allow extra bytes at the end of the SEQUENCE because + // adding elements to the end has been used in X.509 as the + // version numbers have increased. + return + case reflect.Slice: + sliceType := fieldType + if sliceType.Elem().Kind() == reflect.Uint8 { + val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes))) + reflect.Copy(val, reflect.ValueOf(innerBytes)) + return + } + newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem()) + if err1 == nil { + val.Set(newSlice) + } + err = err1 + return + case reflect.String: + var v string + switch universalTag { + case TagPrintableString: + v, err = parsePrintableString(innerBytes) + case TagNumericString: + v, err = parseNumericString(innerBytes) + case TagIA5String: + v, err = parseIA5String(innerBytes) + case TagT61String: + v, err = parseT61String(innerBytes) + case TagUTF8String: + v, err = parseUTF8String(innerBytes) + case TagGeneralString: + // GeneralString is specified in ISO-2022/ECMA-35, + // A brief review suggests that it includes structures + // that allow the encoding to change midstring and + // such. We give up and pass it as an 8-bit string. + v, err = parseT61String(innerBytes) + case TagBMPString: + v, err = parseBMPString(innerBytes) + + default: + err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)} + } + if err == nil { + val.SetString(v) + } + return + } + err = StructuralError{"unsupported: " + v.Type().String()} + return +} + +// canHaveDefaultValue reports whether k is a Kind that we will set a default +// value for. (A signed integer, essentially.) +func canHaveDefaultValue(k reflect.Kind) bool { + switch k { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return true + } + + return false +} + +// setDefaultValue is used to install a default value, from a tag string, into +// a Value. It is successful if the field was optional, even if a default value +// wasn't provided or it failed to install it into the Value. +func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { + if !params.optional { + return + } + ok = true + if params.defaultValue == nil { + return + } + if canHaveDefaultValue(v.Kind()) { + v.SetInt(*params.defaultValue) + } + return +} + +// Unmarshal parses the DER-encoded ASN.1 data structure b +// and uses the reflect package to fill in an arbitrary value pointed at by val. +// Because Unmarshal uses the reflect package, the structs +// being written to must use upper case field names. If val +// is nil or not a pointer, Unmarshal returns an error. +// +// After parsing b, any bytes that were leftover and not used to fill +// val will be returned in rest. When parsing a SEQUENCE into a struct, +// any trailing elements of the SEQUENCE that do not have matching +// fields in val will not be included in rest, as these are considered +// valid elements of the SEQUENCE and not trailing data. +// +// An ASN.1 INTEGER can be written to an int, int32, int64, +// or *big.Int (from the math/big package). +// If the encoded value does not fit in the Go type, +// Unmarshal returns a parse error. +// +// An ASN.1 BIT STRING can be written to a BitString. +// +// An ASN.1 OCTET STRING can be written to a []byte. +// +// An ASN.1 OBJECT IDENTIFIER can be written to an +// ObjectIdentifier. +// +// An ASN.1 ENUMERATED can be written to an Enumerated. +// +// An ASN.1 UTCTIME or GENERALIZEDTIME can be written to a time.Time. +// +// An ASN.1 PrintableString, IA5String, or NumericString can be written to a string. +// +// Any of the above ASN.1 values can be written to an interface{}. +// The value stored in the interface has the corresponding Go type. +// For integers, that type is int64. +// +// An ASN.1 SEQUENCE OF x or SET OF x can be written +// to a slice if an x can be written to the slice's element type. +// +// An ASN.1 SEQUENCE or SET can be written to a struct +// if each of the elements in the sequence can be +// written to the corresponding element in the struct. +// +// The following tags on struct fields have special meaning to Unmarshal: +// +// application specifies that an APPLICATION tag is used +// private specifies that a PRIVATE tag is used +// default:x sets the default value for optional integer fields (only used if optional is also present) +// explicit specifies that an additional, explicit tag wraps the implicit one +// optional marks the field as ASN.1 OPTIONAL +// set causes a SET, rather than a SEQUENCE type to be expected +// tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC +// +// When decoding an ASN.1 value with an IMPLICIT tag into a string field, +// Unmarshal will default to a PrintableString, which doesn't support +// characters such as '@' and '&'. To force other encodings, use the following +// tags: +// +// ia5 causes strings to be unmarshaled as ASN.1 IA5String values +// numeric causes strings to be unmarshaled as ASN.1 NumericString values +// utf8 causes strings to be unmarshaled as ASN.1 UTF8String values +// +// If the type of the first field of a structure is RawContent then the raw +// ASN1 contents of the struct will be stored in it. +// +// If the name of a slice type ends with "SET" then it's treated as if +// the "set" tag was set on it. This results in interpreting the type as a +// SET OF x rather than a SEQUENCE OF x. This can be used with nested slices +// where a struct tag cannot be given. +// +// Other ASN.1 types are not supported; if it encounters them, +// Unmarshal returns a parse error. +func Unmarshal(b []byte, val interface{}) (rest []byte, err error) { + return UnmarshalWithParams(b, val, "") +} + +// An invalidUnmarshalError describes an invalid argument passed to Unmarshal. +// (The argument to Unmarshal must be a non-nil pointer.) +type invalidUnmarshalError struct { + Type reflect.Type +} + +func (e *invalidUnmarshalError) Error() string { + if e.Type == nil { + return "asn1: Unmarshal recipient value is nil" + } + + if e.Type.Kind() != reflect.Ptr { + return "asn1: Unmarshal recipient value is non-pointer " + e.Type.String() + } + return "asn1: Unmarshal recipient value is nil " + e.Type.String() +} + +// UnmarshalWithParams allows field parameters to be specified for the +// top-level element. The form of the params is the same as the field tags. +func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err error) { + v := reflect.ValueOf(val) + if v.Kind() != reflect.Ptr || v.IsNil() { + return nil, &invalidUnmarshalError{reflect.TypeOf(val)} + } + offset, err := parseField(v.Elem(), b, 0, parseFieldParameters(params)) + if err != nil { + return nil, err + } + return b[offset:], nil +} diff --git a/vendor/github.com/zmap/zcrypto/encoding/asn1/common.go b/vendor/github.com/zmap/zcrypto/encoding/asn1/common.go new file mode 100644 index 000000000..1c712e1ef --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/encoding/asn1/common.go @@ -0,0 +1,192 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package asn1 + +import ( + "reflect" + "strconv" + "strings" +) + +// ASN.1 objects have metadata preceding them: +// the tag: the type of the object +// a flag denoting if this object is compound or not +// the class type: the namespace of the tag +// the length of the object, in bytes + +// Here are some standard tags and classes + +// ASN.1 tags represent the type of the following object. +const ( + TagBoolean = 1 + TagInteger = 2 + TagBitString = 3 + TagOctetString = 4 + TagNull = 5 + TagOID = 6 + TagEnum = 10 + TagUTF8String = 12 + TagSequence = 16 + TagSet = 17 + TagNumericString = 18 + TagPrintableString = 19 + TagT61String = 20 + TagIA5String = 22 + TagUTCTime = 23 + TagGeneralizedTime = 24 + TagGeneralString = 27 + TagBMPString = 30 +) + +// ASN.1 class types represent the namespace of the tag. +const ( + ClassUniversal = 0 + ClassApplication = 1 + ClassContextSpecific = 2 + ClassPrivate = 3 +) + +type tagAndLength struct { + class, tag, length int + isCompound bool +} + +// ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead +// of" and "in addition to". When not specified, every primitive type has a +// default tag in the UNIVERSAL class. +// +// For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1 +// doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT +// CONTEXT-SPECIFIC 42], that means that the tag is replaced by another. +// +// On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an +// /additional/ tag would wrap the default tag. This explicit tag will have the +// compound flag set. +// +// (This is used in order to remove ambiguity with optional elements.) +// +// You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we +// don't support that here. We support a single layer of EXPLICIT or IMPLICIT +// tagging with tag strings on the fields of a structure. + +// fieldParameters is the parsed representation of tag string from a structure field. +type fieldParameters struct { + optional bool // true iff the field is OPTIONAL + explicit bool // true iff an EXPLICIT tag is in use. + application bool // true iff an APPLICATION tag is in use. + private bool // true iff a PRIVATE tag is in use. + defaultValue *int64 // a default value for INTEGER typed fields (maybe nil). + tag *int // the EXPLICIT or IMPLICIT tag (maybe nil). + stringType int // the string tag to use when marshaling. + timeType int // the time tag to use when marshaling. + set bool // true iff this should be encoded as a SET + omitEmpty bool // true iff this should be omitted if empty when marshaling. + + // Invariants: + // if explicit is set, tag is non-nil. +} + +// Given a tag string with the format specified in the package comment, +// parseFieldParameters will parse it into a fieldParameters structure, +// ignoring unknown parts of the string. +func parseFieldParameters(str string) (ret fieldParameters) { + var part string + for len(str) > 0 { + // This loop uses IndexByte and explicit slicing + // instead of strings.Split(str, ",") to reduce allocations. + i := strings.IndexByte(str, ',') + if i < 0 { + part, str = str, "" + } else { + part, str = str[:i], str[i+1:] + } + switch { + case part == "optional": + ret.optional = true + case part == "explicit": + ret.explicit = true + if ret.tag == nil { + ret.tag = new(int) + } + case part == "generalized": + ret.timeType = TagGeneralizedTime + case part == "utc": + ret.timeType = TagUTCTime + case part == "ia5": + ret.stringType = TagIA5String + case part == "printable": + ret.stringType = TagPrintableString + case part == "numeric": + ret.stringType = TagNumericString + case part == "utf8": + ret.stringType = TagUTF8String + case strings.HasPrefix(part, "default:"): + i, err := strconv.ParseInt(part[8:], 10, 64) + if err == nil { + ret.defaultValue = new(int64) + *ret.defaultValue = i + } + case strings.HasPrefix(part, "tag:"): + i, err := strconv.Atoi(part[4:]) + if err == nil { + ret.tag = new(int) + *ret.tag = i + } + case part == "set": + ret.set = true + case part == "application": + ret.application = true + if ret.tag == nil { + ret.tag = new(int) + } + case part == "private": + ret.private = true + if ret.tag == nil { + ret.tag = new(int) + } + case part == "omitempty": + ret.omitEmpty = true + } + } + return +} + +// Given a reflected Go type, getUniversalType returns the default tag number +// and expected compound flag. +func getUniversalType(t reflect.Type) (matchAny bool, tagNumber int, isCompound, ok bool) { + switch t { + case rawValueType: + return true, -1, false, true + case objectIdentifierType: + return false, TagOID, false, true + case bitStringType: + return false, TagBitString, false, true + case timeType: + return false, TagUTCTime, false, true + case enumeratedType: + return false, TagEnum, false, true + case bigIntType: + return false, TagInteger, false, true + } + switch t.Kind() { + case reflect.Bool: + return false, TagBoolean, false, true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return false, TagInteger, false, true + case reflect.Struct: + return false, TagSequence, true, true + case reflect.Slice: + if t.Elem().Kind() == reflect.Uint8 { + return false, TagOctetString, false, true + } + if strings.HasSuffix(t.Name(), "SET") { + return false, TagSet, true, true + } + return false, TagSequence, true, true + case reflect.String: + return false, TagPrintableString, false, true + } + return false, 0, false, false +} diff --git a/vendor/github.com/zmap/zcrypto/encoding/asn1/marshal.go b/vendor/github.com/zmap/zcrypto/encoding/asn1/marshal.go new file mode 100644 index 000000000..0d34d5aa1 --- /dev/null +++ b/vendor/github.com/zmap/zcrypto/encoding/asn1/marshal.go @@ -0,0 +1,747 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package asn1 + +import ( + "bytes" + "errors" + "fmt" + "math/big" + "reflect" + "sort" + "time" + "unicode/utf8" +) + +var ( + byte00Encoder encoder = byteEncoder(0x00) + byteFFEncoder encoder = byteEncoder(0xff) +) + +// encoder represents an ASN.1 element that is waiting to be marshaled. +type encoder interface { + // Len returns the number of bytes needed to marshal this element. + Len() int + // Encode encodes this element by writing Len() bytes to dst. + Encode(dst []byte) +} + +type byteEncoder byte + +func (c byteEncoder) Len() int { + return 1 +} + +func (c byteEncoder) Encode(dst []byte) { + dst[0] = byte(c) +} + +type bytesEncoder []byte + +func (b bytesEncoder) Len() int { + return len(b) +} + +func (b bytesEncoder) Encode(dst []byte) { + if copy(dst, b) != len(b) { + panic("internal error") + } +} + +type stringEncoder string + +func (s stringEncoder) Len() int { + return len(s) +} + +func (s stringEncoder) Encode(dst []byte) { + if copy(dst, s) != len(s) { + panic("internal error") + } +} + +type multiEncoder []encoder + +func (m multiEncoder) Len() int { + var size int + for _, e := range m { + size += e.Len() + } + return size +} + +func (m multiEncoder) Encode(dst []byte) { + var off int + for _, e := range m { + e.Encode(dst[off:]) + off += e.Len() + } +} + +type setEncoder []encoder + +func (s setEncoder) Len() int { + var size int + for _, e := range s { + size += e.Len() + } + return size +} + +func (s setEncoder) Encode(dst []byte) { + // Per X690 Section 11.6: The encodings of the component values of a + // set-of value shall appear in ascending order, the encodings being + // compared as octet strings with the shorter components being padded + // at their trailing end with 0-octets. + // + // First we encode each element to its TLV encoding and then use + // octetSort to get the ordering expected by X690 DER rules before + // writing the sorted encodings out to dst. + l := make([][]byte, len(s)) + for i, e := range s { + l[i] = make([]byte, e.Len()) + e.Encode(l[i]) + } + + sort.Slice(l, func(i, j int) bool { + // Since we are using bytes.Compare to compare TLV encodings we + // don't need to right pad s[i] and s[j] to the same length as + // suggested in X690. If len(s[i]) < len(s[j]) the length octet of + // s[i], which is the first determining byte, will inherently be + // smaller than the length octet of s[j]. This lets us skip the + // padding step. + return bytes.Compare(l[i], l[j]) < 0 + }) + + var off int + for _, b := range l { + copy(dst[off:], b) + off += len(b) + } +} + +type taggedEncoder struct { + // scratch contains temporary space for encoding the tag and length of + // an element in order to avoid extra allocations. + scratch [8]byte + tag encoder + body encoder +} + +func (t *taggedEncoder) Len() int { + return t.tag.Len() + t.body.Len() +} + +func (t *taggedEncoder) Encode(dst []byte) { + t.tag.Encode(dst) + t.body.Encode(dst[t.tag.Len():]) +} + +type int64Encoder int64 + +func (i int64Encoder) Len() int { + n := 1 + + for i > 127 { + n++ + i >>= 8 + } + + for i < -128 { + n++ + i >>= 8 + } + + return n +} + +func (i int64Encoder) Encode(dst []byte) { + n := i.Len() + + for j := 0; j < n; j++ { + dst[j] = byte(i >> uint((n-1-j)*8)) + } +} + +func base128IntLength(n int64) int { + if n == 0 { + return 1 + } + + l := 0 + for i := n; i > 0; i >>= 7 { + l++ + } + + return l +} + +func appendBase128Int(dst []byte, n int64) []byte { + l := base128IntLength(n) + + for i := l - 1; i >= 0; i-- { + o := byte(n >> uint(i*7)) + o &= 0x7f + if i != 0 { + o |= 0x80 + } + + dst = append(dst, o) + } + + return dst +} + +func makeBigInt(n *big.Int) (encoder, error) { + if n == nil { + return nil, StructuralError{"empty integer"} + } + + if n.Sign() < 0 { + // A negative number has to be converted to two's-complement + // form. So we'll invert and subtract 1. If the + // most-significant-bit isn't set then we'll need to pad the + // beginning with 0xff in order to keep the number negative. + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bytes := nMinus1.Bytes() + for i := range bytes { + bytes[i] ^= 0xff + } + if len(bytes) == 0 || bytes[0]&0x80 == 0 { + return multiEncoder([]encoder{byteFFEncoder, bytesEncoder(bytes)}), nil + } + return bytesEncoder(bytes), nil + } else if n.Sign() == 0 { + // Zero is written as a single 0 zero rather than no bytes. + return byte00Encoder, nil + } else { + bytes := n.Bytes() + if len(bytes) > 0 && bytes[0]&0x80 != 0 { + // We'll have to pad this with 0x00 in order to stop it + // looking like a negative number. + return multiEncoder([]encoder{byte00Encoder, bytesEncoder(bytes)}), nil + } + return bytesEncoder(bytes), nil + } +} + +func appendLength(dst []byte, i int) []byte { + n := lengthLength(i) + + for ; n > 0; n-- { + dst = append(dst, byte(i>>uint((n-1)*8))) + } + + return dst +} + +func lengthLength(i int) (numBytes int) { + numBytes = 1 + for i > 255 { + numBytes++ + i >>= 8 + } + return +} + +func appendTagAndLength(dst []byte, t tagAndLength) []byte { + b := uint8(t.class) << 6 + if t.isCompound { + b |= 0x20 + } + if t.tag >= 31 { + b |= 0x1f + dst = append(dst, b) + dst = appendBase128Int(dst, int64(t.tag)) + } else { + b |= uint8(t.tag) + dst = append(dst, b) + } + + if t.length >= 128 { + l := lengthLength(t.length) + dst = append(dst, 0x80|byte(l)) + dst = appendLength(dst, t.length) + } else { + dst = append(dst, byte(t.length)) + } + + return dst +} + +type bitStringEncoder BitString + +func (b bitStringEncoder) Len() int { + return len(b.Bytes) + 1 +} + +func (b bitStringEncoder) Encode(dst []byte) { + dst[0] = byte((8 - b.BitLength%8) % 8) + if copy(dst[1:], b.Bytes) != len(b.Bytes) { + panic("internal error") + } +} + +type oidEncoder []int + +func (oid oidEncoder) Len() int { + l := base128IntLength(int64(oid[0]*40 + oid[1])) + for i := 2; i < len(oid); i++ { + l += base128IntLength(int64(oid[i])) + } + return l +} + +func (oid oidEncoder) Encode(dst []byte) { + dst = appendBase128Int(dst[:0], int64(oid[0]*40+oid[1])) + for i := 2; i < len(oid); i++ { + dst = appendBase128Int(dst, int64(oid[i])) + } +} + +func makeObjectIdentifier(oid []int) (e encoder, err error) { + if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) { + return nil, StructuralError{"invalid object identifier"} + } + + return oidEncoder(oid), nil +} + +func makePrintableString(s string) (e encoder, err error) { + for i := 0; i < len(s); i++ { + // The asterisk is often used in PrintableString, even though + // it is invalid. If a PrintableString was specifically + // requested then the asterisk is permitted by this code. + // Ampersand is allowed in parsing due a handful of CA + // certificates, however when making new certificates + // it is rejected. + if !isPrintable(s[i], allowAsterisk, rejectAmpersand) { + return nil, StructuralError{"PrintableString contains invalid character"} + } + } + + return stringEncoder(s), nil +} + +func makeIA5String(s string) (e encoder, err error) { + for i := 0; i < len(s); i++ { + if s[i] > 127 { + return nil, StructuralError{"IA5String contains invalid character"} + } + } + + return stringEncoder(s), nil +} + +func makeNumericString(s string) (e encoder, err error) { + for i := 0; i < len(s); i++ { + if !isNumeric(s[i]) { + return nil, StructuralError{"NumericString contains invalid character"} + } + } + + return stringEncoder(s), nil +} + +func makeUTF8String(s string) encoder { + return stringEncoder(s) +} + +func appendTwoDigits(dst []byte, v int) []byte { + return append(dst, byte('0'+(v/10)%10), byte('0'+v%10)) +} + +func appendFourDigits(dst []byte, v int) []byte { + var bytes [4]byte + for i := range bytes { + bytes[3-i] = '0' + byte(v%10) + v /= 10 + } + return append(dst, bytes[:]...) +} + +func outsideUTCRange(t time.Time) bool { + year := t.Year() + return year < 1950 || year >= 2050 +} + +func makeUTCTime(t time.Time) (e encoder, err error) { + dst := make([]byte, 0, 18) + + dst, err = appendUTCTime(dst, t) + if err != nil { + return nil, err + } + + return bytesEncoder(dst), nil +} + +func makeGeneralizedTime(t time.Time) (e encoder, err error) { + dst := make([]byte, 0, 20) + + dst, err = appendGeneralizedTime(dst, t) + if err != nil { + return nil, err + } + + return bytesEncoder(dst), nil +} + +func appendUTCTime(dst []byte, t time.Time) (ret []byte, err error) { + year := t.Year() + + switch { + case 1950 <= year && year < 2000: + dst = appendTwoDigits(dst, year-1900) + case 2000 <= year && year < 2050: + dst = appendTwoDigits(dst, year-2000) + default: + return nil, StructuralError{"cannot represent time as UTCTime"} + } + + return appendTimeCommon(dst, t), nil +} + +func appendGeneralizedTime(dst []byte, t time.Time) (ret []byte, err error) { + year := t.Year() + if year < 0 || year > 9999 { + return nil, StructuralError{"cannot represent time as GeneralizedTime"} + } + + dst = appendFourDigits(dst, year) + + return appendTimeCommon(dst, t), nil +} + +func appendTimeCommon(dst []byte, t time.Time) []byte { + _, month, day := t.Date() + + dst = appendTwoDigits(dst, int(month)) + dst = appendTwoDigits(dst, day) + + hour, min, sec := t.Clock() + + dst = appendTwoDigits(dst, hour) + dst = appendTwoDigits(dst, min) + dst = appendTwoDigits(dst, sec) + + _, offset := t.Zone() + + switch { + case offset/60 == 0: + return append(dst, 'Z') + case offset > 0: + dst = append(dst, '+') + case offset < 0: + dst = append(dst, '-') + } + + offsetMinutes := offset / 60 + if offsetMinutes < 0 { + offsetMinutes = -offsetMinutes + } + + dst = appendTwoDigits(dst, offsetMinutes/60) + dst = appendTwoDigits(dst, offsetMinutes%60) + + return dst +} + +func stripTagAndLength(in []byte) []byte { + _, offset, err := parseTagAndLength(in, 0) + if err != nil { + return in + } + return in[offset:] +} + +func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error) { + switch value.Type() { + case flagType: + return bytesEncoder(nil), nil + case timeType: + t := value.Interface().(time.Time) + if params.timeType == TagGeneralizedTime || outsideUTCRange(t) { + return makeGeneralizedTime(t) + } + return makeUTCTime(t) + case bitStringType: + return bitStringEncoder(value.Interface().(BitString)), nil + case objectIdentifierType: + return makeObjectIdentifier(value.Interface().(ObjectIdentifier)) + case bigIntType: + return makeBigInt(value.Interface().(*big.Int)) + } + + switch v := value; v.Kind() { + case reflect.Bool: + if v.Bool() { + return byteFFEncoder, nil + } + return byte00Encoder, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return int64Encoder(v.Int()), nil + case reflect.Struct: + t := v.Type() + + for i := 0; i < t.NumField(); i++ { + if t.Field(i).PkgPath != "" { + return nil, StructuralError{"struct contains unexported fields"} + } + } + + startingField := 0 + + n := t.NumField() + if n == 0 { + return bytesEncoder(nil), nil + } + + // If the first element of the structure is a non-empty + // RawContents, then we don't bother serializing the rest. + if t.Field(0).Type == rawContentsType { + s := v.Field(0) + if s.Len() > 0 { + bytes := s.Bytes() + /* The RawContents will contain the tag and + * length fields but we'll also be writing + * those ourselves, so we strip them out of + * bytes */ + return bytesEncoder(stripTagAndLength(bytes)), nil + } + + startingField = 1 + } + + switch n1 := n - startingField; n1 { + case 0: + return bytesEncoder(nil), nil + case 1: + return makeField(v.Field(startingField), parseFieldParameters(t.Field(startingField).Tag.Get("asn1"))) + default: + m := make([]encoder, n1) + for i := 0; i < n1; i++ { + m[i], err = makeField(v.Field(i+startingField), parseFieldParameters(t.Field(i+startingField).Tag.Get("asn1"))) + if err != nil { + return nil, err + } + } + + return multiEncoder(m), nil + } + case reflect.Slice: + sliceType := v.Type() + if sliceType.Elem().Kind() == reflect.Uint8 { + return bytesEncoder(v.Bytes()), nil + } + + var fp fieldParameters + + switch l := v.Len(); l { + case 0: + return bytesEncoder(nil), nil + case 1: + return makeField(v.Index(0), fp) + default: + m := make([]encoder, l) + + for i := 0; i < l; i++ { + m[i], err = makeField(v.Index(i), fp) + if err != nil { + return nil, err + } + } + + if params.set { + return setEncoder(m), nil + } + return multiEncoder(m), nil + } + case reflect.String: + switch params.stringType { + case TagIA5String: + return makeIA5String(v.String()) + case TagPrintableString: + return makePrintableString(v.String()) + case TagNumericString: + return makeNumericString(v.String()) + default: + return makeUTF8String(v.String()), nil + } + } + + return nil, StructuralError{"unknown Go type"} +} + +func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) { + if !v.IsValid() { + return nil, fmt.Errorf("asn1: cannot marshal nil value") + } + // If the field is an interface{} then recurse into it. + if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 { + return makeField(v.Elem(), params) + } + + if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty { + return bytesEncoder(nil), nil + } + + if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) { + defaultValue := reflect.New(v.Type()).Elem() + defaultValue.SetInt(*params.defaultValue) + + if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) { + return bytesEncoder(nil), nil + } + } + + // If no default value is given then the zero value for the type is + // assumed to be the default value. This isn't obviously the correct + // behavior, but it's what Go has traditionally done. + if params.optional && params.defaultValue == nil { + if reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { + return bytesEncoder(nil), nil + } + } + + if v.Type() == rawValueType { + rv := v.Interface().(RawValue) + if len(rv.FullBytes) != 0 { + return bytesEncoder(rv.FullBytes), nil + } + + t := new(taggedEncoder) + + t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})) + t.body = bytesEncoder(rv.Bytes) + + return t, nil + } + + matchAny, tag, isCompound, ok := getUniversalType(v.Type()) + if !ok || matchAny { + return nil, StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} + } + + if params.timeType != 0 && tag != TagUTCTime { + return nil, StructuralError{"explicit time type given to non-time member"} + } + + if params.stringType != 0 && tag != TagPrintableString { + return nil, StructuralError{"explicit string type given to non-string member"} + } + + switch tag { + case TagPrintableString: + if params.stringType == 0 { + // This is a string without an explicit string type. We'll use + // a PrintableString if the character set in the string is + // sufficiently limited, otherwise we'll use a UTF8String. + for _, r := range v.String() { + if r >= utf8.RuneSelf || !isPrintable(byte(r), rejectAsterisk, rejectAmpersand) { + if !utf8.ValidString(v.String()) { + return nil, errors.New("asn1: string not valid UTF-8") + } + tag = TagUTF8String + break + } + } + } else { + tag = params.stringType + } + case TagUTCTime: + if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) { + tag = TagGeneralizedTime + } + } + + if params.set { + if tag != TagSequence { + return nil, StructuralError{"non sequence tagged as set"} + } + tag = TagSet + } + + // makeField can be called for a slice that should be treated as a SET + // but doesn't have params.set set, for instance when using a slice + // with the SET type name suffix. In this case getUniversalType returns + // TagSet, but makeBody doesn't know about that so will treat the slice + // as a sequence. To work around this we set params.set. + if tag == TagSet && !params.set { + params.set = true + } + + t := new(taggedEncoder) + + t.body, err = makeBody(v, params) + if err != nil { + return nil, err + } + + bodyLen := t.body.Len() + + class := ClassUniversal + if params.tag != nil { + if params.application { + class = ClassApplication + } else if params.private { + class = ClassPrivate + } else { + class = ClassContextSpecific + } + + if params.explicit { + t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{ClassUniversal, tag, bodyLen, isCompound})) + + tt := new(taggedEncoder) + + tt.body = t + + tt.tag = bytesEncoder(appendTagAndLength(tt.scratch[:0], tagAndLength{ + class: class, + tag: *params.tag, + length: bodyLen + t.tag.Len(), + isCompound: true, + })) + + return tt, nil + } + + // implicit tag. + tag = *params.tag + } + + t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound})) + + return t, nil +} + +// Marshal returns the ASN.1 encoding of val. +// +// In addition to the struct tags recognised by Unmarshal, the following can be +// used: +// +// ia5: causes strings to be marshaled as ASN.1, IA5String values +// omitempty: causes empty slices to be skipped +// printable: causes strings to be marshaled as ASN.1, PrintableString values +// utf8: causes strings to be marshaled as ASN.1, UTF8String values +// utc: causes time.Time to be marshaled as ASN.1, UTCTime values +// generalized: causes time.Time to be marshaled as ASN.1, GeneralizedTime values +func Marshal(val interface{}) ([]byte, error) { + return MarshalWithParams(val, "") +} + +// MarshalWithParams allows field parameters to be specified for the +// top-level element. The form of the params is the same as the field tags. +func MarshalWithParams(val interface{}, params string) ([]byte, error) { + e, err := makeField(reflect.ValueOf(val), parseFieldParameters(params)) + if err != nil { + return nil, err + } + b := make([]byte, e.Len()) + e.Encode(b) + return b, nil +} diff --git a/vendor/github.com/zmap/zcrypto/x509/extended_key_usage.go b/vendor/github.com/zmap/zcrypto/x509/extended_key_usage.go index 4b66fc522..cde3a8e05 100644 --- a/vendor/github.com/zmap/zcrypto/x509/extended_key_usage.go +++ b/vendor/github.com/zmap/zcrypto/x509/extended_key_usage.go @@ -7,7 +7,7 @@ package x509 import ( - "encoding/asn1" + "github.com/zmap/zcrypto/encoding/asn1" ) const ( diff --git a/vendor/github.com/zmap/zcrypto/x509/extensions.go b/vendor/github.com/zmap/zcrypto/x509/extensions.go index 3c15216e3..b1edaf26e 100644 --- a/vendor/github.com/zmap/zcrypto/x509/extensions.go +++ b/vendor/github.com/zmap/zcrypto/x509/extensions.go @@ -5,13 +5,13 @@ package x509 import ( - "encoding/asn1" "encoding/hex" "encoding/json" "net" "strconv" "strings" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509/ct" "github.com/zmap/zcrypto/x509/pkix" ) diff --git a/vendor/github.com/zmap/zcrypto/x509/json.go b/vendor/github.com/zmap/zcrypto/x509/json.go index 936f28f3f..af26c4958 100644 --- a/vendor/github.com/zmap/zcrypto/x509/json.go +++ b/vendor/github.com/zmap/zcrypto/x509/json.go @@ -7,17 +7,15 @@ package x509 import ( "crypto/ecdsa" "crypto/rsa" - "encoding/asn1" "encoding/json" "errors" "net" "sort" - - "github.com/zmap/zcrypto/dsa" - "strings" "time" + "github.com/zmap/zcrypto/dsa" + "github.com/zmap/zcrypto/encoding/asn1" jsonKeys "github.com/zmap/zcrypto/json" "github.com/zmap/zcrypto/util" "github.com/zmap/zcrypto/x509/pkix" @@ -27,7 +25,7 @@ var kMinTime, kMaxTime time.Time func init() { var err error - kMinTime, err = time.Parse(time.RFC3339, "1970-01-01T00:00:00Z") + kMinTime, err = time.Parse(time.RFC3339, "0001-01-01T00:00:00Z") if err != nil { panic(err) } @@ -220,7 +218,7 @@ func (v *validity) MarshalJSON() ([]byte, error) { aux := auxValidity{ Start: clampTime(v.NotBefore.UTC()).Format(time.RFC3339), End: clampTime(v.NotAfter.UTC()).Format(time.RFC3339), - ValidityPeriod: int(v.NotAfter.Sub(v.NotBefore).Seconds()), + ValidityPeriod: int(v.NotAfter.Unix() - v.NotBefore.Unix()), } return json.Marshal(&aux) } @@ -237,7 +235,6 @@ func (v *validity) UnmarshalJSON(b []byte) error { if v.NotAfter, err = time.Parse(time.RFC3339, aux.End); err != nil { return err } - return nil } diff --git a/vendor/github.com/zmap/zcrypto/x509/pkcs1.go b/vendor/github.com/zmap/zcrypto/x509/pkcs1.go index 73bc7623a..008112ec5 100644 --- a/vendor/github.com/zmap/zcrypto/x509/pkcs1.go +++ b/vendor/github.com/zmap/zcrypto/x509/pkcs1.go @@ -6,9 +6,10 @@ package x509 import ( "crypto/rsa" - "encoding/asn1" "errors" "math/big" + + "github.com/zmap/zcrypto/encoding/asn1" ) // pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key. diff --git a/vendor/github.com/zmap/zcrypto/x509/pkcs8.go b/vendor/github.com/zmap/zcrypto/x509/pkcs8.go index d69049fae..4f4d12a9c 100644 --- a/vendor/github.com/zmap/zcrypto/x509/pkcs8.go +++ b/vendor/github.com/zmap/zcrypto/x509/pkcs8.go @@ -5,9 +5,10 @@ package x509 import ( - "encoding/asn1" "errors" "fmt" + + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509/pkix" ) diff --git a/vendor/github.com/zmap/zcrypto/x509/pkix/json.go b/vendor/github.com/zmap/zcrypto/x509/pkix/json.go index 3000f977e..b7041a67e 100644 --- a/vendor/github.com/zmap/zcrypto/x509/pkix/json.go +++ b/vendor/github.com/zmap/zcrypto/x509/pkix/json.go @@ -5,11 +5,12 @@ package pkix import ( - "encoding/asn1" "encoding/json" "errors" "strconv" "strings" + + "github.com/zmap/zcrypto/encoding/asn1" ) type auxAttributeTypeAndValue struct { diff --git a/vendor/github.com/zmap/zcrypto/x509/pkix/oid.go b/vendor/github.com/zmap/zcrypto/x509/pkix/oid.go index 314ab7b58..444b3afff 100644 --- a/vendor/github.com/zmap/zcrypto/x509/pkix/oid.go +++ b/vendor/github.com/zmap/zcrypto/x509/pkix/oid.go @@ -5,11 +5,12 @@ package pkix import ( - "encoding/asn1" "encoding/json" "fmt" "strconv" "strings" + + "github.com/zmap/zcrypto/encoding/asn1" ) // AuxOID behaves similar to asn1.ObjectIdentifier, except encodes to JSON as a diff --git a/vendor/github.com/zmap/zcrypto/x509/pkix/pkix.go b/vendor/github.com/zmap/zcrypto/x509/pkix/pkix.go index 5f3f013c6..176b6c44a 100644 --- a/vendor/github.com/zmap/zcrypto/x509/pkix/pkix.go +++ b/vendor/github.com/zmap/zcrypto/x509/pkix/pkix.go @@ -7,12 +7,18 @@ package pkix import ( - "encoding/asn1" + "encoding/hex" + "fmt" "math/big" - "strings" "time" + + "github.com/zmap/zcrypto/encoding/asn1" ) +// LegacyNameString allows to specify legacy ZCrypto behaviour +// for X509Name.String() in reverse order +var LegacyNameString = false + // AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC // 5280, section 4.1.1.2. type AlgorithmIdentifier struct { @@ -25,7 +31,7 @@ type RDNSequence []RelativeDistinguishedNameSET type RelativeDistinguishedNameSET []AttributeTypeAndValue // AttributeTypeAndValue mirrors the ASN.1 structure of the same name in -// http://tools.ietf.org/html/rfc5280#section-4.1.2.4 +// RFC 5280, Section 4.1.2.4. type AttributeTypeAndValue struct { Type asn1.ObjectIdentifier `json:"type"` Value interface{} `json:"value"` @@ -47,7 +53,9 @@ type Extension struct { } // Name represents an X.509 distinguished name. This only includes the common -// elements of a DN. Additional elements in the name are ignored. +// elements of a DN. Note that Name is only an approximation of the X.509 +// structure. If an accurate representation is needed, asn1.Unmarshal the raw +// subject or issuer as an RDNSequence. type Name struct { Country, Organization, OrganizationalUnit []string Locality, Province []string @@ -60,71 +68,81 @@ type Name struct { // EV Components JurisdictionLocality, JurisdictionProvince, JurisdictionCountry []string - Names []AttributeTypeAndValue - ExtraNames []AttributeTypeAndValue + // Names contains all parsed attributes. When parsing distinguished names, + // this can be used to extract non-standard attributes that are not parsed + // by this package. When marshaling to RDNSequences, the Names field is + // ignored, see ExtraNames. + Names []AttributeTypeAndValue + // ExtraNames contains attributes to be copied, raw, into any marshaled + // distinguished names. Values override any attributes with the same OID. + // The ExtraNames field is not populated when parsing, see Names. + ExtraNames []AttributeTypeAndValue // OriginalRDNS is saved if the name is populated using FillFromRDNSequence. // Additionally, if OriginalRDNS is non-nil, the String and ToRDNSequence // methods will simply use this. OriginalRDNS RDNSequence } -// FillFromRDNSequence populates n based on the AttributeTypeAndValueSETs in the -// RDNSequence. It save the sequence as OriginalRDNS. +// FillFromRDNSequence populates n from the provided RDNSequence. +// Multi-entry RDNs are flattened, all entries are added to the +// relevant n fields, and the grouping is not preserved. func (n *Name) FillFromRDNSequence(rdns *RDNSequence) { n.OriginalRDNS = *rdns for _, rdn := range *rdns { if len(rdn) == 0 { continue } - atv := rdn[0] - n.Names = append(n.Names, atv) - value, ok := atv.Value.(string) - if !ok { - continue - } - t := atv.Type - if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 { - switch t[3] { - case 3: - n.CommonName = value - n.CommonNames = append(n.CommonNames, value) - case 4: - n.Surname = append(n.Surname, value) - case 5: - n.SerialNumber = value - n.SerialNumbers = append(n.SerialNumbers, value) - case 6: - n.Country = append(n.Country, value) - case 7: - n.Locality = append(n.Locality, value) - case 8: - n.Province = append(n.Province, value) - case 9: - n.StreetAddress = append(n.StreetAddress, value) - case 10: - n.Organization = append(n.Organization, value) - case 11: - n.OrganizationalUnit = append(n.OrganizationalUnit, value) - case 17: - n.PostalCode = append(n.PostalCode, value) - case 42: - n.GivenName = append(n.GivenName, value) - case 97: - n.OrganizationIDs = append(n.OrganizationIDs, value) + for _, atv := range rdn { + n.Names = append(n.Names, atv) + value, ok := atv.Value.(string) + if !ok { + continue + } + + t := atv.Type + if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 { + switch t[3] { + case 3: + n.CommonName = value + n.CommonNames = append(n.CommonNames, value) + case 4: + n.Surname = append(n.Surname, value) + case 5: + n.SerialNumber = value + n.SerialNumbers = append(n.SerialNumbers, value) + case 6: + n.Country = append(n.Country, value) + case 7: + n.Locality = append(n.Locality, value) + case 8: + n.Province = append(n.Province, value) + case 9: + n.StreetAddress = append(n.StreetAddress, value) + case 10: + n.Organization = append(n.Organization, value) + case 11: + n.OrganizationalUnit = append(n.OrganizationalUnit, value) + case 17: + n.PostalCode = append(n.PostalCode, value) + case 42: + n.GivenName = append(n.GivenName, value) + case 97: + n.OrganizationIDs = append(n.OrganizationIDs, value) + } + } else if t.Equal(oidDomainComponent) { + n.DomainComponent = append(n.DomainComponent, value) + } else if t.Equal(oidDNEmailAddress) { + // Deprecated, see RFC 5280 Section 4.1.2.6 + n.EmailAddress = append(n.EmailAddress, value) + } else if t.Equal(oidJurisdictionLocality) { + n.JurisdictionLocality = append(n.JurisdictionLocality, value) + } else if t.Equal(oidJurisdictionProvince) { + n.JurisdictionProvince = append(n.JurisdictionProvince, value) + } else if t.Equal(oidJurisdictionCountry) { + n.JurisdictionCountry = append(n.JurisdictionCountry, value) } - } else if t.Equal(oidDomainComponent) { - n.DomainComponent = append(n.DomainComponent, value) - } else if t.Equal(oidDNEmailAddress) { - // Deprecated, see RFC 5280 Section 4.1.2.6 - n.EmailAddress = append(n.EmailAddress, value) - } else if t.Equal(oidJurisdictionLocality) { - n.JurisdictionLocality = append(n.JurisdictionLocality, value) - } else if t.Equal(oidJurisdictionProvince) { - n.JurisdictionProvince = append(n.JurisdictionProvince, value) - } else if t.Equal(oidJurisdictionCountry) { - n.JurisdictionCountry = append(n.JurisdictionCountry, value) } } } @@ -171,39 +189,82 @@ func (n Name) appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentif return append(in, s) } -// String returns an RDNSequence as comma seperated list of -// AttributeTypeAndValues in canonical form. -func (seq RDNSequence) String() string { - out := make([]string, 0, len(seq)) - // An RDNSequence is effectively an [][]AttributeTypeAndValue - for _, atvSet := range seq { - for _, atv := range atvSet { - // Convert each individual AttributeTypeAndValue to X=Y - attrParts := make([]string, 0, 2) - oidString := atv.Type.String() - oidName, ok := oidDotNotationToNames[oidString] - if ok { - attrParts = append(attrParts, oidName.ShortName) - } else { - attrParts = append(attrParts, oidString) +// String returns a string representation of the sequence r, +// roughly following the RFC 2253 Distinguished Names syntax. +func (r RDNSequence) String() string { + s := "" + for i := 0; i < len(r); i++ { + idx := len(r) - 1 - i + if LegacyNameString { + idx = i + } + rdn := r[idx] + if i > 0 { + s += ", " + } + for j, tv := range rdn { + if j > 0 { + s += ", " } - switch value := atv.Value.(type) { - case string: - attrParts = append(attrParts, value) - case []byte: - attrParts = append(attrParts, string(value)) - default: - continue + + oidString := tv.Type.String() + var typeName string + if oidName, ok := oidDotNotationToNames[oidString]; ok { + typeName = oidName.ShortName } - attrString := strings.Join(attrParts, "=") - out = append(out, attrString) + if typeName == "" { + derBytes, err := asn1.Marshal(tv.Value) + if err == nil { + s += oidString + "=#" + hex.EncodeToString(derBytes) + continue // No value escaping necessary. + } + + typeName = oidString + } + + valueString := fmt.Sprint(tv.Value) + escaped := make([]rune, 0, len(valueString)) + + for k, c := range valueString { + escape := false + + switch c { + case ',', '+', '"', '\\', '<', '>', ';': + escape = true + + case ' ': + escape = k == 0 || k == len(valueString)-1 + + case '#': + escape = k == 0 + } + + if escape { + escaped = append(escaped, '\\', c) + } else { + escaped = append(escaped, c) + } + } + + s += typeName + "=" + string(escaped) } } - return strings.Join(out, ", ") + + return s } -// ToRDNSequence returns OriginalRDNS is populated. Otherwise, it builds an -// RDNSequence in canonical order. +// ToRDNSequence converts n into a single RDNSequence. The following +// attributes are encoded as multi-value RDNs: +// +// - Country +// - Organization +// - OrganizationalUnit +// - Locality +// - Province +// - StreetAddress +// - PostalCode +// +// Each ExtraNames entry is encoded as an individual RDN. func (n Name) ToRDNSequence() (ret RDNSequence) { if n.OriginalRDNS != nil { return n.OriginalRDNS @@ -228,19 +289,11 @@ func (n Name) ToRDNSequence() (ret RDNSequence) { if len(n.SerialNumber) > 0 { ret = n.appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber) } - ret = append(ret, n.ExtraNames) - return ret -} - -// oidInAttributeTypeAndValue returns whether a type with the given OID exists -// in atv. -func oidInAttributeTypeAndValue(oid asn1.ObjectIdentifier, atv []AttributeTypeAndValue) bool { - for _, a := range atv { - if a.Type.Equal(oid) { - return true - } + for _, atv := range n.ExtraNames { + ret = append(ret, []AttributeTypeAndValue{atv}) } - return false + + return ret } // CertificateList represents the ASN.1 structure of the same name. See RFC @@ -252,15 +305,34 @@ type CertificateList struct { SignatureValue asn1.BitString } -// HasExpired reports whether now is past the expiry time of certList. +// HasExpired reports whether certList should have been updated by now. func (certList *CertificateList) HasExpired(now time.Time) bool { - return now.After(certList.TBSCertList.NextUpdate) + return !now.Before(certList.TBSCertList.NextUpdate) } -// String returns a canonical representation of a DistinguishedName -func (n *Name) String() string { - seq := n.ToRDNSequence() - return seq.String() +// String returns the string form of n, roughly following +// the RFC 2253 Distinguished Names syntax. +func (n Name) String() string { + var rdns RDNSequence + // If there are no ExtraNames, surface the parsed value (all entries in + // Names) instead. + if n.ExtraNames == nil { + for _, atv := range n.Names { + t := atv.Type + if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 { + switch t[3] { + case 3, 5, 6, 7, 8, 9, 10, 11, 17: + // These attributes were already parsed into named fields. + continue + } + } + // Place non-standard parsed values at the beginning of the sequence + // so they will be at the end of the string. See Issue 39924. + rdns = append(rdns, []AttributeTypeAndValue{atv}) + } + } + rdns = append(rdns, n.ToRDNSequence()...) + return rdns.String() } // OtherName represents the ASN.1 structure of the same name. See RFC diff --git a/vendor/github.com/zmap/zcrypto/x509/qc_statements.go b/vendor/github.com/zmap/zcrypto/x509/qc_statements.go index 3adecd5c7..4eeb5d731 100644 --- a/vendor/github.com/zmap/zcrypto/x509/qc_statements.go +++ b/vendor/github.com/zmap/zcrypto/x509/qc_statements.go @@ -1,9 +1,10 @@ package x509 import ( - "encoding/asn1" "encoding/json" "errors" + + "github.com/zmap/zcrypto/encoding/asn1" ) type QCStatementASN struct { diff --git a/vendor/github.com/zmap/zcrypto/x509/sec1.go b/vendor/github.com/zmap/zcrypto/x509/sec1.go index 33f376c07..4ef211ff9 100644 --- a/vendor/github.com/zmap/zcrypto/x509/sec1.go +++ b/vendor/github.com/zmap/zcrypto/x509/sec1.go @@ -7,10 +7,11 @@ package x509 import ( "crypto/ecdsa" "crypto/elliptic" - "encoding/asn1" "errors" "fmt" "math/big" + + "github.com/zmap/zcrypto/encoding/asn1" ) const ecPrivKeyVersion = 1 diff --git a/vendor/github.com/zmap/zcrypto/x509/tor_service_descriptor.go b/vendor/github.com/zmap/zcrypto/x509/tor_service_descriptor.go index 366bd9591..27220f874 100644 --- a/vendor/github.com/zmap/zcrypto/x509/tor_service_descriptor.go +++ b/vendor/github.com/zmap/zcrypto/x509/tor_service_descriptor.go @@ -1,7 +1,7 @@ package x509 import ( - "encoding/asn1" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509/pkix" ) diff --git a/vendor/github.com/zmap/zcrypto/x509/x509.go b/vendor/github.com/zmap/zcrypto/x509/x509.go index 160fca3df..8057b0b0a 100644 --- a/vendor/github.com/zmap/zcrypto/x509/x509.go +++ b/vendor/github.com/zmap/zcrypto/x509/x509.go @@ -27,7 +27,6 @@ import ( _ "crypto/sha1" _ "crypto/sha256" _ "crypto/sha512" - "encoding/asn1" "encoding/pem" "errors" "fmt" @@ -36,9 +35,9 @@ import ( "strconv" "time" - "github.com/zmap/zcrypto/dsa" - "github.com/weppos/publicsuffix-go/publicsuffix" + "github.com/zmap/zcrypto/dsa" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509/ct" "github.com/zmap/zcrypto/x509/pkix" "golang.org/x/crypto/ed25519" @@ -838,6 +837,10 @@ type Certificate struct { PermittedX400Addresses []GeneralSubtreeRaw ExcludedX400Addresses []GeneralSubtreeRaw + // FailedToParseNames contains values that are failed to parse, + // without returning an error. + FailedToParseNames []asn1.RawValue + // CRL Distribution Points CRLDistributionPoints []string @@ -1298,11 +1301,15 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{ return nil, errors.New("x509: trailing data after RSA public key") } - if p.N.Sign() <= 0 { - return nil, errors.New("x509: RSA modulus is not a positive number") - } - if p.E <= 0 { - return nil, errors.New("x509: RSA public exponent is not a positive number") + // ZCrypto: Allow to parse + if !asn1.AllowPermissiveParsing { + + if p.N.Sign() <= 0 { + return nil, errors.New("x509: RSA modulus is not a positive number") + } + if p.E <= 0 { + return nil, errors.New("x509: RSA public exponent is not a positive number") + } } pub := &rsa.PublicKey{ @@ -1442,7 +1449,7 @@ func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddre return } -func parseGeneralNames(value []byte) (otherNames []pkix.OtherName, dnsNames, emailAddresses, URIs []string, directoryNames []pkix.Name, ediPartyNames []pkix.EDIPartyName, ipAddresses []net.IP, registeredIDs []asn1.ObjectIdentifier, err error) { +func parseGeneralNames(value []byte) (otherNames []pkix.OtherName, dnsNames, emailAddresses, URIs []string, directoryNames []pkix.Name, ediPartyNames []pkix.EDIPartyName, ipAddresses []net.IP, registeredIDs []asn1.ObjectIdentifier, failedToParse []asn1.RawValue, err error) { // RFC 5280, 4.2.1.6 // SubjectAltName ::= GeneralNames @@ -1478,8 +1485,13 @@ func parseGeneralNames(value []byte) (otherNames []pkix.OtherName, dnsNames, ema switch v.Tag { case 0: var oName pkix.OtherName - _, err = asn1.UnmarshalWithParams(v.FullBytes, &oName, "tag:0") - if err != nil { + _, perr := asn1.UnmarshalWithParams(v.FullBytes, &oName, "tag:0") + if perr != nil { + if asn1.AllowPermissiveParsing { + failedToParse = append(failedToParse, v) + continue + } + err = perr return } otherNames = append(otherNames, oName) @@ -1489,8 +1501,13 @@ func parseGeneralNames(value []byte) (otherNames []pkix.OtherName, dnsNames, ema dnsNames = append(dnsNames, string(v.Bytes)) case 4: var rdn pkix.RDNSequence - _, err = asn1.Unmarshal(v.Bytes, &rdn) - if err != nil { + _, perr := asn1.Unmarshal(v.Bytes, &rdn) + if perr != nil { + if asn1.AllowPermissiveParsing { + failedToParse = append(failedToParse, v) + continue + } + err = perr return } var dir pkix.Name @@ -1498,8 +1515,13 @@ func parseGeneralNames(value []byte) (otherNames []pkix.OtherName, dnsNames, ema directoryNames = append(directoryNames, dir) case 5: var ediName pkix.EDIPartyName - _, err = asn1.UnmarshalWithParams(v.FullBytes, &ediName, "tag:5") - if err != nil { + _, perr := asn1.UnmarshalWithParams(v.FullBytes, &ediName, "tag:5") + if perr != nil { + if asn1.AllowPermissiveParsing { + failedToParse = append(failedToParse, v) + continue + } + err = perr return } ediPartyNames = append(ediPartyNames, ediName) @@ -1510,13 +1532,22 @@ func parseGeneralNames(value []byte) (otherNames []pkix.OtherName, dnsNames, ema case net.IPv4len, net.IPv6len: ipAddresses = append(ipAddresses, v.Bytes) default: - err = errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes))) - return + if asn1.AllowPermissiveParsing { + failedToParse = append(failedToParse, v) + } else { + err = errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes))) + return + } } case 8: var id asn1.ObjectIdentifier - _, err = asn1.UnmarshalWithParams(v.FullBytes, &id, "tag:8") - if err != nil { + _, perr := asn1.UnmarshalWithParams(v.FullBytes, &id, "tag:8") + if perr != nil { + if asn1.AllowPermissiveParsing { + failedToParse = append(failedToParse, v) + continue + } + err = perr return } registeredIDs = append(registeredIDs, id) @@ -1656,7 +1687,9 @@ func parseCertificate(in *certificate) (*Certificate, error) { continue } case 17: - out.OtherNames, out.DNSNames, out.EmailAddresses, out.URIs, out.DirectoryNames, out.EDIPartyNames, out.IPAddresses, out.RegisteredIDs, err = parseGeneralNames(e.Value) + out.OtherNames, out.DNSNames, out.EmailAddresses, + out.URIs, out.DirectoryNames, out.EDIPartyNames, + out.IPAddresses, out.RegisteredIDs, out.FailedToParseNames, err = parseGeneralNames(e.Value) if err != nil { return nil, err } @@ -1667,7 +1700,9 @@ func parseCertificate(in *certificate) (*Certificate, error) { // If we didn't parse any of the names then we // fall through to the critical check below. case 18: - out.IANOtherNames, out.IANDNSNames, out.IANEmailAddresses, out.IANURIs, out.IANDirectoryNames, out.IANEDIPartyNames, out.IANIPAddresses, out.IANRegisteredIDs, err = parseGeneralNames(e.Value) + out.IANOtherNames, out.IANDNSNames, out.IANEmailAddresses, + out.IANURIs, out.IANDirectoryNames, out.IANEDIPartyNames, + out.IANIPAddresses, out.IANRegisteredIDs, out.FailedToParseNames, err = parseGeneralNames(e.Value) if err != nil { return nil, err } @@ -1735,7 +1770,9 @@ func parseCertificate(in *certificate) (*Certificate, error) { ip := net.IPNet{IP: subtree.Value.Bytes[:net.IPv6len], Mask: subtree.Value.Bytes[net.IPv6len:]} out.PermittedIPAddresses = append(out.PermittedIPAddresses, GeneralSubtreeIP{Data: ip, Max: subtree.Max, Min: subtree.Min}) default: - return out, errors.New("x509: certificate name constraint contained IP address range of length " + strconv.Itoa(len(subtree.Value.Bytes))) + if !asn1.AllowPermissiveParsing { + return out, errors.New("x509: certificate name constraint contained IP address range of length " + strconv.Itoa(len(subtree.Value.Bytes))) + } } case 8: var id asn1.ObjectIdentifier @@ -1780,7 +1817,9 @@ func parseCertificate(in *certificate) (*Certificate, error) { ip := net.IPNet{IP: subtree.Value.Bytes[:net.IPv6len], Mask: subtree.Value.Bytes[net.IPv6len:]} out.ExcludedIPAddresses = append(out.ExcludedIPAddresses, GeneralSubtreeIP{Data: ip, Max: subtree.Max, Min: subtree.Min}) default: - return out, errors.New("x509: certificate name constraint contained IP address range of length " + strconv.Itoa(len(subtree.Value.Bytes))) + if !asn1.AllowPermissiveParsing { + return out, errors.New("x509: certificate name constraint contained IP address range of length " + strconv.Itoa(len(subtree.Value.Bytes))) + } } case 8: var id asn1.ObjectIdentifier @@ -1860,7 +1899,10 @@ func parseCertificate(in *certificate) (*Certificate, error) { var keyUsage []asn1.ObjectIdentifier _, err = asn1.Unmarshal(e.Value, &keyUsage) if err != nil { - return nil, err + if !asn1.AllowPermissiveParsing { + return nil, err + } + continue } for _, u := range keyUsage { @@ -1907,25 +1949,31 @@ func parseCertificate(in *certificate) (*Certificate, error) { cpsURIOID := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 1} if qualifier.PolicyQualifierId.Equal(userNoticeOID) { var un userNotice - if _, err = asn1.Unmarshal(qualifier.Qualifier.FullBytes, &un); err != nil { + _, err := asn1.Unmarshal(qualifier.Qualifier.FullBytes, &un) + if err != nil && !asn1.AllowPermissiveParsing { return nil, err } - if len(un.ExplicitText.Bytes) != 0 { - out.ExplicitTexts[i] = append(out.ExplicitTexts[i], un.ExplicitText) - out.ParsedExplicitTexts[i] = append(out.ParsedExplicitTexts[i], string(un.ExplicitText.Bytes)) - } - if un.NoticeRef.Organization.Bytes != nil || un.NoticeRef.NoticeNumbers != nil { - out.NoticeRefOrgnization[i] = append(out.NoticeRefOrgnization[i], un.NoticeRef.Organization) - out.NoticeRefNumbers[i] = append(out.NoticeRefNumbers[i], un.NoticeRef.NoticeNumbers) - out.ParsedNoticeRefOrganization[i] = append(out.ParsedNoticeRefOrganization[i], string(un.NoticeRef.Organization.Bytes)) + if err == nil { + if len(un.ExplicitText.Bytes) != 0 { + out.ExplicitTexts[i] = append(out.ExplicitTexts[i], un.ExplicitText) + out.ParsedExplicitTexts[i] = append(out.ParsedExplicitTexts[i], string(un.ExplicitText.Bytes)) + } + if un.NoticeRef.Organization.Bytes != nil || un.NoticeRef.NoticeNumbers != nil { + out.NoticeRefOrgnization[i] = append(out.NoticeRefOrgnization[i], un.NoticeRef.Organization) + out.NoticeRefNumbers[i] = append(out.NoticeRefNumbers[i], un.NoticeRef.NoticeNumbers) + out.ParsedNoticeRefOrganization[i] = append(out.ParsedNoticeRefOrganization[i], string(un.NoticeRef.Organization.Bytes)) + } } } if qualifier.PolicyQualifierId.Equal(cpsURIOID) { var cpsURIRaw asn1.RawValue - if _, err = asn1.Unmarshal(qualifier.Qualifier.FullBytes, &cpsURIRaw); err != nil { + _, err = asn1.Unmarshal(qualifier.Qualifier.FullBytes, &cpsURIRaw) + if err != nil && !asn1.AllowPermissiveParsing { return nil, err } - out.CPSuri[i] = append(out.CPSuri[i], string(cpsURIRaw.Bytes)) + if err == nil { + out.CPSuri[i] = append(out.CPSuri[i], string(cpsURIRaw.Bytes)) + } } } } @@ -1974,7 +2022,9 @@ func parseCertificate(in *certificate) (*Certificate, error) { out.IsPrecert = true continue } else { - return nil, UnhandledCriticalExtension{e.Id, "Malformed precert poison"} + if !asn1.AllowPermissiveParsing { + return nil, UnhandledCriticalExtension{e.Id, "Malformed precert poison"} + } } } else if e.Id.Equal(oidBRTorServiceDescriptor) { descs, err := parseTorServiceDescriptorSyntax(e) diff --git a/vendor/github.com/zmap/zlint/v3/lint/base.go b/vendor/github.com/zmap/zlint/v3/lint/base.go index efecfa97e..c5afe8a31 100644 --- a/vendor/github.com/zmap/zlint/v3/lint/base.go +++ b/vendor/github.com/zmap/zlint/v3/lint/base.go @@ -15,6 +15,7 @@ package lint */ import ( + "fmt" "time" "github.com/zmap/zcrypto/x509" @@ -22,10 +23,7 @@ import ( ) // LintInterface is implemented by each Lint. -type LintInterface interface { - // Initialize runs once per-lint. It is called during RegisterLint(). - Initialize() error - +type LintInterface interface { //nolint:revive // CheckApplies runs once per certificate. It returns true if the Lint should // run on the given certificate. If CheckApplies returns false, the Lint // result is automatically set to NA without calling CheckEffective() or @@ -37,6 +35,11 @@ type LintInterface interface { Execute(c *x509.Certificate) *LintResult } +// Configurable lints return a pointer into a struct that they wish to receive their configuration into. +type Configurable interface { + Configure() interface{} +} + // A Lint struct represents a single lint, e.g. // "e_basic_constraints_not_critical". It contains an implementation of LintInterface. type Lint struct { @@ -58,20 +61,31 @@ type Lint struct { // Lints automatically returns NE for all certificates where CheckApplies() is // true but with NotBefore < EffectiveDate. This check is bypassed if - // EffectiveDate is zero. + // EffectiveDate is zero. Please see CheckEffective for more information. EffectiveDate time.Time `json:"-"` - // The implementation of the lint logic. - Lint LintInterface `json:"-"` + // Lints automatically returns NE for all certificates where CheckApplies() is + // true but with NotBefore >= IneffectiveDate. This check is bypassed if + // IneffectiveDate is zero. Please see CheckEffective for more information. + IneffectiveDate time.Time `json:"-"` + + // A constructor which returns the implementation of the lint logic. + Lint func() LintInterface `json:"-"` } -// CheckEffective returns true if c was issued on or after the EffectiveDate. If -// EffectiveDate is zero, CheckEffective always returns true. +// CheckEffective returns true if c was issued on or after the EffectiveDate +// AND before (but not on) the Ineffective date. That is, CheckEffective +// returns true if... +// +// c.NotBefore in [EffectiveDate, IneffectiveDate) +// +// If EffectiveDate is zero, then only IneffectiveDate is checked. Conversely, +// if IneffectiveDate is zero then only EffectiveDate is checked. If both EffectiveDate +// and IneffectiveDate are zero then CheckEffective always returns true. func (l *Lint) CheckEffective(c *x509.Certificate) bool { - if l.EffectiveDate.IsZero() || !l.EffectiveDate.After(c.NotBefore) { - return true - } - return false + onOrAfterEffective := l.EffectiveDate.IsZero() || util.OnOrAfter(c.NotBefore, l.EffectiveDate) + strictlyBeforeIneffective := l.IneffectiveDate.IsZero() || c.NotBefore.Before(l.IneffectiveDate) + return onOrAfterEffective && strictlyBeforeIneffective } // Execute runs the lint against a certificate. For lints that are @@ -79,18 +93,38 @@ func (l *Lint) CheckEffective(c *x509.Certificate) bool { // if they are within the purview of the BRs. See LintInterface for details // about the other methods called. The ordering is as follows: // +// Configure() ----> only if the lint implements Configurable // CheckApplies() // CheckEffective() // Execute() -func (l *Lint) Execute(cert *x509.Certificate) *LintResult { +func (l *Lint) Execute(cert *x509.Certificate, config Configuration) *LintResult { if l.Source == CABFBaselineRequirements && !util.IsServerAuthCert(cert) { return &LintResult{Status: NA} } - if !l.Lint.CheckApplies(cert) { + return l.execute(l.Lint(), cert, config) +} + +func (l *Lint) execute(lint LintInterface, cert *x509.Certificate, config Configuration) *LintResult { + configurable, ok := lint.(Configurable) + if ok { + err := config.Configure(configurable.Configure(), l.Name) + if err != nil { + details := fmt.Sprintf( + "A fatal error occurred while attempting to configure %s. Please visit the [%s] section of "+ + "your provided configuration and compare it with the output of `zlint -exampleConfig`. Error: %s", + l.Name, + l.Name, + err.Error()) + return &LintResult{ + Status: Fatal, + Details: details} + } + } + if !lint.CheckApplies(cert) { return &LintResult{Status: NA} } else if !l.CheckEffective(cert) { return &LintResult{Status: NE} } - res := l.Lint.Execute(cert) + res := lint.Execute(cert) return res } diff --git a/vendor/github.com/zmap/zlint/v3/lint/configuration.go b/vendor/github.com/zmap/zlint/v3/lint/configuration.go new file mode 100644 index 000000000..d60f3aec7 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lint/configuration.go @@ -0,0 +1,248 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package lint + +import ( + "fmt" + "io" + "os" + "reflect" + "strings" + + "github.com/pelletier/go-toml" +) + +// Configuration is a ZLint configuration which serves as a target +// to hold the full TOML tree that is a physical ZLint configuration./ +type Configuration struct { + tree *toml.Tree +} + +// Configure attempts to deserialize the provided namespace into the provided empty interface. +// +// For example, let's say that the name of your lint is MyLint, then the configuration +// file might look something like the following... +// +// ``` +// [MyLint] +// A = 1 +// B = 2 +// ``` +// +// Given this, our target struct may look like the following... +// +// ``` +// type MytLint struct { +// A int +// B uint +// } +// ``` +// +// So deserializing into this struct would look like... +// +// ``` +// configuration.Configure(&myLint, myLint.Name()) +// ``` +func (c Configuration) Configure(lint interface{}, namespace string) error { + return c.deserializeConfigInto(lint, namespace) +} + +// NewConfig attempts to instantiate a configuration by consuming the contents of the provided reader. +// +// The contents of the provided reader MUST be in a valid TOML format. The caller of this function +// is responsible for closing the reader, if appropriate. +func NewConfig(r io.Reader) (Configuration, error) { + tree, err := toml.LoadReader(r) + if err != nil { + return Configuration{}, err + } + return Configuration{tree}, nil +} + +// NewConfigFromFile attempts to instantiate a configuration from the provided filesystem path. +// +// The file pointed to by `path` MUST be valid TOML file. If `path` is the empty string then +// an empty configuration is returned. +func NewConfigFromFile(path string) (Configuration, error) { + if path == "" { + return NewEmptyConfig(), nil + } + f, err := os.Open(path) + if err != nil { + return Configuration{}, fmt.Errorf("failed to open the provided configuration at %s. Error: %s", path, err.Error()) + } + defer f.Close() + return NewConfig(f) +} + +// NewConfigFromString attempts to instantiate a configuration from the provided string. +// +// The provided string MUST be in a valid TOML format. +func NewConfigFromString(config string) (Configuration, error) { + return NewConfig(strings.NewReader(config)) +} + +// NewEmptyConfig returns a configuration that is backed by an entirely empty TOML tree. +// +// This is useful if no particular configuration is set at all by the user of ZLint as +// any attempt to resolve a namespace in `deserializeConfigInto` fails and thus results +// in all defaults for all lints being maintained. +func NewEmptyConfig() Configuration { + cfg, _ := NewConfigFromString("") + return cfg +} + +// deserializeConfigInto deserializes the section labeled by the provided `namespace` +// into the provided target `interface{}`. +// +// For example, given the following configuration... +// +// ``` +// [e_some_lint] +// field = 1 +// flag = false +// +// [w_some_other_lint] +// is_web_pki = true +// ``` +// +// And the following struct definition... +// +// ``` +// type SomeOtherLint { +// IsWebPKI bool `toml:"is_web_pki"` +// } +// ``` +// +// Then the invocation of this function should be... +// +// ``` +// lint := &SomeOtherLint{} +// deserializeConfigInto(lint, "w_some_other_lint") +// ``` +// +// If there is no such namespace found in this configuration then provided the namespace specific data encoded +// within `target` is left unmodified. However, configuration of higher scoped fields will still be attempted. +func (c Configuration) deserializeConfigInto(target interface{}, namespace string) error { + if tree := c.tree.Get(namespace); tree != nil { + err := tree.(*toml.Tree).Unmarshal(target) + if err != nil { + return err + } + } + return c.resolveHigherScopedReferences(target) +} + +// resolveHigherScopeReferences takes in an interface{} value and attempts to +// find any field within its inner value that is either a struct or a pointer +// to a struct that is one of our global configurable types. If such a field +// exists then that higher scoped configuration will be copied into the value +// held by the provided interface{}. +// +// This procedure is recursive. +func (c Configuration) resolveHigherScopedReferences(i interface{}) error { + value := reflect.Indirect(reflect.ValueOf(i)) + if value.Kind() != reflect.Struct { + // Our target higher scoped configurations are either structs + // or are fields of structs. Any other Kind simply cannot + // be a target for deserialization here. For example, an interface + // does not make sense since an interface cannot have fields nor + // are any of our higher scoped configurations interfaces themselves. + // + // For a comprehensive list of Kinds, please see `type.go` in the `reflect` package. + return nil + } + // Iterate through every field within the struct held by the provided interface{}. + // If the field is either one of our higher scoped configurations (or a pointer to one) + // then deserialize that higher scoped configuration into that field. If the field + // is not one of our higher scoped configurations then recursively pass it to this function + // in an attempt to resolve it. + for field := 0; field < value.NumField(); field++ { + field := value.Field(field) + if !field.CanSet() { + // This skips fields that are either not addressable or are private data members. + continue + } + if _, ok := field.Interface().(GlobalConfiguration); ok { + // It's one of our higher level configurations, so we need to pull out a different + // subtree from our TOML document and inject it int othis struct. + config := initializePtr(field).Interface().(GlobalConfiguration) + err := c.deserializeConfigInto(config, config.namespace()) + if err != nil { + return err + } + field.Set(reflect.ValueOf(config)) + } else { + // This is just another member of some kind that is not one of our higher level configurations. + err := c.resolveHigherScopedReferences(field.Addr().Interface()) + if err != nil { + return err + } + } + } + return nil +} + +// stripGlobalsFromExample takes in an interface{} and returns a mapping that is +// the provided struct but with all references to higher scoped configurations scrubbed. +// +// This is intended only for use when constructing an example configuration file via the +// `-exampleConfig` flag. This is to avoid visually redundant, and possibly incorrect, +// examples such as the following... +// +// ``` +// [Global] +// something = false +// something_else = "" +// +// [e_some_lint] +// my_data = 0 +// my_flag = false +// globals = { something = false, something_else = "" } +// ``` +// +// Notice how the above has Global effectively listed twice - once externally and once internally, which +// defeats the whole point of having globals to begin with. +func stripGlobalsFromExample(i interface{}) interface{} { + value := reflect.Indirect(reflect.ValueOf(i)) + if value.Kind() != reflect.Struct { + return i + } + m := map[string]interface{}{} + for field := 0; field < value.NumField(); field++ { + name := value.Type().Field(field).Name + field := value.Field(field) + if !field.CanInterface() { + continue + } + if _, ok := field.Interface().(GlobalConfiguration); ok { + continue + } + field = initializePtr(field) + m[name] = stripGlobalsFromExample(field.Interface()) + } + return m +} + +// initializePtr checks whether the provided reflect.Value is a pointer type and is nil. If so, it returns +// a new reflect.Value that has an initialized pointer. +// +// If the provided reflect.Value is not a nil pointer, then the original reflect.Value is returned. +func initializePtr(value reflect.Value) reflect.Value { + if value.Kind() == reflect.Ptr && value.IsZero() { + return reflect.New(value.Type().Elem()) + } + return value +} diff --git a/vendor/github.com/zmap/zlint/v3/lint/global_configurations.go b/vendor/github.com/zmap/zlint/v3/lint/global_configurations.go new file mode 100644 index 000000000..826734ed3 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lint/global_configurations.go @@ -0,0 +1,155 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package lint + +// Global is what one would intuitive think of as being the global context of the configuration file. +// That is, given the following configuration... +// +// some_flag = true +// some_string = "the greatest song in the world" +// +// [e_some_lint] +// some_other_flag = false +// +// The fields `some_flag` and `some_string` will be targeted to land into this struct. +type Global struct{} + +func (g Global) namespace() string { + return "Global" +} + +// RFC5280Config is the higher scoped configuration which services as the deserialization target for... +// +// [RFC5280Config] +// ... +// ... +type RFC5280Config struct{} + +func (r RFC5280Config) namespace() string { + return "RFC5280Config" +} + +// RFC5480Config is the higher scoped configuration which services as the deserialization target for... +// +// [RFC5480Config] +// ... +// ... +type RFC5480Config struct{} + +func (r RFC5480Config) namespace() string { + return "RFC5480Config" +} + +// RFC5891Config is the higher scoped configuration which services as the deserialization target for... +// +// [RFC5891Config] +// ... +// ... +type RFC5891Config struct{} + +func (r RFC5891Config) namespace() string { + return "RFC5891Config" +} + +// CABFBaselineRequirementsConfig is the higher scoped configuration which services as the deserialization target for... +// +// [CABFBaselineRequirementsConfig] +// ... +// ... +type CABFBaselineRequirementsConfig struct{} + +func (c CABFBaselineRequirementsConfig) namespace() string { + return "CABFBaselineRequirementsConfig" +} + +// CABFEVGuidelinesConfig is the higher scoped configuration which services as the deserialization target for... +// +// [CABFEVGuidelinesConfig] +// ... +// ... +type CABFEVGuidelinesConfig struct{} + +func (c CABFEVGuidelinesConfig) namespace() string { + return "CABFEVGuidelinesConfig" +} + +// MozillaRootStorePolicyConfig is the higher scoped configuration which services as the deserialization target for... +// +// [MozillaRootStorePolicyConfig] +// ... +// ... +type MozillaRootStorePolicyConfig struct{} + +func (m MozillaRootStorePolicyConfig) namespace() string { + return "MozillaRootStorePolicyConfig" +} + +// AppleRootStorePolicyConfig is the higher scoped configuration which services as the deserialization target for... +// +// [AppleRootStorePolicyConfig] +// ... +// ... +type AppleRootStorePolicyConfig struct{} + +func (a AppleRootStorePolicyConfig) namespace() string { + return "AppleRootStorePolicyConfig" +} + +// CommunityConfig is the higher scoped configuration which services as the deserialization target for... +// +// [CommunityConfig] +// ... +// ... +type CommunityConfig struct{} + +func (c CommunityConfig) namespace() string { + return "CommunityConfig" +} + +// EtsiEsiConfig is the higher scoped configuration which services as the deserialization target for... +// +// [EtsiEsiConfig] +// ... +// ... +type EtsiEsiConfig struct{} + +func (e EtsiEsiConfig) namespace() string { + return "EtsiEsiConfig" +} + +// GlobalConfiguration acts both as an interface that can be used to obtain the TOML namespace of configuration +// as well as a way to mark a fielf in a struct as one of our own, higher scoped, configurations. +// +// the interface itself is public, however the singular `namespace` method is package private, meaning that +// normal lint struct cannot accidentally implement this. +type GlobalConfiguration interface { + namespace() string +} + +// defaultGlobals are used by other locations in the codebase that may want to iterate over all currently know +// global configuration types. Most notably, Registry.DefaultConfiguration uses it because it wants to print +// out a TOML document that is the full default configuration for ZLint. +var defaultGlobals = []GlobalConfiguration{ + &Global{}, + &CABFBaselineRequirementsConfig{}, + &RFC5280Config{}, + &RFC5480Config{}, + &RFC5891Config{}, + &CABFBaselineRequirementsConfig{}, + &CABFEVGuidelinesConfig{}, + &MozillaRootStorePolicyConfig{}, + &AppleRootStorePolicyConfig{}, + &CommunityConfig{}, +} diff --git a/vendor/github.com/zmap/zlint/v3/lint/registration.go b/vendor/github.com/zmap/zlint/v3/lint/registration.go index 694ae1faa..2d6d96939 100644 --- a/vendor/github.com/zmap/zlint/v3/lint/registration.go +++ b/vendor/github.com/zmap/zlint/v3/lint/registration.go @@ -15,6 +15,7 @@ package lint import ( + "bytes" "encoding/json" "errors" "fmt" @@ -23,6 +24,8 @@ import ( "sort" "strings" "sync" + + "github.com/pelletier/go-toml" ) // FilterOptions is a struct used by Registry.Filter to create a sub registry @@ -75,6 +78,8 @@ type Registry interface { // Sources returns a SourceList of registered LintSources. The list is not // sorted but can be sorted by the caller with sort.Sort() if required. Sources() SourceList + // @TODO + DefaultConfiguration() ([]byte, error) // ByName returns a pointer to the registered lint with the given name, or nil // if there is no such lint registered in the registry. ByName(name string) *Lint @@ -87,6 +92,8 @@ type Registry interface { // WriteJSON writes a description of each registered lint as // a JSON object, one object per line, to the provided writer. WriteJSON(w io.Writer) + SetConfiguration(config Configuration) + GetConfiguration() Configuration } // registryImpl implements the Registry interface to provide a global collection @@ -102,6 +109,7 @@ type registryImpl struct { // lintsBySource is a map of all registered lints by source category. Lints // are added to the lintsBySource map by RegisterLint. lintsBySource map[LintSource][]*Lint + configuration Configuration } var ( @@ -127,29 +135,16 @@ func (e errDuplicateName) Error() string { e.lintName) } -// errBadInit is returned from registry.Register if the provided lint's -// Initialize function returned an error. -type errBadInit struct { - lintName string - err error -} - -func (e errBadInit) Error() string { - return fmt.Sprintf( - "failed to register lint with name %q - failed to Initialize: %q", - e.lintName, e.err) -} - // register adds the provided lint to the Registry. If initialize is true then // the lint's Initialize() function will be called before registering the lint. // // An error is returned if the lint or lint's Lint pointer is nil, if the Lint // has an empty Name or if the Name was previously registered. -func (r *registryImpl) register(l *Lint, initialize bool) error { +func (r *registryImpl) register(l *Lint) error { if l == nil { return errNilLint } - if l.Lint == nil { + if l.Lint() == nil { return errNilLintPtr } if l.Name == "" { @@ -158,11 +153,6 @@ func (r *registryImpl) register(l *Lint, initialize bool) error { if existing := r.ByName(l.Name); existing != nil { return &errDuplicateName{l.Name} } - if initialize { - if err := l.Lint.Initialize(); err != nil { - return &errBadInit{l.Name, err} - } - } r.Lock() defer r.Unlock() r.lintNames = append(r.lintNames, l.Name) @@ -243,6 +233,7 @@ func sourceListToMap(sources SourceList) map[LintSource]bool { // // FilterOptions are applied in the following order of precedence: // ExcludeSources > IncludeSources > NameFilter > ExcludeNames > IncludeNames +//nolint:cyclop func (r *registryImpl) Filter(opts FilterOptions) (Registry, error) { // If there's no filtering to be done, return the existing Registry. if opts.Empty() { @@ -250,6 +241,7 @@ func (r *registryImpl) Filter(opts FilterOptions) (Registry, error) { } filteredRegistry := NewRegistry() + filteredRegistry.SetConfiguration(r.configuration) sourceExcludes := sourceListToMap(opts.ExcludeSources) sourceIncludes := sourceListToMap(opts.IncludeSources) @@ -290,7 +282,7 @@ func (r *registryImpl) Filter(opts FilterOptions) (Registry, error) { // when adding lints to a filtered registry we do not want Initialize() to // be called a second time, so provide false as the initialize argument. - if err := filteredRegistry.register(l, false); err != nil { + if err := filteredRegistry.register(l); err != nil { return nil, err } } @@ -304,22 +296,83 @@ func (r *registryImpl) WriteJSON(w io.Writer) { enc := json.NewEncoder(w) enc.SetEscapeHTML(false) for _, name := range r.Names() { + //nolint:errchkjson _ = enc.Encode(r.ByName(name)) } } +func (r *registryImpl) SetConfiguration(cfg Configuration) { + r.configuration = cfg +} + +func (r *registryImpl) GetConfiguration() Configuration { + return r.configuration +} + +// DefaultConfiguration returns a serialized copy of the default configuration for ZLint. +// +// This is especially useful combined with the -exampleConfig CLI argument which prints this +// to stdout. In this way, operators can quickly see what lints are configurable and what their +// fields are without having to dig through documentation or, even worse, code. +func (r *registryImpl) DefaultConfiguration() ([]byte, error) { + return r.defaultConfiguration(defaultGlobals) +} + +// defaultConfiguration is abstracted out to a private function that takes in a slice of globals +// for the sake of making unit testing easier. +func (r *registryImpl) defaultConfiguration(globals []GlobalConfiguration) ([]byte, error) { + configurables := map[string]interface{}{} + for name, lint := range r.lintsByName { + switch configurable := lint.Lint().(type) { + case Configurable: + configurables[name] = stripGlobalsFromExample(configurable.Configure()) + default: + } + } + for _, config := range globals { + switch config.(type) { + case *Global: + // We're just using stripGlobalsFromExample here as a convenient way to + // recursively turn the `Global` struct type into a map. + // + // We have to do this because if we simply followed the pattern above and did... + // + // configurables["Global"] = &Global{} + // + // ...then we would end up with a [Global] section in the resulting configuration, + // which is not what we are looking for (we simply want it to be flattened out into + // the top most context of the configuration file). + for k, v := range stripGlobalsFromExample(config).(map[string]interface{}) { + configurables[k] = v + } + default: + configurables[config.namespace()] = config + } + + } + w := &bytes.Buffer{} + err := toml.NewEncoder(w).Indentation("").CompactComments(true).Encode(configurables) + if err != nil { + return nil, err + } + return w.Bytes(), nil +} + // NewRegistry constructs a Registry implementation that can be used to register // lints. +//nolint:revive func NewRegistry() *registryImpl { - return ®istryImpl{ + registry := ®istryImpl{ lintsByName: make(map[string]*Lint), lintsBySource: make(map[LintSource][]*Lint), } + registry.SetConfiguration(NewEmptyConfig()) + return registry } // globalRegistry is the Registry used by all loaded lints that call // RegisterLint(). -var globalRegistry *registryImpl = NewRegistry() +var globalRegistry = NewRegistry() // RegisterLint must be called once for each lint to be executed. Normally, // RegisterLint is called from the Go init() function of a lint implementation. @@ -335,7 +388,7 @@ func RegisterLint(l *Lint) { // RegisterLint always sets initialize to true. It's assumed this is called by // the package init() functions and therefore must be doing the first // initialization of a lint. - if err := globalRegistry.register(l, true); err != nil { + if err := globalRegistry.register(l); err != nil { panic(fmt.Sprintf("RegisterLint error: %v\n", err.Error())) } } diff --git a/vendor/github.com/zmap/zlint/v3/lint/result.go b/vendor/github.com/zmap/zlint/v3/lint/result.go index 71b43be9c..726d5743f 100644 --- a/vendor/github.com/zmap/zlint/v3/lint/result.go +++ b/vendor/github.com/zmap/zlint/v3/lint/result.go @@ -21,6 +21,7 @@ import ( ) // LintStatus is an enum returned by lints inside of a LintResult. +//nolint:revive type LintStatus int // Known LintStatus values diff --git a/vendor/github.com/zmap/zlint/v3/lint/source.go b/vendor/github.com/zmap/zlint/v3/lint/source.go index 226a7c0d5..b978ea8b6 100644 --- a/vendor/github.com/zmap/zlint/v3/lint/source.go +++ b/vendor/github.com/zmap/zlint/v3/lint/source.go @@ -7,7 +7,7 @@ import ( ) /* - * ZLint Copyright 2021 Regents of the University of Michigan + * ZLint Copyright 2022 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -22,13 +22,16 @@ import ( // LintSource is a type representing a known lint source that lints cite // requirements from. +//nolint:revive type LintSource string const ( UnknownLintSource LintSource = "Unknown" + RFC3279 LintSource = "RFC3279" RFC5280 LintSource = "RFC5280" RFC5480 LintSource = "RFC5480" RFC5891 LintSource = "RFC5891" + RFC8813 LintSource = "RFC8813" CABFBaselineRequirements LintSource = "CABF_BR" CABFEVGuidelines LintSource = "CABF_EV" MozillaRootStorePolicy LintSource = "Mozilla" diff --git a/vendor/github.com/zmap/zlint/v3/lints/apple/lint_ct_sct_policy_count_unsatisfied.go b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_ct_sct_policy_count_unsatisfied.go index cf77a6f20..37f4dc041 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/apple/lint_ct_sct_policy_count_unsatisfied.go +++ b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_ct_sct_policy_count_unsatisfied.go @@ -33,15 +33,16 @@ func init() { Citation: "https://support.apple.com/en-us/HT205280", Source: lint.AppleRootStorePolicy, EffectiveDate: util.AppleCTPolicyDate, - Lint: &sctPolicyCount{}, + Lint: NewSctPolicyCount, }) } -// Initialize for a sctPolicyCount instance does nothing. -func (l *sctPolicyCount) Initialize() error { - return nil +func NewSctPolicyCount() lint.LintInterface { + return &sctPolicyCount{} } +// Initialize for a sctPolicyCount instance does nothing. + // CheckApplies returns true for any subscriber certificates that are not // precertificates (e.g. that do not have the CT poison extension defined in RFC // 6962. diff --git a/vendor/github.com/zmap/zlint/v3/lints/apple/lint_e_server_cert_valid_time_longer_than_398_days.go b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_e_server_cert_valid_time_longer_than_398_days.go index b6077bff7..0902bb176 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/apple/lint_e_server_cert_valid_time_longer_than_398_days.go +++ b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_e_server_cert_valid_time_longer_than_398_days.go @@ -32,12 +32,12 @@ func init() { Citation: "https://support.apple.com/en-us/HT211025", Source: lint.AppleRootStorePolicy, EffectiveDate: util.AppleReducedLifetimeDate, - Lint: &serverCertValidityTooLong{}, + Lint: NewServerCertValidityTooLong, }) } -func (l *serverCertValidityTooLong) Initialize() error { - return nil +func NewServerCertValidityTooLong() lint.LintInterface { + return &serverCertValidityTooLong{} } func (l *serverCertValidityTooLong) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/apple/lint_w_server_cert_valid_time_longer_than_397_days.go b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_w_server_cert_valid_time_longer_than_397_days.go index 26a483fbe..c80c185ba 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/apple/lint_w_server_cert_valid_time_longer_than_397_days.go +++ b/vendor/github.com/zmap/zlint/v3/lints/apple/lint_w_server_cert_valid_time_longer_than_397_days.go @@ -32,12 +32,12 @@ func init() { Citation: "https://support.apple.com/en-us/HT211025", Source: lint.AppleRootStorePolicy, EffectiveDate: util.AppleReducedLifetimeDate, - Lint: &serverCertValidityAlmostTooLong{}, + Lint: NewServerCertValidityAlmostTooLong, }) } -func (l *serverCertValidityAlmostTooLong) Initialize() error { - return nil +func NewServerCertValidityAlmostTooLong() lint.LintInterface { + return &serverCertValidityAlmostTooLong{} } func (l *serverCertValidityAlmostTooLong) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_common_name_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_common_name_missing.go index e5918f29f..cded5cb8c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_common_name_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_common_name_missing.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.4.3.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV148Date, - Lint: &caCommonNameMissing{}, + Lint: NewCaCommonNameMissing, }) } -func (l *caCommonNameMissing) Initialize() error { - return nil +func NewCaCommonNameMissing() lint.LintInterface { + return &caCommonNameMissing{} } func (l *caCommonNameMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_invalid.go index 6fa2acbf7..ba34eea9d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_invalid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_invalid.go @@ -37,12 +37,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &caCountryNameInvalid{}, + Lint: NewCaCountryNameInvalid, }) } -func (l *caCountryNameInvalid) Initialize() error { - return nil +func NewCaCountryNameInvalid() lint.LintInterface { + return &caCountryNameInvalid{} } func (l *caCountryNameInvalid) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_missing.go index 3472daa21..a0a112b2b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_country_name_missing.go @@ -37,12 +37,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &caCountryNameMissing{}, + Lint: NewCaCountryNameMissing, }) } -func (l *caCountryNameMissing) Initialize() error { - return nil +func NewCaCountryNameMissing() lint.LintInterface { + return &caCountryNameMissing{} } func (l *caCountryNameMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_crl_sign_not_set.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_crl_sign_not_set.go index d842f4712..863a7ea40 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_crl_sign_not_set.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_crl_sign_not_set.go @@ -36,12 +36,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &caCRLSignNotSet{}, + Lint: NewCaCRLSignNotSet, }) } -func (l *caCRLSignNotSet) Initialize() error { - return nil +func NewCaCRLSignNotSet() lint.LintInterface { + return &caCRLSignNotSet{} } func (l *caCRLSignNotSet) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_digital_signature_not_set.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_digital_signature_not_set.go index 057f42032..64fc07c28 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_digital_signature_not_set.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_digital_signature_not_set.go @@ -39,12 +39,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &caDigSignNotSet{}, + Lint: NewCaDigSignNotSet, }) } -func (l *caDigSignNotSet) Initialize() error { - return nil +func NewCaDigSignNotSet() lint.LintInterface { + return &caDigSignNotSet{} } func (l *caDigSignNotSet) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_is_ca.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_is_ca.go index 838c0a700..5bec46cec 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_is_ca.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_is_ca.go @@ -15,8 +15,7 @@ package cabf_br */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -31,19 +30,19 @@ func init() { Citation: "BRs: 7.1.2.1, BRs: 7.1.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &caIsCA{}, + Lint: NewCaIsCA, }) } +func NewCaIsCA() lint.LintInterface { + return &caIsCA{} +} + type basicConstraints struct { IsCA bool `asn1:"optional"` MaxPathLen int `asn1:"optional,default:-1"` } -func (l *caIsCA) Initialize() error { - return nil -} - func (l *caIsCA) CheckApplies(c *x509.Certificate) bool { return util.IsExtInCert(c, util.KeyUsageOID) && c.KeyUsage&x509.KeyUsageCertSign != 0 && util.IsExtInCert(c, util.BasicConstOID) } diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_cert_sign_not_set.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_cert_sign_not_set.go index 86206b774..1861e3a41 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_cert_sign_not_set.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_cert_sign_not_set.go @@ -35,12 +35,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &caKeyCertSignNotSet{}, + Lint: NewCaKeyCertSignNotSet, }) } -func (l *caKeyCertSignNotSet) Initialize() error { - return nil +func NewCaKeyCertSignNotSet() lint.LintInterface { + return &caKeyCertSignNotSet{} } func (l *caKeyCertSignNotSet) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_missing.go index 4264e92e7..551a9a831 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_missing.go @@ -37,12 +37,12 @@ func init() { Citation: "BRs: 7.1.2.1, RFC 5280: 4.2.1.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.RFC3280Date, - Lint: &caKeyUsageMissing{}, + Lint: NewCaKeyUsageMissing, }) } -func (l *caKeyUsageMissing) Initialize() error { - return nil +func NewCaKeyUsageMissing() lint.LintInterface { + return &caKeyUsageMissing{} } func (l *caKeyUsageMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_not_critical.go index 375b22c53..1af5c0942 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_not_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_key_usage_not_critical.go @@ -35,12 +35,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &caKeyUsageNotCrit{}, + Lint: NewCaKeyUsageNotCrit, }) } -func (l *caKeyUsageNotCrit) Initialize() error { - return nil +func NewCaKeyUsageNotCrit() lint.LintInterface { + return &caKeyUsageNotCrit{} } func (l *caKeyUsageNotCrit) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_organization_name_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_organization_name_missing.go index 98bc43cf0..38d702e6d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_organization_name_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_organization_name_missing.go @@ -34,12 +34,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &caOrganizationNameMissing{}, + Lint: NewCaOrganizationNameMissing, }) } -func (l *caOrganizationNameMissing) Initialize() error { - return nil +func NewCaOrganizationNameMissing() lint.LintInterface { + return &caOrganizationNameMissing{} } func (l *caOrganizationNameMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_locality.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_locality.go index 992fe0ecb..7b290e49a 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_locality.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_locality.go @@ -23,12 +23,23 @@ import ( "github.com/zmap/zlint/v3/util" ) -type certPolicyConflictsWithLocality struct{} +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_cab_dv_conflicts_with_locality", + Description: "If certificate policy 2.23.140.1.2.1 (CA/B BR domain validated) is included, locality name MUST NOT be included in subject", + Citation: "BRs: 7.1.6.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + Lint: NewCertPolicyConflictsWithLocality, + }) +} -func (l *certPolicyConflictsWithLocality) Initialize() error { - return nil +func NewCertPolicyConflictsWithLocality() lint.LintInterface { + return &certPolicyConflictsWithLocality{} } +type certPolicyConflictsWithLocality struct{} + func (l *certPolicyConflictsWithLocality) CheckApplies(cert *x509.Certificate) bool { return util.SliceContainsOID(cert.PolicyIdentifiers, util.BRDomainValidatedOID) && !util.IsCACert(cert) } @@ -39,14 +50,3 @@ func (l *certPolicyConflictsWithLocality) Execute(cert *x509.Certificate) *lint. } return &lint.LintResult{Status: lint.Pass} } - -func init() { - lint.RegisterLint(&lint.Lint{ - Name: "e_cab_dv_conflicts_with_locality", - Description: "If certificate policy 2.23.140.1.2.1 (CA/B BR domain validated) is included, locality name MUST NOT be included in subject", - Citation: "BRs: 7.1.6.1", - Source: lint.CABFBaselineRequirements, - EffectiveDate: util.CABEffectiveDate, - Lint: &certPolicyConflictsWithLocality{}, - }) -} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_org.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_org.go index a9cc3f4c4..c32b5ae96 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_org.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_org.go @@ -39,12 +39,12 @@ func init() { Citation: "BRs: 7.1.6.4", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &certPolicyConflictsWithOrg{}, + Lint: NewCertPolicyConflictsWithOrg, }) } -func (l *certPolicyConflictsWithOrg) Initialize() error { - return nil +func NewCertPolicyConflictsWithOrg() lint.LintInterface { + return &certPolicyConflictsWithOrg{} } func (l *certPolicyConflictsWithOrg) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_postal.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_postal.go index 5ad1b85a5..2b9d26abb 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_postal.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_postal.go @@ -39,12 +39,12 @@ func init() { Citation: "BRs: 7.1.6.4", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &certPolicyConflictsWithPostal{}, + Lint: NewCertPolicyConflictsWithPostal, }) } -func (l *certPolicyConflictsWithPostal) Initialize() error { - return nil +func NewCertPolicyConflictsWithPostal() lint.LintInterface { + return &certPolicyConflictsWithPostal{} } func (l *certPolicyConflictsWithPostal) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_province.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_province.go index b0e4b7de3..656c80767 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_province.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_province.go @@ -39,12 +39,12 @@ func init() { Citation: "BRs: 7.1.6.4", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &certPolicyConflictsWithProvince{}, + Lint: NewCertPolicyConflictsWithProvince, }) } -func (l *certPolicyConflictsWithProvince) Initialize() error { - return nil +func NewCertPolicyConflictsWithProvince() lint.LintInterface { + return &certPolicyConflictsWithProvince{} } func (l *certPolicyConflictsWithProvince) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_street.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_street.go index ed217c4d4..314278a61 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_street.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_dv_conflicts_with_street.go @@ -39,12 +39,12 @@ func init() { Citation: "BRs: 7.1.6.4", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &certPolicyConflictsWithStreet{}, + Lint: NewCertPolicyConflictsWithStreet, }) } -func (l *certPolicyConflictsWithStreet) Initialize() error { - return nil +func NewCertPolicyConflictsWithStreet() lint.LintInterface { + return &certPolicyConflictsWithStreet{} } func (l *certPolicyConflictsWithStreet) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_iv_requires_personal_name.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_iv_requires_personal_name.go index 5da044fe6..8f81fdc8a 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_iv_requires_personal_name.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_iv_requires_personal_name.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.6.4", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV131Date, - Lint: &CertPolicyRequiresPersonalName{}, + Lint: NewCertPolicyRequiresPersonalName, }) } -func (l *CertPolicyRequiresPersonalName) Initialize() error { - return nil +func NewCertPolicyRequiresPersonalName() lint.LintInterface { + return &CertPolicyRequiresPersonalName{} } func (l *CertPolicyRequiresPersonalName) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_ov_requires_org.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_ov_requires_org.go index fcfe4e6f6..b39c0512e 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_ov_requires_org.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cab_ov_requires_org.go @@ -39,12 +39,12 @@ func init() { Citation: "BRs: 7.1.6.4", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &CertPolicyRequiresOrg{}, + Lint: NewCertPolicyRequiresOrg, }) } -func (l *CertPolicyRequiresOrg) Initialize() error { - return nil +func NewCertPolicyRequiresOrg() lint.LintInterface { + return &CertPolicyRequiresOrg{} } func (l *CertPolicyRequiresOrg) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_country.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_country.go index 5a05e49d3..75ca58834 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_country.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_country.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.6.4", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV131Date, - Lint: &CertPolicyIVRequiresCountry{}, + Lint: NewCertPolicyIVRequiresCountry, }) } -func (l *CertPolicyIVRequiresCountry) Initialize() error { - return nil +func NewCertPolicyIVRequiresCountry() lint.LintInterface { + return &CertPolicyIVRequiresCountry{} } func (l *CertPolicyIVRequiresCountry) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_province_or_locality.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_province_or_locality.go index 23a7c48b9..cfeac1b91 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_province_or_locality.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_iv_requires_province_or_locality.go @@ -41,12 +41,12 @@ func init() { Citation: "BRs: 7.1.6.4", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV131Date, - Lint: &CertPolicyIVRequiresProvinceOrLocal{}, + Lint: NewCertPolicyIVRequiresProvinceOrLocal, }) } -func (l *CertPolicyIVRequiresProvinceOrLocal) Initialize() error { - return nil +func NewCertPolicyIVRequiresProvinceOrLocal() lint.LintInterface { + return &CertPolicyIVRequiresProvinceOrLocal{} } func (l *CertPolicyIVRequiresProvinceOrLocal) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_country.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_country.go index fb8cae0cd..ef81bd934 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_country.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_country.go @@ -39,12 +39,12 @@ func init() { Citation: "BRs: 7.1.6.4", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &CertPolicyOVRequiresCountry{}, + Lint: NewCertPolicyOVRequiresCountry, }) } -func (l *CertPolicyOVRequiresCountry) Initialize() error { - return nil +func NewCertPolicyOVRequiresCountry() lint.LintInterface { + return &CertPolicyOVRequiresCountry{} } func (l *CertPolicyOVRequiresCountry) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_province_or_locality.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_province_or_locality.go index 7a219ddb3..e3ed9aae8 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_province_or_locality.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_cert_policy_ov_requires_province_or_locality.go @@ -41,12 +41,12 @@ func init() { Citation: "BRs: 7.1.6.4", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &CertPolicyOVRequiresProvinceOrLocal{}, + Lint: NewCertPolicyOVRequiresProvinceOrLocal, }) } -func (l *CertPolicyOVRequiresProvinceOrLocal) Initialize() error { - return nil +func NewCertPolicyOVRequiresProvinceOrLocal() lint.LintInterface { + return &CertPolicyOVRequiresProvinceOrLocal{} } func (l *CertPolicyOVRequiresProvinceOrLocal) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dh_params_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dh_params_missing.go index 2ea2193c0..1c38628f0 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dh_params_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dh_params_missing.go @@ -15,7 +15,7 @@ package cabf_br */ import ( - "crypto/dsa" + "github.com/zmap/zcrypto/dsa" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" @@ -26,17 +26,18 @@ type dsaParamsMissing struct{} func init() { lint.RegisterLint(&lint.Lint{ - Name: "e_dsa_params_missing", - Description: "DSA: Certificates MUST include all domain parameters", - Citation: "BRs v1.7.0: 6.1.6", - Source: lint.CABFBaselineRequirements, - EffectiveDate: util.CABEffectiveDate, - Lint: &dsaParamsMissing{}, + Name: "e_dsa_params_missing", + Description: "DSA: Certificates MUST include all domain parameters", + Citation: "BRs v1.7.0: 6.1.6", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + IneffectiveDate: util.CABFBRs_1_7_1_Date, + Lint: NewDsaParamsMissing, }) } -func (l *dsaParamsMissing) Initialize() error { - return nil +func NewDsaParamsMissing() lint.LintInterface { + return &dsaParamsMissing{} } func (l *dsaParamsMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_bad_character_in_label.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_bad_character_in_label.go index 838a6ef1a..8f70133e6 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_bad_character_in_label.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_bad_character_in_label.go @@ -33,16 +33,14 @@ func init() { Citation: "BRs: 7.1.4.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &DNSNameProperCharacters{}, + Lint: NewDNSNameProperCharacters, }) } -func (l *DNSNameProperCharacters) Initialize() error { - const dnsNameRegexp = `^(\*\.)?(\?\.)*([A-Za-z0-9*_-]+\.)*[A-Za-z0-9*_-]*$` - var err error - l.CompiledExpression, err = regexp.Compile(dnsNameRegexp) - - return err +func NewDNSNameProperCharacters() lint.LintInterface { + return &DNSNameProperCharacters{ + CompiledExpression: regexp.MustCompile(`^(\*\.)?(\?\.)*([A-Za-z0-9*_-]+\.)*[A-Za-z0-9*_-]*$`), + } } func (l *DNSNameProperCharacters) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_check_left_label_wildcard.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_check_left_label_wildcard.go index 3c9c6c26d..2700c4854 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_check_left_label_wildcard.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_check_left_label_wildcard.go @@ -31,12 +31,12 @@ func init() { Citation: "BRs: 1.6.1, Wildcard Certificate and Wildcard Domain Name", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &DNSNameLeftLabelWildcardCheck{}, + Lint: NewDNSNameLeftLabelWildcardCheck, }) } -func (l *DNSNameLeftLabelWildcardCheck) Initialize() error { - return nil +func NewDNSNameLeftLabelWildcardCheck() lint.LintInterface { + return &DNSNameLeftLabelWildcardCheck{} } func (l *DNSNameLeftLabelWildcardCheck) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_bare_iana_suffix.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_bare_iana_suffix.go index bbf31a53b..ce914657a 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_bare_iana_suffix.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_bare_iana_suffix.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 1.6.1, Base Domain Name", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &dnsNameContainsBareIANASuffix{}, + Lint: NewDnsNameContainsBareIANASuffix, }) } -func (l *dnsNameContainsBareIANASuffix) Initialize() error { - return nil +func NewDnsNameContainsBareIANASuffix() lint.LintInterface { + return &dnsNameContainsBareIANASuffix{} } func (l *dnsNameContainsBareIANASuffix) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_empty_label.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_empty_label.go index c617460fe..6fa57d2f1 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_empty_label.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_empty_label.go @@ -31,12 +31,12 @@ func init() { Citation: "BRs: 7.1.4.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &DNSNameEmptyLabel{}, + Lint: NewDNSNameEmptyLabel, }) } -func (l *DNSNameEmptyLabel) Initialize() error { - return nil +func NewDNSNameEmptyLabel() lint.LintInterface { + return &DNSNameEmptyLabel{} } func (l *DNSNameEmptyLabel) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_prohibited_reserved_label.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_prohibited_reserved_label.go new file mode 100644 index 000000000..2c3983eff --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_contains_prohibited_reserved_label.go @@ -0,0 +1,58 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_br + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_dnsname_contains_prohibited_reserved_label", + Description: "FQDNs MUST consist solely of Domain Labels that are P‐Labels or Non‐Reserved LDH Labels", + Citation: "BRs: 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.NoReservedDomainLabelsDate, + Lint: NewDNSNameContainsProhibitedReservedLabel, + }) +} + +type DNSNameContainsProhibitedReservedLabel struct{} + +func NewDNSNameContainsProhibitedReservedLabel() lint.LintInterface { + return &DNSNameContainsProhibitedReservedLabel{} +} + +func (l *DNSNameContainsProhibitedReservedLabel) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *DNSNameContainsProhibitedReservedLabel) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + labels := strings.Split(dns, ".") + + for _, label := range labels { + if util.HasReservedLabelPrefix(label) && !util.HasXNLabelPrefix(label) { + return &lint.LintResult{Status: lint.Error} + } + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_hyphen_in_sld.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_hyphen_in_sld.go index f2687edc5..f894fa006 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_hyphen_in_sld.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_hyphen_in_sld.go @@ -31,12 +31,12 @@ func init() { Citation: "BRs 7.1.4.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.RFC5280Date, - Lint: &DNSNameHyphenInSLD{}, + Lint: NewDNSNameHyphenInSLD, }) } -func (l *DNSNameHyphenInSLD) Initialize() error { - return nil +func NewDNSNameHyphenInSLD() lint.LintInterface { + return &DNSNameHyphenInSLD{} } func (l *DNSNameHyphenInSLD) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_label_too_long.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_label_too_long.go index f13f93358..700e9ab8b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_label_too_long.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_label_too_long.go @@ -31,12 +31,12 @@ func init() { Citation: "RFC 1035", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &DNSNameLabelLengthTooLong{}, + Lint: NewDNSNameLabelLengthTooLong, }) } -func (l *DNSNameLabelLengthTooLong) Initialize() error { - return nil +func NewDNSNameLabelLengthTooLong() lint.LintInterface { + return &DNSNameLabelLengthTooLong{} } func (l *DNSNameLabelLengthTooLong) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_right_label_valid_tld.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_right_label_valid_tld.go index 23998b5b8..eee0fab14 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_right_label_valid_tld.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_right_label_valid_tld.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 3.2.2.4", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &DNSNameValidTLD{}, + Lint: NewDNSNameValidTLD, }) } -func (l *DNSNameValidTLD) Initialize() error { - return nil +func NewDNSNameValidTLD() lint.LintInterface { + return &DNSNameValidTLD{} } func (l *DNSNameValidTLD) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_sld.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_sld.go index f02a86f02..1c3ec26f1 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_sld.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_sld.go @@ -31,12 +31,12 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.RFC5280Date, - Lint: &DNSNameUnderscoreInSLD{}, + Lint: NewDNSNameUnderscoreInSLD, }) } -func (l *DNSNameUnderscoreInSLD) Initialize() error { - return nil +func NewDNSNameUnderscoreInSLD() lint.LintInterface { + return &DNSNameUnderscoreInSLD{} } func (l *DNSNameUnderscoreInSLD) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_trd.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_trd.go index 0e8e02e59..6da9f1f8f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_trd.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_underscore_in_trd.go @@ -31,12 +31,12 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.RFC5280Date, - Lint: &DNSNameUnderscoreInTRD{}, + Lint: NewDNSNameUnderscoreInTRD, }) } -func (l *DNSNameUnderscoreInTRD) Initialize() error { - return nil +func NewDNSNameUnderscoreInTRD() lint.LintInterface { + return &DNSNameUnderscoreInTRD{} } func (l *DNSNameUnderscoreInTRD) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_left_of_public_suffix.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_left_of_public_suffix.go index a2d0eb927..b1c67c8f2 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_left_of_public_suffix.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_left_of_public_suffix.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 3.2.2.6", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &DNSNameWildcardLeftofPublicSuffix{}, + Lint: NewDNSNameWildcardLeftofPublicSuffix, }) } -func (l *DNSNameWildcardLeftofPublicSuffix) Initialize() error { - return nil +func NewDNSNameWildcardLeftofPublicSuffix() lint.LintInterface { + return &DNSNameWildcardLeftofPublicSuffix{} } func (l *DNSNameWildcardLeftofPublicSuffix) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_only_in_left_label.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_only_in_left_label.go index 1bcc08021..da3320ee3 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_only_in_left_label.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dnsname_wildcard_only_in_left_label.go @@ -31,12 +31,12 @@ func init() { Citation: "BRs: 1.6.1, Wildcard Domain Name", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &DNSNameWildcardOnlyInLeftlabel{}, + Lint: NewDNSNameWildcardOnlyInLeftlabel, }) } -func (l *DNSNameWildcardOnlyInLeftlabel) Initialize() error { - return nil +func NewDNSNameWildcardOnlyInLeftlabel() lint.LintInterface { + return &DNSNameWildcardOnlyInLeftlabel{} } func (l *DNSNameWildcardOnlyInLeftlabel) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_correct_order_in_subgroup.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_correct_order_in_subgroup.go index 5109a5787..0def57863 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_correct_order_in_subgroup.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_correct_order_in_subgroup.go @@ -15,9 +15,10 @@ package cabf_br */ import ( - "crypto/dsa" "math/big" + "github.com/zmap/zcrypto/dsa" + "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -32,12 +33,12 @@ func init() { Citation: "BRs v1.7.0: 6.1.6", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &dsaSubgroup{}, + Lint: NewDsaSubgroup, }) } -func (l *dsaSubgroup) Initialize() error { - return nil +func NewDsaSubgroup() lint.LintInterface { + return &dsaSubgroup{} } func (l *dsaSubgroup) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_improper_modulus_or_divisor_size.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_improper_modulus_or_divisor_size.go index d991d872b..123ce672f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_improper_modulus_or_divisor_size.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_improper_modulus_or_divisor_size.go @@ -15,7 +15,7 @@ package cabf_br */ import ( - "crypto/dsa" + "github.com/zmap/zcrypto/dsa" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" @@ -31,12 +31,12 @@ func init() { Citation: "BRs v1.7.0: 6.1.5", Source: lint.CABFBaselineRequirements, EffectiveDate: util.ZeroDate, - Lint: &dsaImproperSize{}, + Lint: NewDsaImproperSize, }) } -func (l *dsaImproperSize) Initialize() error { - return nil +func NewDsaImproperSize() lint.LintInterface { + return &dsaImproperSize{} } func (l *dsaImproperSize) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_shorter_than_2048_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_shorter_than_2048_bits.go index bbf7b4f60..f9e9cd7d7 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_shorter_than_2048_bits.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_shorter_than_2048_bits.go @@ -15,7 +15,7 @@ package cabf_br */ import ( - "crypto/dsa" + "github.com/zmap/zcrypto/dsa" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" @@ -32,12 +32,12 @@ func init() { // Refer to BRs: 6.1.5, taking the statement "Before 31 Dec 2010" literally Source: lint.CABFBaselineRequirements, EffectiveDate: util.ZeroDate, - Lint: &dsaTooShort{}, + Lint: NewDsaTooShort, }) } -func (l *dsaTooShort) Initialize() error { - return nil +func NewDsaTooShort() lint.LintInterface { + return &dsaTooShort{} } func (l *dsaTooShort) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_unique_correct_representation.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_unique_correct_representation.go index da36d97d6..de64fbbff 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_unique_correct_representation.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_dsa_unique_correct_representation.go @@ -15,9 +15,10 @@ package cabf_br */ import ( - "crypto/dsa" "math/big" + "github.com/zmap/zcrypto/dsa" + "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -32,12 +33,12 @@ func init() { Citation: "BRs v1.7.0: 6.1.6", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &dsaUniqueCorrectRepresentation{}, + Lint: NewDsaUniqueCorrectRepresentation, }) } -func (l *dsaUniqueCorrectRepresentation) Initialize() error { - return nil +func NewDsaUniqueCorrectRepresentation() lint.LintInterface { + return &dsaUniqueCorrectRepresentation{} } func (l *dsaUniqueCorrectRepresentation) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_sub_ca_aia_missing.go similarity index 78% rename from vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_missing.go rename to vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_sub_ca_aia_missing.go index 14c70565e..defe83064 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_sub_ca_aia_missing.go @@ -32,17 +32,18 @@ marked critical, and it MUST contain the HTTP URL of the Issuing CA’s OCSP res func init() { lint.RegisterLint(&lint.Lint{ - Name: "e_sub_ca_aia_missing", - Description: "Subordinate CA Certificate: authorityInformationAccess MUST be present, with the exception of stapling.", - Citation: "BRs: 7.1.2.2", - Source: lint.CABFBaselineRequirements, - EffectiveDate: util.CABEffectiveDate, - Lint: &caAiaMissing{}, + Name: "e_sub_ca_aia_missing", + Description: "Subordinate CA Certificate: authorityInformationAccess MUST be present, with the exception of stapling.", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + IneffectiveDate: util.CABFBRs_1_7_1_Date, + Lint: NewCaAiaMissing, }) } -func (l *caAiaMissing) Initialize() error { - return nil +func NewCaAiaMissing() lint.LintInterface { + return &caAiaMissing{} } func (l *caAiaMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ec_improper_curves.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ec_improper_curves.go index 9e894b4b7..5b995d403 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ec_improper_curves.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ec_improper_curves.go @@ -38,12 +38,12 @@ func init() { Source: lint.CABFBaselineRequirements, // Refer to BRs: 6.1.5, taking the statement "Before 31 Dec 2010" literally EffectiveDate: util.ZeroDate, - Lint: &ecImproperCurves{}, + Lint: NewEcImproperCurves, }) } -func (l *ecImproperCurves) Initialize() error { - return nil +func NewEcImproperCurves() lint.LintInterface { + return &ecImproperCurves{} } func (l *ecImproperCurves) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_nc_intersects_reserved_ip.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_nc_intersects_reserved_ip.go index df33ab21a..6a5961bf8 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_nc_intersects_reserved_ip.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_nc_intersects_reserved_ip.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.5 / 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &NCReservedIPNet{}, + Lint: NewNCReservedIPNet, }) } -func (l *NCReservedIPNet) Initialize() error { - return nil +func NewNCReservedIPNet() lint.LintInterface { + return &NCReservedIPNet{} } func (l *NCReservedIPNet) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_contains_reserved_ip.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_contains_reserved_ip.go index 727085745..5f6c91716 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_contains_reserved_ip.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_contains_reserved_ip.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &SANReservedIP{}, + Lint: NewSANReservedIP, }) } -func (l *SANReservedIP) Initialize() error { - return nil +func NewSANReservedIP() lint.LintInterface { + return &SANReservedIP{} } func (l *SANReservedIP) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_critical_with_subject_dn.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_critical_with_subject_dn.go index ccb3d325d..04a44e5a4 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_critical_with_subject_dn.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_critical_with_subject_dn.go @@ -40,12 +40,12 @@ func init() { Citation: "RFC 5280: 4.2.1.6", Source: lint.CABFBaselineRequirements, EffectiveDate: util.RFC5280Date, - Lint: &ExtSANCriticalWithSubjectDN{}, + Lint: NewExtSANCriticalWithSubjectDN, }) } -func (l *ExtSANCriticalWithSubjectDN) Initialize() error { - return nil +func NewExtSANCriticalWithSubjectDN() lint.LintInterface { + return &ExtSANCriticalWithSubjectDN{} } func (l *ExtSANCriticalWithSubjectDN) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_directory_name_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_directory_name_present.go index 6d1aa5920..bcfb9cf21 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_directory_name_present.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_directory_name_present.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &SANDirName{}, + Lint: NewSANDirName, }) } -func (l *SANDirName) Initialize() error { - return nil +func NewSANDirName() lint.LintInterface { + return &SANDirName{} } func (l *SANDirName) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_edi_party_name_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_edi_party_name_present.go index 42c193dc4..bd6e2f050 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_edi_party_name_present.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_edi_party_name_present.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &SANEDI{}, + Lint: NewSANEDI, }) } -func (l *SANEDI) Initialize() error { - return nil +func NewSANEDI() lint.LintInterface { + return &SANEDI{} } func (l *SANEDI) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_missing.go index 59aae44c2..a43af6099 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_missing.go @@ -36,12 +36,12 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &SANMissing{}, + Lint: NewSANMissing, }) } -func (l *SANMissing) Initialize() error { - return nil +func NewSANMissing() lint.LintInterface { + return &SANMissing{} } func (l *SANMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_other_name_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_other_name_present.go index fa6f90d5f..1752d00b3 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_other_name_present.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_other_name_present.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &SANOtherName{}, + Lint: NewSANOtherName, }) } -func (l *SANOtherName) Initialize() error { - return nil +func NewSANOtherName() lint.LintInterface { + return &SANOtherName{} } func (l *SANOtherName) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_registered_id_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_registered_id_present.go index ef9bea512..dd6a5ec66 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_registered_id_present.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_registered_id_present.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &SANRegId{}, + Lint: NewSANRegId, }) } -func (l *SANRegId) Initialize() error { - return nil +func NewSANRegId() lint.LintInterface { + return &SANRegId{} } func (l *SANRegId) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_rfc822_name_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_rfc822_name_present.go index 27e1b401f..1aedbcfc4 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_rfc822_name_present.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_rfc822_name_present.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &SANRfc822{}, + Lint: NewSANRfc822, }) } -func (l *SANRfc822) Initialize() error { - return nil +func NewSANRfc822() lint.LintInterface { + return &SANRfc822{} } func (l *SANRfc822) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_uniform_resource_identifier_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_uniform_resource_identifier_present.go index 203c7cd6e..5a011e710 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_uniform_resource_identifier_present.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_san_uniform_resource_identifier_present.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &SANURI{}, + Lint: NewSANURI, }) } -func (l *SANURI) Initialize() error { - return nil +func NewSANURI() lint.LintInterface { + return &SANURI{} } func (l *SANURI) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_tor_service_descriptor_hash_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_tor_service_descriptor_hash_invalid.go index aa550b1a2..b70573268 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_tor_service_descriptor_hash_invalid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ext_tor_service_descriptor_hash_invalid.go @@ -33,10 +33,14 @@ func init() { Citation: "BRs: Ballot 201, Ballot SC27", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV201Date, - Lint: &torServiceDescHashInvalid{}, + Lint: NewTorServiceDescHashInvalid, }) } +func NewTorServiceDescHashInvalid() lint.LintInterface { + return &torServiceDescHashInvalid{} +} + func (l *torServiceDescHashInvalid) Initialize() error { // There is nothing to initialize for a torServiceDescHashInvalid linter. return nil @@ -49,7 +53,8 @@ func (l *torServiceDescHashInvalid) CheckApplies(c *x509.Certificate) bool { ext := util.GetExtFromCert(c, util.BRTorServiceDescriptor) return ext != nil || (util.IsSubscriberCert(c) && util.CertificateSubjInTLD(c, util.OnionTLD) && - util.IsEV(c.PolicyIdentifiers)) + util.IsEV(c.PolicyIdentifiers)) && + util.IsOnionV2Cert(c) } // failResult is a small utility function for creating a failed lint result. @@ -108,6 +113,7 @@ func lintOnionURL(onion string) *lint.LintResult { // an onion subject in the cert. // 6) There is an onion subject in the cert that doesn't correspond to // a TorServiceDescriptorHash, if required. +//nolint:cyclop func (l *torServiceDescHashInvalid) Execute(c *x509.Certificate) *lint.LintResult { // If the certificate is EV, the BRTorServiceDescriptor extension is required. // We know that `CheckApplies` will only apply if the certificate has the diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_extra_subject_common_names.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_extra_subject_common_names.go index 43c1ebd1b..3d17bca22 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_extra_subject_common_names.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_extra_subject_common_names.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &extraSubjectCommonNames{}, + Lint: NewExtraSubjectCommonNames, }) } -func (l *extraSubjectCommonNames) Initialize() error { - return nil +func NewExtraSubjectCommonNames() lint.LintInterface { + return &extraSubjectCommonNames{} } func (l *extraSubjectCommonNames) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_invalid_certificate_version.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_invalid_certificate_version.go index 24e63be41..67c5b5705 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_invalid_certificate_version.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_invalid_certificate_version.go @@ -33,12 +33,12 @@ func init() { Citation: "BRs: 7.1.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV130Date, - Lint: &InvalidCertificateVersion{}, + Lint: NewInvalidCertificateVersion, }) } -func (l *InvalidCertificateVersion) Initialize() error { - return nil +func NewInvalidCertificateVersion() lint.LintInterface { + return &InvalidCertificateVersion{} } func (l *InvalidCertificateVersion) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_no_underscores_before_1_6_2.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_no_underscores_before_1_6_2.go new file mode 100644 index 000000000..865244253 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_no_underscores_before_1_6_2.go @@ -0,0 +1,58 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_br + +import ( + "fmt" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_no_underscores_before_1_6_2", + Description: "Before explicitly stating as such in CABF 1.6.2, the stance of RFC5280 is adopted that DNSNames MUST NOT contain an underscore character.", + Citation: "BR 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.ZeroDate, + IneffectiveDate: util.CABFBRs_1_6_2_Date, + Lint: func() lint.LintInterface { return &NoUnderscoreBefore1_6_2{} }, + }) +} + +type NoUnderscoreBefore1_6_2 struct{} + +func NewNoUnderscoreBefore1_6_2() lint.LintInterface { + return &NoUnderscoreBefore1_6_2{} +} + +func (l *NoUnderscoreBefore1_6_2) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *NoUnderscoreBefore1_6_2) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + if strings.Contains(dns, "_") { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("The DNS name '%s' contains an underscore (_) character", dns), + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ocsp_id_pkix_ocsp_nocheck_ext_not_included_server_auth.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ocsp_id_pkix_ocsp_nocheck_ext_not_included_server_auth.go index 94c315977..6fd53b783 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ocsp_id_pkix_ocsp_nocheck_ext_not_included_server_auth.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ocsp_id_pkix_ocsp_nocheck_ext_not_included_server_auth.go @@ -30,12 +30,12 @@ func init() { Citation: "BRs: 4.9.9", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &OCSPIDPKIXOCSPNocheckExtNotIncludedServerAuth{}, + Lint: NewOCSPIDPKIXOCSPNocheckExtNotIncludedServerAuth, }) } -func (l *OCSPIDPKIXOCSPNocheckExtNotIncludedServerAuth) Initialize() error { - return nil +func NewOCSPIDPKIXOCSPNocheckExtNotIncludedServerAuth() lint.LintInterface { + return &OCSPIDPKIXOCSPNocheckExtNotIncludedServerAuth{} } func (l *OCSPIDPKIXOCSPNocheckExtNotIncludedServerAuth) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_root_ca_rsa_mod_less_than_2048_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_root_ca_rsa_mod_less_than_2048_bits.go index bff217863..9d9cc782e 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_root_ca_rsa_mod_less_than_2048_bits.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_root_ca_rsa_mod_less_than_2048_bits.go @@ -31,12 +31,12 @@ func init() { Citation: "BRs: 6.1.5", Source: lint.CABFBaselineRequirements, EffectiveDate: util.ZeroDate, - Lint: &rootCaModSize{}, + Lint: NewRootCaModSize, }) } -func (l *rootCaModSize) Initialize() error { - return nil +func NewRootCaModSize() lint.LintInterface { + return &rootCaModSize{} } func (l *rootCaModSize) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_ca_rsa_mod_less_than_1024_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_ca_rsa_mod_less_than_1024_bits.go index 974ef8c8d..0895100f6 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_ca_rsa_mod_less_than_1024_bits.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_ca_rsa_mod_less_than_1024_bits.go @@ -34,12 +34,12 @@ func init() { Source: lint.CABFBaselineRequirements, // since effective date should be checked against end date in this specific case, putting time check into checkApplies instead, ZeroDate here to automatically pass NE test EffectiveDate: util.ZeroDate, - Lint: &subCaModSize{}, + Lint: NewSubCaModSize, }) } -func (l *subCaModSize) Initialize() error { - return nil +func NewSubCaModSize() lint.LintInterface { + return &subCaModSize{} } func (l *subCaModSize) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_cert_rsa_mod_less_than_1024_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_cert_rsa_mod_less_than_1024_bits.go index 989f3ab42..e0fc1d586 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_cert_rsa_mod_less_than_1024_bits.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_old_sub_cert_rsa_mod_less_than_1024_bits.go @@ -32,12 +32,12 @@ func init() { Source: lint.CABFBaselineRequirements, // since effective date should be checked against end date in this specific case, putting time check into checkApplies instead, ZeroDate here to automatically pass NE test EffectiveDate: util.ZeroDate, - Lint: &subModSize{}, + Lint: NewSubModSize, }) } -func (l *subModSize) Initialize() error { - return nil +func NewSubModSize() lint.LintInterface { + return &subModSize{} } func (l *subModSize) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_organizational_unit_name_prohibited.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_organizational_unit_name_prohibited.go new file mode 100644 index 000000000..610ea156a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_organizational_unit_name_prohibited.go @@ -0,0 +1,50 @@ +package cabf_br + +/* + * ZLint Copyright 2022 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_organizational_unit_name_prohibited", + Description: "OrganizationalUnitName is prohibited if...the certificate was issued on or after September 1, 2022", + Citation: "BRs: 7.1.4.2.2-i", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABFBRs_OU_Prohibited_Date, + Lint: NewOrganizationalUnitNameProhibited, + }) +} + +type OrganizationalUnitNameProhibited struct{} + +func NewOrganizationalUnitNameProhibited() lint.LintInterface { + return &OrganizationalUnitNameProhibited{} +} + +func (l *OrganizationalUnitNameProhibited) CheckApplies(c *x509.Certificate) bool { + return !c.IsCA +} + +func (l *OrganizationalUnitNameProhibited) Execute(c *x509.Certificate) *lint.LintResult { + if c.Subject.OrganizationalUnit != nil { + return &lint.LintResult{Status: lint.Error} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_prohibit_dsa_usage.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_prohibit_dsa_usage.go new file mode 100644 index 000000000..0a9e9a2c0 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_prohibit_dsa_usage.go @@ -0,0 +1,50 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_br + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type prohibitDSAUsage struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_br_prohibit_dsa_usage", + Description: "DSA was removed from the Baseline Requirements as a valid signature algorithm in 1.7.1.", + Citation: "BRs: v1.7.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABFBRs_1_7_1_Date, + Lint: NewProhibitDSAUsage, + }) +} + +func NewProhibitDSAUsage() lint.LintInterface { + return &prohibitDSAUsage{} +} + +func (l *prohibitDSAUsage) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *prohibitDSAUsage) Execute(c *x509.Certificate) *lint.LintResult { + if c.PublicKeyAlgorithm == x509.DSA { + return &lint.LintResult{Status: lint.Error} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_public_key_type_not_allowed.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_public_key_type_not_allowed.go index dcc9cc7f5..026f51f2c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_public_key_type_not_allowed.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_public_key_type_not_allowed.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 6.1.5", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &publicKeyAllowed{}, + Lint: NewPublicKeyAllowed, }) } -func (l *publicKeyAllowed) Initialize() error { - return nil +func NewPublicKeyAllowed() lint.LintInterface { + return &publicKeyAllowed{} } func (l *publicKeyAllowed) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_basic_constraints_path_len_constraint_field_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_basic_constraints_path_len_constraint_field_present.go index d62f41fd1..91efa0ce5 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_basic_constraints_path_len_constraint_field_present.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_basic_constraints_path_len_constraint_field_present.go @@ -15,8 +15,7 @@ package cabf_br */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -37,12 +36,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &rootCaPathLenPresent{}, + Lint: NewRootCaPathLenPresent, }) } -func (l *rootCaPathLenPresent) Initialize() error { - return nil +func NewRootCaPathLenPresent() lint.LintInterface { + return &rootCaPathLenPresent{} } func (l *rootCaPathLenPresent) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_contains_cert_policy.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_contains_cert_policy.go index 170772616..078455a6b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_contains_cert_policy.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_contains_cert_policy.go @@ -34,12 +34,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &rootCAContainsCertPolicy{}, + Lint: NewRootCAContainsCertPolicy, }) } -func (l *rootCAContainsCertPolicy) Initialize() error { - return nil +func NewRootCAContainsCertPolicy() lint.LintInterface { + return &rootCAContainsCertPolicy{} } func (l *rootCAContainsCertPolicy) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_extended_key_usage_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_extended_key_usage_present.go index 843a2e89a..1d54b8a5c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_extended_key_usage_present.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_extended_key_usage_present.go @@ -34,12 +34,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &rootCAContainsEKU{}, + Lint: NewRootCAContainsEKU, }) } -func (l *rootCAContainsEKU) Initialize() error { - return nil +func NewRootCAContainsEKU() lint.LintInterface { + return &rootCAContainsEKU{} } func (l *rootCAContainsEKU) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_must_be_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_must_be_critical.go index 23167e8d9..023405150 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_must_be_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_must_be_critical.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.RFC2459Date, - Lint: &rootCAKeyUsageMustBeCritical{}, + Lint: NewRootCAKeyUsageMustBeCritical, }) } -func (l *rootCAKeyUsageMustBeCritical) Initialize() error { - return nil +func NewRootCAKeyUsageMustBeCritical() lint.LintInterface { + return &rootCAKeyUsageMustBeCritical{} } func (l *rootCAKeyUsageMustBeCritical) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_present.go index 0fc91f40d..7dccd4ff4 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_present.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_root_ca_key_usage_present.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.RFC2459Date, - Lint: &rootCAKeyUsagePresent{}, + Lint: NewRootCAKeyUsagePresent, }) } -func (l *rootCAKeyUsagePresent) Initialize() error { - return nil +func NewRootCAKeyUsagePresent() lint.LintInterface { + return &rootCAKeyUsagePresent{} } func (l *rootCAKeyUsagePresent) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_factors_smaller_than_752_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_factors_smaller_than_752_bits.go index 856a9882c..89954519f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_factors_smaller_than_752_bits.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_factors_smaller_than_752_bits.go @@ -36,12 +36,12 @@ func init() { Citation: "BRs: 6.1.6", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV113Date, - Lint: &rsaModSmallFactor{}, + Lint: NewRsaModSmallFactor, }) } -func (l *rsaModSmallFactor) Initialize() error { - return nil +func NewRsaModSmallFactor() lint.LintInterface { + return &rsaModSmallFactor{} } func (l *rsaModSmallFactor) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_less_than_2048_bits.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_less_than_2048_bits.go index 6e1fee4fd..3769f998c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_less_than_2048_bits.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_less_than_2048_bits.go @@ -31,17 +31,17 @@ func init() { Citation: "BRs: 6.1.5", Source: lint.CABFBaselineRequirements, EffectiveDate: util.ZeroDate, - Lint: &rsaParsedTestsKeySize{}, + Lint: NewRsaParsedTestsKeySize, }) } -func (l *rsaParsedTestsKeySize) Initialize() error { - return nil +func NewRsaParsedTestsKeySize() lint.LintInterface { + return &rsaParsedTestsKeySize{} } func (l *rsaParsedTestsKeySize) CheckApplies(c *x509.Certificate) bool { _, ok := c.PublicKey.(*rsa.PublicKey) - return ok && c.PublicKeyAlgorithm == x509.RSA && c.NotAfter.After(util.NoRSA1024Date.Add(-1)) + return ok && c.PublicKeyAlgorithm == x509.RSA && util.OnOrAfter(c.NotAfter, util.NoRSA1024Date) } func (l *rsaParsedTestsKeySize) Execute(c *x509.Certificate) *lint.LintResult { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_not_odd.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_not_odd.go index 910d77d60..8ebbae7b6 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_not_odd.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_mod_not_odd.go @@ -37,12 +37,12 @@ func init() { Citation: "BRs: 6.1.6", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV113Date, - Lint: &rsaParsedTestsKeyModOdd{}, + Lint: NewRsaParsedTestsKeyModOdd, }) } -func (l *rsaParsedTestsKeyModOdd) Initialize() error { - return nil +func NewRsaParsedTestsKeyModOdd() lint.LintInterface { + return &rsaParsedTestsKeyModOdd{} } func (l *rsaParsedTestsKeyModOdd) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_in_range.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_in_range.go index 9015140bd..375718875 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_in_range.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_in_range.go @@ -39,14 +39,15 @@ func init() { Citation: "BRs: 6.1.6", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV113Date, - Lint: &rsaParsedTestsExpInRange{}, + Lint: NewRsaParsedTestsExpInRange, }) } -func (l *rsaParsedTestsExpInRange) Initialize() error { +func NewRsaParsedTestsExpInRange() lint.LintInterface { + l := &rsaParsedTestsExpInRange{} l.upperBound = &big.Int{} l.upperBound.Exp(big.NewInt(2), big.NewInt(256), nil) - return nil + return l } func (l *rsaParsedTestsExpInRange) CheckApplies(c *x509.Certificate) bool { @@ -57,8 +58,8 @@ func (l *rsaParsedTestsExpInRange) CheckApplies(c *x509.Certificate) bool { func (l *rsaParsedTestsExpInRange) Execute(c *x509.Certificate) *lint.LintResult { key := c.PublicKey.(*rsa.PublicKey) exponent := key.E - const lowerBound = 65536 // 2^16 + 1 - if exponent > lowerBound && l.upperBound.Cmp(big.NewInt(int64(exponent))) == 1 { + const lowerBound = 65537 // 2^16 + 1 + if exponent >= lowerBound && l.upperBound.Cmp(big.NewInt(int64(exponent))) == 1 { return &lint.LintResult{Status: lint.Pass} } return &lint.LintResult{Status: lint.Warn} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_odd.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_odd.go index 9b39ca649..fd669fec5 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_odd.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_not_odd.go @@ -36,12 +36,12 @@ func init() { Citation: "BRs: 6.1.6", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV113Date, - Lint: &rsaParsedTestsKeyExpOdd{}, + Lint: NewRsaParsedTestsKeyExpOdd, }) } -func (l *rsaParsedTestsKeyExpOdd) Initialize() error { - return nil +func NewRsaParsedTestsKeyExpOdd() lint.LintInterface { + return &rsaParsedTestsKeyExpOdd{} } func (l *rsaParsedTestsKeyExpOdd) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_too_small.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_too_small.go index 76620a8b0..5735c9b96 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_too_small.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_rsa_public_exponent_too_small.go @@ -36,12 +36,12 @@ func init() { Citation: "BRs: 6.1.6", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV113Date, - Lint: &rsaParsedTestsExpBounds{}, + Lint: NewRsaParsedTestsExpBounds, }) } -func (l *rsaParsedTestsExpBounds) Initialize() error { - return nil +func NewRsaParsedTestsExpBounds() lint.LintInterface { + return &rsaParsedTestsExpBounds{} } func (l *rsaParsedTestsExpBounds) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_invalid.go index f3e2f8e60..59c89556c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_invalid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_invalid.go @@ -84,12 +84,12 @@ func init() { Citation: "RFC 7686, EVGs v1.7.2: Appendix F, BRs v1.6.9: Appendix C", Source: lint.CABFBaselineRequirements, EffectiveDate: util.OnionOnlyEVDate, - Lint: &onionNotValid{}, + Lint: NewOnionNotValid, }) } -func (l *onionNotValid) Initialize() error { - return nil +func NewOnionNotValid() lint.LintInterface { + return &onionNotValid{} } // CheckApplies returns true if the certificate contains one or more subject diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_not_ev_cert.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_not_ev_cert.go index d26a277ed..ae6fbb7e0 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_not_ev_cert.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_san_dns_name_onion_not_ev_cert.go @@ -31,12 +31,12 @@ func init() { Citation: "CABF Ballot 144", Source: lint.CABFBaselineRequirements, EffectiveDate: util.OnionOnlyEVDate, - Lint: &onionNotEV{}, + Lint: NewOnionNotEV, }) } -func (l *onionNotEV) Initialize() error { - return nil +func NewOnionNotEV() lint.LintInterface { + return &onionNotEV{} } // This lint only applies for certificates issued before CA/Browser Forum diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_signature_algorithm_not_supported.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_signature_algorithm_not_supported.go index 2e25a3b78..fee64fc1c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_signature_algorithm_not_supported.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_signature_algorithm_not_supported.go @@ -61,12 +61,12 @@ func init() { Citation: "BRs: 6.1.5", Source: lint.CABFBaselineRequirements, EffectiveDate: util.ZeroDate, - Lint: &signatureAlgorithmNotSupported{}, + Lint: NewSignatureAlgorithmNotSupported, }) } -func (l *signatureAlgorithmNotSupported) Initialize() error { - return nil +func NewSignatureAlgorithmNotSupported() lint.LintInterface { + return &signatureAlgorithmNotSupported{} } func (l *signatureAlgorithmNotSupported) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go index 0a4e7b14a..4b30db332 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go @@ -39,12 +39,12 @@ func init() { Citation: "BRs: 7.1.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCaIssuerUrl{}, + Lint: NewSubCaIssuerUrl, }) } -func (l *subCaIssuerUrl) Initialize() error { - return nil +func NewSubCaIssuerUrl() lint.LintInterface { + return &subCaIssuerUrl{} } func (l *subCaIssuerUrl) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_marked_critical.go index 247a1b8bc..15379bf3f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_marked_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_marked_critical.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.ZeroDate, - Lint: &subCaAIAMarkedCritical{}, + Lint: NewSubCaAIAMarkedCritical, }) } -func (l *subCaAIAMarkedCritical) Initialize() error { - return nil +func NewSubCaAIAMarkedCritical() lint.LintInterface { + return &subCaAIAMarkedCritical{} } func (l *subCaAIAMarkedCritical) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_marked_critical.go index a0932fc24..0358ccff4 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_marked_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_marked_critical.go @@ -34,12 +34,12 @@ func init() { Citation: "BRs: 7.1.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCACertPolicyCrit{}, + Lint: NewSubCACertPolicyCrit, }) } -func (l *subCACertPolicyCrit) Initialize() error { - return nil +func NewSubCACertPolicyCrit() lint.LintInterface { + return &subCACertPolicyCrit{} } func (l *subCACertPolicyCrit) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_missing.go index 636274e3e..e025c01e2 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_certificate_policies_missing.go @@ -34,12 +34,12 @@ func init() { Citation: "BRs: 7.1.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCACertPolicyMissing{}, + Lint: NewSubCACertPolicyMissing, }) } -func (l *subCACertPolicyMissing) Initialize() error { - return nil +func NewSubCACertPolicyMissing() lint.LintInterface { + return &subCACertPolicyMissing{} } func (l *subCACertPolicyMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_does_not_contain_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_does_not_contain_url.go index 7e377534c..5544a966b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_does_not_contain_url.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_does_not_contain_url.go @@ -37,12 +37,12 @@ func init() { Citation: "BRs: 7.1.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCACRLDistNoUrl{}, + Lint: NewSubCACRLDistNoUrl, }) } -func (l *subCACRLDistNoUrl) Initialize() error { - return nil +func NewSubCACRLDistNoUrl() lint.LintInterface { + return &subCACRLDistNoUrl{} } func (l *subCACRLDistNoUrl) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_marked_critical.go index a04c39f76..884f791d9 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_marked_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_marked_critical.go @@ -35,12 +35,12 @@ func init() { Citation: "BRs: 7.1.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCACRLDistCrit{}, + Lint: NewSubCACRLDistCrit, }) } -func (l *subCACRLDistCrit) Initialize() error { - return nil +func NewSubCACRLDistCrit() lint.LintInterface { + return &subCACRLDistCrit{} } func (l *subCACRLDistCrit) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_missing.go index 7f1236183..91244962d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_crl_distribution_points_missing.go @@ -35,12 +35,12 @@ func init() { Citation: "BRs: 7.1.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCACRLDistMissing{}, + Lint: NewSubCACRLDistMissing, }) } -func (l *subCACRLDistMissing) Initialize() error { - return nil +func NewSubCACRLDistMissing() lint.LintInterface { + return &subCACRLDistMissing{} } func (l *subCACRLDistMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_critical.go index 5bb416d41..9cae37883 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_critical.go @@ -37,12 +37,12 @@ func init() { Citation: "BRs: 7.1.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV116Date, - Lint: &subCAEKUCrit{}, + Lint: NewSubCAEKUCrit, }) } -func (l *subCAEKUCrit) Initialize() error { - return nil +func NewSubCAEKUCrit() lint.LintInterface { + return &subCAEKUCrit{} } func (l *subCAEKUCrit) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_missing.go index 31add62b3..93c2f7385 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_missing.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.5", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCAEKUMissing{}, + Lint: NewSubCAEKUMissing, }) } -func (l *subCAEKUMissing) Initialize() error { - return nil +func NewSubCAEKUMissing() lint.LintInterface { + return &subCAEKUMissing{} } func (l *subCAEKUMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields.go index 1893dfcb2..875fd22c7 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_eku_valid_fields.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV116Date, - Lint: &subCAEKUValidFields{}, + Lint: NewSubCAEKUValidFields, }) } -func (l *subCAEKUValidFields) Initialize() error { - return nil +func NewSubCAEKUValidFields() lint.LintInterface { + return &subCAEKUValidFields{} } func (l *subCAEKUValidFields) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_name_constraints_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_name_constraints_not_critical.go index 24fb89932..fe6479e4b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_name_constraints_not_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_name_constraints_not_critical.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABV102Date, - Lint: &SubCANameConstraintsNotCritical{}, + Lint: NewSubCANameConstraintsNotCritical, }) } -func (l *SubCANameConstraintsNotCritical) Initialize() error { - return nil +func NewSubCANameConstraintsNotCritical() lint.LintInterface { + return &SubCANameConstraintsNotCritical{} } func (l *SubCANameConstraintsNotCritical) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_issuing_ca_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_issuing_ca_url.go index 2d8b98e34..c43a467e7 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_issuing_ca_url.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_issuing_ca_url.go @@ -38,12 +38,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCertIssuerUrl{}, + Lint: NewSubCertIssuerUrl, }) } -func (l *subCertIssuerUrl) Initialize() error { - return nil +func NewSubCertIssuerUrl() lint.LintInterface { + return &subCertIssuerUrl{} } func (l *subCertIssuerUrl) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_ocsp_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_ocsp_url.go index 3bbd9bb05..ad0bf1f42 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_ocsp_url.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_does_not_contain_ocsp_url.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCertOcspUrl{}, + Lint: NewSubCertOcspUrl, }) } -func (l *subCertOcspUrl) Initialize() error { - return nil +func NewSubCertOcspUrl() lint.LintInterface { + return &subCertOcspUrl{} } func (l *subCertOcspUrl) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_marked_critical.go index 7429b758e..aff407d1b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_marked_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_marked_critical.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCertAiaMarkedCritical{}, + Lint: NewSubCertAiaMarkedCritical, }) } -func (l *subCertAiaMarkedCritical) Initialize() error { - return nil +func NewSubCertAiaMarkedCritical() lint.LintInterface { + return &subCertAiaMarkedCritical{} } func (l *subCertAiaMarkedCritical) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_missing.go index 90278c403..2d4fb3d1f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_aia_missing.go @@ -38,12 +38,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCertAiaMissing{}, + Lint: NewSubCertAiaMissing, }) } -func (l *subCertAiaMissing) Initialize() error { - return nil +func NewSubCertAiaMissing() lint.LintInterface { + return &subCertAiaMissing{} } func (l *subCertAiaMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_cert_policy_empty.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_cert_policy_empty.go index 5da91655f..aad92ba16 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_cert_policy_empty.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_cert_policy_empty.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCertPolicyEmpty{}, + Lint: NewSubCertPolicyEmpty, }) } -func (l *subCertPolicyEmpty) Initialize() error { - return nil +func NewSubCertPolicyEmpty() lint.LintInterface { + return &subCertPolicyEmpty{} } func (l *subCertPolicyEmpty) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_marked_critical.go index da89e0f5e..4169b0f8d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_marked_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_marked_critical.go @@ -35,12 +35,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCertPolicyCrit{}, + Lint: NewSubCertPolicyCrit, }) } -func (l *subCertPolicyCrit) Initialize() error { - return nil +func NewSubCertPolicyCrit() lint.LintInterface { + return &subCertPolicyCrit{} } func (l *subCertPolicyCrit) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_missing.go index 95dbb20e8..ad1966447 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_certificate_policies_missing.go @@ -35,12 +35,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCertPolicy{}, + Lint: NewSubCertPolicy, }) } -func (l *subCertPolicy) Initialize() error { - return nil +func NewSubCertPolicy() lint.LintInterface { + return &subCertPolicy{} } func (l *subCertPolicy) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_country_name_must_appear.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_country_name_must_appear.go index 033407bc3..04dae16ce 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_country_name_must_appear.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_country_name_must_appear.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABGivenNameDate, - Lint: &subCertCountryNameMustAppear{}, + Lint: NewSubCertCountryNameMustAppear, }) } -func (l *subCertCountryNameMustAppear) Initialize() error { - return nil +func NewSubCertCountryNameMustAppear() lint.LintInterface { + return &subCertCountryNameMustAppear{} } func (l *subCertCountryNameMustAppear) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_does_not_contain_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_does_not_contain_url.go index 7e81f60b8..1daf79dce 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_does_not_contain_url.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_does_not_contain_url.go @@ -38,12 +38,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCRLDistNoURL{}, + Lint: NewSubCRLDistNoURL, }) } -func (l *subCRLDistNoURL) Initialize() error { - return nil +func NewSubCRLDistNoURL() lint.LintInterface { + return &subCRLDistNoURL{} } func (l *subCRLDistNoURL) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_marked_critical.go index aa4cc8caa..e97969276 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_marked_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_crl_distribution_points_marked_critical.go @@ -36,12 +36,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCrlDistCrit{}, + Lint: NewSubCrlDistCrit, }) } -func (l *subCrlDistCrit) Initialize() error { - return nil +func NewSubCrlDistCrit() lint.LintInterface { + return &subCrlDistCrit{} } func (l *subCrlDistCrit) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go index cd75f5958..197809a56 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_extra_values.go @@ -38,12 +38,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subExtKeyUsageLegalUsage{}, + Lint: NewSubExtKeyUsageLegalUsage, }) } -func (l *subExtKeyUsageLegalUsage) Initialize() error { - return nil +func NewSubExtKeyUsageLegalUsage() lint.LintInterface { + return &subExtKeyUsageLegalUsage{} } func (l *subExtKeyUsageLegalUsage) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_missing.go index b18bbad87..e769230fe 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_missing.go @@ -37,12 +37,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subExtKeyUsage{}, + Lint: NewSubExtKeyUsage, }) } -func (l *subExtKeyUsage) Initialize() error { - return nil +func NewSubExtKeyUsage() lint.LintInterface { + return &subExtKeyUsage{} } func (l *subExtKeyUsage) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go index 2ef26e02b..112824728 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_eku_server_auth_client_auth_missing.go @@ -38,12 +38,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subExtKeyUsageClientOrServer{}, + Lint: NewSubExtKeyUsageClientOrServer, }) } -func (l *subExtKeyUsageClientOrServer) Initialize() error { - return nil +func NewSubExtKeyUsageClientOrServer() lint.LintInterface { + return &subExtKeyUsageClientOrServer{} } func (l *subExtKeyUsageClientOrServer) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_gn_sn_contains_policy.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_gn_sn_contains_policy.go index e8d49a5a9..04625aca4 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_gn_sn_contains_policy.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_gn_sn_contains_policy.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABGivenNameDate, - Lint: &subCertSubjectGnOrSnContainsPolicy{}, + Lint: NewSubCertSubjectGnOrSnContainsPolicy, }) } -func (l *subCertSubjectGnOrSnContainsPolicy) Initialize() error { - return nil +func NewSubCertSubjectGnOrSnContainsPolicy() lint.LintInterface { + return &subCertSubjectGnOrSnContainsPolicy{} } func (l *subCertSubjectGnOrSnContainsPolicy) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_is_ca.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_is_ca.go index 0c014483d..c92d6522b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_is_ca.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_is_ca.go @@ -15,8 +15,7 @@ package cabf_br */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -31,12 +30,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCertNotCA{}, + Lint: NewSubCertNotCA, }) } -func (l *subCertNotCA) Initialize() error { - return nil +func NewSubCertNotCA() lint.LintInterface { + return &subCertNotCA{} } func (l *subCertNotCA) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_cert_sign_bit_set.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_cert_sign_bit_set.go index 584b8a9fb..5ba2ea32c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_cert_sign_bit_set.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_cert_sign_bit_set.go @@ -35,12 +35,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCertKeyUsageBitSet{}, + Lint: NewSubCertKeyUsageBitSet, }) } -func (l *subCertKeyUsageBitSet) Initialize() error { - return nil +func NewSubCertKeyUsageBitSet() lint.LintInterface { + return &subCertKeyUsageBitSet{} } func (l *subCertKeyUsageBitSet) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_crl_sign_bit_set.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_crl_sign_bit_set.go index fb44f79ba..e802927d4 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_crl_sign_bit_set.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_key_usage_crl_sign_bit_set.go @@ -35,12 +35,12 @@ func init() { Citation: "BRs: 7.1.2.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subCrlSignAllowed{}, + Lint: NewSubCrlSignAllowed, }) } -func (l *subCrlSignAllowed) Initialize() error { - return nil +func NewSubCrlSignAllowed() lint.LintInterface { + return &subCrlSignAllowed{} } func (l *subCrlSignAllowed) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_appear.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_appear.go index 6333100d5..179bd3c3b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_appear.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_appear.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABGivenNameDate, - Lint: &subCertLocalityNameMustAppear{}, + Lint: NewSubCertLocalityNameMustAppear, }) } -func (l *subCertLocalityNameMustAppear) Initialize() error { - return nil +func NewSubCertLocalityNameMustAppear() lint.LintInterface { + return &subCertLocalityNameMustAppear{} } func (l *subCertLocalityNameMustAppear) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_not_appear.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_not_appear.go index eca2b8539..a55098115 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_not_appear.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_locality_name_must_not_appear.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABGivenNameDate, - Lint: &subCertLocalityNameMustNotAppear{}, + Lint: NewSubCertLocalityNameMustNotAppear, }) } -func (l *subCertLocalityNameMustNotAppear) Initialize() error { - return nil +func NewSubCertLocalityNameMustNotAppear() lint.LintInterface { + return &subCertLocalityNameMustNotAppear{} } func (l *subCertLocalityNameMustNotAppear) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_or_sub_ca_using_sha1.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_or_sub_ca_using_sha1.go index 157ce654e..dcecee34c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_or_sub_ca_using_sha1.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_or_sub_ca_using_sha1.go @@ -34,12 +34,12 @@ func init() { Citation: "BRs: 7.1.3", Source: lint.CABFBaselineRequirements, EffectiveDate: util.NO_SHA1, - Lint: &sigAlgTestsSHA1{}, + Lint: NewSigAlgTestsSHA1, }) } -func (l *sigAlgTestsSHA1) Initialize() error { - return nil +func NewSigAlgTestsSHA1() lint.LintInterface { + return &sigAlgTestsSHA1{} } func (l *sigAlgTestsSHA1) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_postal_code_prohibited.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_postal_code_prohibited.go index f62129005..16f5c3d81 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_postal_code_prohibited.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_postal_code_prohibited.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABGivenNameDate, - Lint: &subCertPostalCodeMustNotAppear{}, + Lint: NewSubCertPostalCodeMustNotAppear, }) } -func (l *subCertPostalCodeMustNotAppear) Initialize() error { - return nil +func NewSubCertPostalCodeMustNotAppear() lint.LintInterface { + return &subCertPostalCodeMustNotAppear{} } func (l *subCertPostalCodeMustNotAppear) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_appear.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_appear.go index ec4603930..81ba9aabf 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_appear.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_appear.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABGivenNameDate, - Lint: &subCertProvinceMustAppear{}, + Lint: NewSubCertProvinceMustAppear, }) } -func (l *subCertProvinceMustAppear) Initialize() error { - return nil +func NewSubCertProvinceMustAppear() lint.LintInterface { + return &subCertProvinceMustAppear{} } func (l *subCertProvinceMustAppear) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_not_appear.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_not_appear.go index b61fdca2e..c0bd32dd4 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_not_appear.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_province_must_not_appear.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABGivenNameDate, - Lint: &subCertProvinceMustNotAppear{}, + Lint: NewSubCertProvinceMustNotAppear, }) } -func (l *subCertProvinceMustNotAppear) Initialize() error { - return nil +func NewSubCertProvinceMustNotAppear() lint.LintInterface { + return &subCertProvinceMustNotAppear{} } func (l *subCertProvinceMustNotAppear) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_sha1_expiration_too_long.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_sha1_expiration_too_long.go index 533584d17..69efa499d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_sha1_expiration_too_long.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_sha1_expiration_too_long.go @@ -37,13 +37,13 @@ func init() { Description: "Subscriber certificates using the SHA-1 algorithm SHOULD NOT have an expiration date later than 1 Jan 2017", Citation: "BRs: 7.1.3", Source: lint.CABFBaselineRequirements, - EffectiveDate: time.Date(2015, time.January, 16, 0, 0, 0, 0, time.UTC), - Lint: &sha1ExpireLong{}, + EffectiveDate: util.CABFBRs_1_2_1_Date, + Lint: NewSha1ExpireLong, }) } -func (l *sha1ExpireLong) Initialize() error { - return nil +func NewSha1ExpireLong() lint.LintInterface { + return &sha1ExpireLong{} } func (l *sha1ExpireLong) CheckApplies(c *x509.Certificate) bool { @@ -52,8 +52,10 @@ func (l *sha1ExpireLong) CheckApplies(c *x509.Certificate) bool { c.SignatureAlgorithm == x509.ECDSAWithSHA1) } +var sha1SunsetDate = time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC) + func (l *sha1ExpireLong) Execute(c *x509.Certificate) *lint.LintResult { - if c.NotAfter.After(time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC)) { + if c.NotAfter.After(sha1SunsetDate) { return &lint.LintResult{Status: lint.Warn} } else { return &lint.LintResult{Status: lint.Pass} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_street_address_should_not_exist.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_street_address_should_not_exist.go index 9f3b39c7a..3ce211338 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_street_address_should_not_exist.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_street_address_should_not_exist.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABGivenNameDate, - Lint: &subCertStreetAddressShouldNotExist{}, + Lint: NewSubCertStreetAddressShouldNotExist, }) } -func (l *subCertStreetAddressShouldNotExist) Initialize() error { - return nil +func NewSubCertStreetAddressShouldNotExist() lint.LintInterface { + return &subCertStreetAddressShouldNotExist{} } func (l *subCertStreetAddressShouldNotExist) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_39_months.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_39_months.go index 9a2e8d8fd..00d8a76d5 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_39_months.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_39_months.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 6.3.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.SubCert39Month, - Lint: &subCertValidTimeLongerThan39Months{}, + Lint: NewSubCertValidTimeLongerThan39Months, }) } -func (l *subCertValidTimeLongerThan39Months) Initialize() error { - return nil +func NewSubCertValidTimeLongerThan39Months() lint.LintInterface { + return &subCertValidTimeLongerThan39Months{} } func (l *subCertValidTimeLongerThan39Months) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_825_days.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_825_days.go index 687a1c50e..4c1644071 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_825_days.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_cert_valid_time_longer_than_825_days.go @@ -29,12 +29,12 @@ func init() { Citation: "BRs: 6.3.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.SubCert825Days, - Lint: &subCertValidTimeLongerThan825Days{}, + Lint: NewSubCertValidTimeLongerThan825Days, }) } -func (l *subCertValidTimeLongerThan825Days) Initialize() error { - return nil +func NewSubCertValidTimeLongerThan825Days() lint.LintInterface { + return &subCertValidTimeLongerThan825Days{} } func (l *subCertValidTimeLongerThan825Days) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_included.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_included.go index 9ded4d9b9..03f194e02 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_included.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_included.go @@ -34,12 +34,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &commonNames{}, + Lint: NewCommonNames, }) } -func (l *commonNames) Initialize() error { - return nil +func NewCommonNames() lint.LintInterface { + return &commonNames{} } func (l *commonNames) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_not_exactly_from_san.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_not_exactly_from_san.go new file mode 100644 index 000000000..0c6acfdee --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_not_exactly_from_san.go @@ -0,0 +1,82 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type subjectCommonNameNotExactlyFromSAN struct{} + +/************************************************ +If present, this field MUST contain exactly one entry that is one of the values contained +in the Certificate's `subjectAltName` extension + +If the [subject:commonName] is a Fully-Qualified Domain Name or Wildcard Domain Name, then +the value MUST be encoded as a character-for-character copy of the dNSName entry value from +the subjectAltName extension. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_common_name_not_exactly_from_san", + Description: "The common name field in subscriber certificates must include only names from the SAN extension", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABFBRs_1_8_0_Date, + Lint: NewSubjectCommonNameNotExactlyFromSAN, + }) +} + +func NewSubjectCommonNameNotExactlyFromSAN() lint.LintInterface { + return &subjectCommonNameNotExactlyFromSAN{} +} + +func (l *subjectCommonNameNotExactlyFromSAN) CheckApplies(c *x509.Certificate) bool { + return len(c.Subject.CommonNames) > 0 && !util.IsCACert(c) +} + +func (l *subjectCommonNameNotExactlyFromSAN) Execute(c *x509.Certificate) *lint.LintResult { + for _, cn := range c.Subject.CommonNames { + var cnFound = false + for _, dn := range c.DNSNames { + if cn == dn { + cnFound = true + break + } + } + if cnFound { + continue + } + + for _, ip := range c.IPAddresses { + if cn == ip.String() { + cnFound = true + break + } + } + if cnFound { + continue + } + + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("Missing common name, '%s'", cn)} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_not_from_san.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_not_from_san.go index ae8f382b8..305f17189 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_not_from_san.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_common_name_not_from_san.go @@ -33,17 +33,18 @@ contained in the Certificate’s subjectAltName extension (see Section 7.1.4.2.1 func init() { lint.RegisterLint(&lint.Lint{ - Name: "e_subject_common_name_not_from_san", - Description: "The common name field in subscriber certificates must include only names from the SAN extension", - Citation: "BRs: 7.1.4.2.2", - Source: lint.CABFBaselineRequirements, - EffectiveDate: util.CABEffectiveDate, - Lint: &subjectCommonNameNotFromSAN{}, + Name: "e_subject_common_name_not_from_san", + Description: "The common name field in subscriber certificates must include only names from the SAN extension", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + IneffectiveDate: util.CABFBRs_1_8_0_Date, + Lint: NewSubjectCommonNameNotFromSAN, }) } -func (l *subjectCommonNameNotFromSAN) Initialize() error { - return nil +func NewSubjectCommonNameNotFromSAN() lint.LintInterface { + return &subjectCommonNameNotFromSAN{} } func (l *subjectCommonNameNotFromSAN) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_malformed_arpa_ip.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_malformed_arpa_ip.go index 6ecea2ff0..fac5422d6 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_malformed_arpa_ip.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_malformed_arpa_ip.go @@ -48,15 +48,16 @@ func init() { Citation: "BRs: 3.2.2.6", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &arpaMalformedIP{}, + Lint: NewArpaMalformedIP, }) } +func NewArpaMalformedIP() lint.LintInterface { + return &arpaMalformedIP{} +} + // Initialize for an arpaMalformedIP linter is a NOP to statisfy linting // interfaces. -func (l *arpaMalformedIP) Initialize() error { - return nil -} // CheckApplies returns true if the certificate contains any names that end in // one of the two designated zones for reverse DNS: in-addr.arpa or ip6.arpa. diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_noninformational_value.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_noninformational_value.go index fefe63e20..f622e5312 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_noninformational_value.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_noninformational_value.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &illegalChar{}, + Lint: NewIllegalChar, }) } -func (l *illegalChar) Initialize() error { - return nil +func NewIllegalChar() lint.LintInterface { + return &illegalChar{} } func (l *illegalChar) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_organizational_unit_name_and_no_organization_name.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_organizational_unit_name_and_no_organization_name.go new file mode 100644 index 000000000..9f49f8e10 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_organizational_unit_name_and_no_organization_name.go @@ -0,0 +1,60 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type SubjectContainsOrganizationalUnitNameButNoOrganizationName struct{} + +/************************************************ +BRs: 7.1.4.2.2 +Certificate Field: subject:organizationalUnitName (OID: 2.5.4.11) +Required/Optional: Deprecated. Prohibited if the +subject:organizationName is absent or the certificate is issued on or after +September 1, 2022. +This lint check the first requirement, i.e.: Prohibited if the subject:organizationName is absent. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_contains_organizational_unit_name_and_no_organization_name", + Description: "If a subject organization name is absent then an organizational unit name MUST NOT be included in subject", + Citation: "BRs: 7.1.4.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABFBRs_1_7_9_Date, + Lint: NewSubjectContainsOrganizationalUnitNameButNoOrganizationName, + }) +} + +func NewSubjectContainsOrganizationalUnitNameButNoOrganizationName() lint.LintInterface { + return &SubjectContainsOrganizationalUnitNameButNoOrganizationName{} +} + +func (l *SubjectContainsOrganizationalUnitNameButNoOrganizationName) CheckApplies(cert *x509.Certificate) bool { + return util.TypeInName(&cert.Subject, util.OrganizationalUnitNameOID) +} + +func (l *SubjectContainsOrganizationalUnitNameButNoOrganizationName) Execute(cert *x509.Certificate) *lint.LintResult { + + if !util.TypeInName(&cert.Subject, util.OrganizationNameOID) { + return &lint.LintResult{Status: lint.Error, Details: "subject:organizationalUnitName is prohibited if subject:organizationName is absent"} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_arpa_ip.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_arpa_ip.go index 37b2d69f7..3410cec12 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_arpa_ip.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_arpa_ip.go @@ -61,15 +61,16 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &arpaReservedIP{}, + Lint: NewArpaReservedIP, }) } +func NewArpaReservedIP() lint.LintInterface { + return &arpaReservedIP{} +} + // Initialize for an arpaReservedIP linter is a NOP to statisfy linting // interfaces. -func (l *arpaReservedIP) Initialize() error { - return nil -} // CheckApplies returns true if the certificate contains any names that end in // one of the two designated zones for reverse DNS: in-addr.arpa or ip6.arpa. diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_ip.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_ip.go index 6547857bc..e35c9d849 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_ip.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_contains_reserved_ip.go @@ -40,12 +40,12 @@ func init() { Citation: "BRs: 7.1.4.2.1", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &subjectReservedIP{}, + Lint: NewSubjectReservedIP, }) } -func (l *subjectReservedIP) Initialize() error { - return nil +func NewSubjectReservedIP() lint.LintInterface { + return &subjectReservedIP{} } func (l *subjectReservedIP) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_country_not_iso.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_country_not_iso.go index 71389890f..306193dad 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_country_not_iso.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_country_not_iso.go @@ -39,12 +39,12 @@ func init() { Citation: "BRs: 7.1.4.2.2", Source: lint.CABFBaselineRequirements, EffectiveDate: util.CABEffectiveDate, - Lint: &countryNotIso{}, + Lint: NewCountryNotIso, }) } -func (l *countryNotIso) Initialize() error { - return nil +func NewCountryNotIso() lint.LintInterface { + return &countryNotIso{} } func (l *countryNotIso) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_public_key_info_improper_algorithm_object_identifier_encoding.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_public_key_info_improper_algorithm_object_identifier_encoding.go new file mode 100644 index 000000000..315580135 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_subject_public_key_info_improper_algorithm_object_identifier_encoding.go @@ -0,0 +1,88 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "bytes" + "encoding/hex" + "fmt" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type algorithmObjectIdentifierEncoding struct{} + +/************************************************ +This lint refers to CAB Baseline Requirements (Version 1.7.4) chapter 7.1.3.1, which defines the +required encodings of AlgorithmObjectIdentifiers inside a SubjectPublicKeyInfo field. + +Section 7.1.3.1.1: When encoded, the AlgorithmIdentifier for RSA keys MUST be byte‐for‐byte +identical with the following hex‐encoded bytes: 300d06092a864886f70d0101010500 + +Section 7.1.3.1.2: When encoded, the AlgorithmIdentifier for ECDSA keys MUST be +byte‐for‐byte identical with the following hex‐encoded bytes: +For P‐256 keys: 301306072a8648ce3d020106082a8648ce3d030107 +For P‐384 keys: 301006072a8648ce3d020106052b81040022 +For P‐521 keys: 301006072a8648ce3d020106052b81040023 +************************************************/ +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_algorithm_identifier_improper_encoding", + Description: "Encoded AlgorithmObjectIdentifier objects inside a SubjectPublicKeyInfo field " + + "MUST comply with specified byte sequences.", + Citation: "BRs: 7.1.3.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABFBRs_1_7_1_Date, + Lint: NewAlgorithmObjectIdentifierEncoding, + }) +} + +func NewAlgorithmObjectIdentifierEncoding() lint.LintInterface { + return &algorithmObjectIdentifierEncoding{} +} + +var allowedPublicKeyEncodings = [4][]byte{ + // encoded AlgorithmIdentifier for an RSA key + {0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00}, + // encoded AlgorithmIdentifier for a P-256 key + {0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}, + // encoded AlgorithmIdentifier for a P-384 key + {0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22}, + // encoded AlgorithmIdentifier for a P-521 key + {0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23}, +} + +func (l *algorithmObjectIdentifierEncoding) CheckApplies(c *x509.Certificate) bool { + // always check if the public key is one of the four explicitly specified encodings + return true +} + +func (l *algorithmObjectIdentifierEncoding) Execute(c *x509.Certificate) *lint.LintResult { + + rawAlgorithmIdentifier, err := util.GetPublicKeyAidEncoded(c) + if err != nil { + return &lint.LintResult{Status: lint.Fatal, Details: "error parsing SubjectPublicKeyInfo"} + } + + for _, encoding := range allowedPublicKeyEncodings { + if bytes.Equal(rawAlgorithmIdentifier, encoding) { + return &lint.LintResult{Status: lint.Pass} + } + } + + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("The encoded AlgorithmObjectIdentifier %q inside the SubjectPublicKeyInfo field is not allowed", hex.EncodeToString(rawAlgorithmIdentifier))} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_underscore_not_permissible_in_dnsname.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_underscore_not_permissible_in_dnsname.go new file mode 100644 index 000000000..a81b1ba3a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_underscore_not_permissible_in_dnsname.go @@ -0,0 +1,54 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_br + +import ( + "fmt" + "strings" + + "github.com/zmap/zlint/v3/util" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" +) + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_underscore_not_permissible_in_dnsname", + Description: "DNSNames MUST NOT contain underscore characters", + Citation: "BR 7.1.4.2.1", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABFBRs_1_6_2_UnderscorePermissibilitySunsetDate, + Lint: func() lint.LintInterface { return &UnderscoreNotPermissibleInDNSName{} }, + }) +} + +type UnderscoreNotPermissibleInDNSName struct{} + +func (l *UnderscoreNotPermissibleInDNSName) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *UnderscoreNotPermissibleInDNSName) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + if strings.Contains(dns, "_") { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("The DNS name '%s' contains an underscore (_) character", dns), + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_sub_ca_aia_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_sub_ca_aia_missing.go new file mode 100644 index 000000000..6b09cb6e4 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_sub_ca_aia_missing.go @@ -0,0 +1,58 @@ +package cabf_br + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type caAiaShouldNotBeMissing struct{} + +/*********************************************** +CAB BR 1.7.1 Section 7.1.2.2c - authorityInformationAccess +This extension SHOULD be present. It MUST NOT be marked critical. +It SHOULD contain the HTTP URL of the Issuing CA’s certificate (accessMethod = +1.3.6.1.5.5.7.48.2). It MAY contain the HTTP URL of the Issuing CA’s OCSP responder +(accessMethod = 1.3.6.1.5.5.7.48.1). +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_sub_ca_aia_missing", + Description: "Subordinate CA Certificate: authorityInformationAccess SHOULD be present.", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABFBRs_1_7_1_Date, + Lint: NewCaAiaShouldNotBeMissing, + }) +} + +func NewCaAiaShouldNotBeMissing() lint.LintInterface { + return &caAiaShouldNotBeMissing{} +} + +func (l *caAiaShouldNotBeMissing) CheckApplies(c *x509.Certificate) bool { + return util.IsCACert(c) && !util.IsRootCA(c) +} + +func (l *caAiaShouldNotBeMissing) Execute(c *x509.Certificate) *lint.LintResult { + if util.IsExtInCert(c, util.AiaOID) { + return &lint.LintResult{Status: lint.Pass} + } else { + return &lint.LintResult{Status: lint.Warn} + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_business_category_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_business_category_missing.go index 469b12c3e..1e16216a2 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_business_category_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_business_category_missing.go @@ -29,12 +29,12 @@ func init() { Citation: "EVGs: 9.2.3", Source: lint.CABFEVGuidelines, EffectiveDate: util.ZeroDate, - Lint: &evNoBiz{}, + Lint: NewEvNoBiz, }) } -func (l *evNoBiz) Initialize() error { - return nil +func NewEvNoBiz() lint.LintInterface { + return &evNoBiz{} } func (l *evNoBiz) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_country_name_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_country_name_missing.go index fe9d71557..6763501f7 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_country_name_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_country_name_missing.go @@ -29,12 +29,12 @@ func init() { Citation: "EVGs: 9.2.4", Source: lint.CABFEVGuidelines, EffectiveDate: util.ZeroDate, - Lint: &evCountryMissing{}, + Lint: NewEvCountryMissing, }) } -func (l *evCountryMissing) Initialize() error { - return nil +func NewEvCountryMissing() lint.LintInterface { + return &evCountryMissing{} } func (l *evCountryMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_not_wildcard.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_not_wildcard.go new file mode 100644 index 000000000..12c55ec6d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_not_wildcard.go @@ -0,0 +1,58 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_ev + +import ( + "fmt" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ev_not_wildcard", + Description: "Wildcard certificates are not allowed for EV Certificates except for those with .onion as the TLD.", + Citation: "CABF EV Guidelines 1.7.8 Section 9.8.1", + Source: lint.CABFEVGuidelines, + EffectiveDate: util.OnionOnlyEVDate, + Lint: NewEvNotWildCard, + }) +} + +type EvNotWildCard struct{} + +func NewEvNotWildCard() lint.LintInterface { + return &EvNotWildCard{} +} + +func (l *EvNotWildCard) CheckApplies(c *x509.Certificate) bool { + return util.IsEV(c.PolicyIdentifiers) +} + +func (l *EvNotWildCard) Execute(c *x509.Certificate) *lint.LintResult { + names := append(c.GetParsedDNSNames(false), c.GetParsedSubjectCommonName(false)) + for _, name := range names { + if name.ParseError != nil { + continue + } + if strings.Contains(name.DomainString, "*") && !strings.HasSuffix(name.DomainString, util.OnionTLD) { + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("'%s' appears to be a wildcard domain", name.DomainString)} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_id_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_id_missing.go index fca799b72..26cacc80f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_id_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_id_missing.go @@ -30,12 +30,12 @@ func init() { Citation: "CA/Browser Forum EV Guidelines v1.7.0, Sec. 9.8.2", Source: lint.CABFEVGuidelines, EffectiveDate: util.CABFEV_9_8_2, - Lint: &evOrgIdExtMissing{}, + Lint: NewEvOrgIdExtMissing, }) } -func (l *evOrgIdExtMissing) Initialize() error { - return nil +func NewEvOrgIdExtMissing() lint.LintInterface { + return &evOrgIdExtMissing{} } func (l *evOrgIdExtMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_name_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_name_missing.go index 34ceb20bf..ecd64eac8 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_name_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_organization_name_missing.go @@ -29,12 +29,12 @@ func init() { Citation: "EVGs: 9.2.1", Source: lint.CABFEVGuidelines, EffectiveDate: util.ZeroDate, - Lint: &evOrgMissing{}, + Lint: NewEvOrgMissing, }) } -func (l *evOrgMissing) Initialize() error { - return nil +func NewEvOrgMissing() lint.LintInterface { + return &evOrgMissing{} } func (l *evOrgMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_san_ip_address_present.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_san_ip_address_present.go new file mode 100644 index 000000000..7e9deafe8 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_san_ip_address_present.go @@ -0,0 +1,49 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_ev + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ev_san_ip_address_present", + Description: "The Subject Alternate Name extension MUST contain only 'dnsName' name types.", + Citation: "CABF EV Guidelines 1.7.8 Section 9.8.1", + Source: lint.CABFEVGuidelines, + EffectiveDate: util.ZeroDate, + Lint: NewEvSanIpAddressPresent, + }) +} + +type EvSanIpAddressPresent struct{} + +func NewEvSanIpAddressPresent() lint.LintInterface { + return &EvSanIpAddressPresent{} +} + +func (l *EvSanIpAddressPresent) CheckApplies(c *x509.Certificate) bool { + return util.IsEV(c.PolicyIdentifiers) +} + +func (l *EvSanIpAddressPresent) Execute(c *x509.Certificate) *lint.LintResult { + if len(c.IPAddresses) > 0 { + return &lint.LintResult{Status: lint.Error} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_serial_number_missing.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_serial_number_missing.go index bfbfb04ad..bb0a5bca4 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_serial_number_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_serial_number_missing.go @@ -29,12 +29,12 @@ func init() { Citation: "EVGs: 9.2.6", Source: lint.CABFEVGuidelines, EffectiveDate: util.ZeroDate, - Lint: &evSNMissing{}, + Lint: NewEvSNMissing, }) } -func (l *evSNMissing) Initialize() error { - return nil +func NewEvSNMissing() lint.LintInterface { + return &evSNMissing{} } func (l *evSNMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_valid_time_too_long.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_valid_time_too_long.go index e796a443a..67b4cded4 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_valid_time_too_long.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_ev_valid_time_too_long.go @@ -29,12 +29,12 @@ func init() { Citation: "EVGs 1.0: 8(a), EVGs 1.6.1: 9.4", Source: lint.CABFEVGuidelines, EffectiveDate: util.ZeroDate, - Lint: &evValidTooLong{}, + Lint: NewEvValidTooLong, }) } -func (l *evValidTooLong) Initialize() error { - return nil +func NewEvValidTooLong() lint.LintInterface { + return &evValidTooLong{} } func (l *evValidTooLong) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_onion_subject_validity_time_too_large.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_onion_subject_validity_time_too_large.go index 1efedcb00..83672ee42 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_onion_subject_validity_time_too_large.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_ev/lint_onion_subject_validity_time_too_large.go @@ -41,15 +41,16 @@ func init() { Citation: "EVGs: Appendix F", Source: lint.CABFEVGuidelines, EffectiveDate: util.OnionOnlyEVDate, - Lint: &torValidityTooLarge{}, + Lint: NewTorValidityTooLarge, }) } -// Initialize for a torValidityTooLarge linter is a NOP. -func (l *torValidityTooLarge) Initialize() error { - return nil +func NewTorValidityTooLarge() lint.LintInterface { + return &torValidityTooLarge{} } +// Initialize for a torValidityTooLarge linter is a NOP. + // CheckApplies returns true if the certificate is a subscriber certificate that // contains a subject name ending in `.onion`. func (l *torValidityTooLarge) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_bare_wildcard.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_bare_wildcard.go index 6629efb37..29870e50b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_bare_wildcard.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_bare_wildcard.go @@ -31,12 +31,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &brIANBareWildcard{}, + Lint: NewBrIANBareWildcard, }) } -func (l *brIANBareWildcard) Initialize() error { - return nil +func NewBrIANBareWildcard() lint.LintInterface { + return &brIANBareWildcard{} } func (l *brIANBareWildcard) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_includes_null_char.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_includes_null_char.go index 9e29904b6..5b21e7dfc 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_includes_null_char.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_includes_null_char.go @@ -29,12 +29,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &IANDNSNull{}, + Lint: NewIANDNSNull, }) } -func (l *IANDNSNull) Initialize() error { - return nil +func NewIANDNSNull() lint.LintInterface { + return &IANDNSNull{} } func (l *IANDNSNull) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_starts_with_period.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_starts_with_period.go index e42fd7756..d81e57c10 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_starts_with_period.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_dns_name_starts_with_period.go @@ -31,12 +31,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &IANDNSPeriod{}, + Lint: NewIANDNSPeriod, }) } -func (l *IANDNSPeriod) Initialize() error { - return nil +func NewIANDNSPeriod() lint.LintInterface { + return &IANDNSPeriod{} } func (l *IANDNSPeriod) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_iana_pub_suffix_empty.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_iana_pub_suffix_empty.go index 290425045..e733445c5 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_iana_pub_suffix_empty.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_iana_pub_suffix_empty.go @@ -31,12 +31,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &IANPubSuffix{}, + Lint: NewIANPubSuffix, }) } -func (l *IANPubSuffix) Initialize() error { - return nil +func NewIANPubSuffix() lint.LintInterface { + return &IANPubSuffix{} } func (l *IANPubSuffix) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_wildcard_not_first.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_wildcard_not_first.go index e9a4693b9..b93f9de1c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_wildcard_not_first.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_ian_wildcard_not_first.go @@ -29,12 +29,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &brIANWildcardFirst{}, + Lint: NewBrIANWildcardFirst, }) } -func (l *brIANWildcardFirst) Initialize() error { - return nil +func NewBrIANWildcardFirst() lint.LintInterface { + return &brIANWildcardFirst{} } func (l *brIANWildcardFirst) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_is_redacted_cert.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_is_redacted_cert.go index 74910d67a..0612a3bec 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_is_redacted_cert.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_is_redacted_cert.go @@ -31,12 +31,12 @@ func init() { Source: lint.Community, Citation: "IETF Draft: https://tools.ietf.org/id/draft-strad-trans-redaction-00.html", EffectiveDate: util.ZeroDate, - Lint: &DNSNameRedacted{}, + Lint: NewDNSNameRedacted, }) } -func (l *DNSNameRedacted) Initialize() error { - return nil +func NewDNSNameRedacted() lint.LintInterface { + return &DNSNameRedacted{} } func (l *DNSNameRedacted) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_leading_whitespace.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_leading_whitespace.go index 7c87b5195..6fe3646ed 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_leading_whitespace.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_leading_whitespace.go @@ -29,12 +29,12 @@ func init() { Citation: "lint.AWSLabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &IssuerDNLeadingSpace{}, + Lint: NewIssuerDNLeadingSpace, }) } -func (l *IssuerDNLeadingSpace) Initialize() error { - return nil +func NewIssuerDNLeadingSpace() lint.LintInterface { + return &IssuerDNLeadingSpace{} } func (l *IssuerDNLeadingSpace) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_trailing_whitespace.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_trailing_whitespace.go index 67c69206b..3f24a3bfc 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_trailing_whitespace.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_dn_trailing_whitespace.go @@ -29,12 +29,12 @@ func init() { Citation: "lint.AWSLabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &IssuerDNTrailingSpace{}, + Lint: NewIssuerDNTrailingSpace, }) } -func (l *IssuerDNTrailingSpace) Initialize() error { - return nil +func NewIssuerDNTrailingSpace() lint.LintInterface { + return &IssuerDNTrailingSpace{} } func (l *IssuerDNTrailingSpace) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_multiple_rdn.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_multiple_rdn.go index 780e65100..56b20cc08 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_multiple_rdn.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_issuer_multiple_rdn.go @@ -15,8 +15,7 @@ package community */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zcrypto/x509/pkix" "github.com/zmap/zlint/v3/lint" @@ -32,12 +31,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &IssuerRDNHasMultipleAttribute{}, + Lint: NewIssuerRDNHasMultipleAttribute, }) } -func (l *IssuerRDNHasMultipleAttribute) Initialize() error { - return nil +func NewIssuerRDNHasMultipleAttribute() lint.LintInterface { + return &IssuerRDNHasMultipleAttribute{} } func (l *IssuerRDNHasMultipleAttribute) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_exp_negative.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_exp_negative.go index 03e948715..870fad637 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_exp_negative.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_exp_negative.go @@ -31,12 +31,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &rsaExpNegative{}, + Lint: NewRsaExpNegative, }) } -func (l *rsaExpNegative) Initialize() error { - return nil +func NewRsaExpNegative() lint.LintInterface { + return &rsaExpNegative{} } func (l *rsaExpNegative) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_fermat_factorization.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_fermat_factorization.go new file mode 100644 index 000000000..76ed8c526 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_fermat_factorization.go @@ -0,0 +1,121 @@ +package community + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "crypto/rsa" + "fmt" + "math/big" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type fermatFactorization struct { + Rounds int `comment:"The number of iterations to attempt Fermat factorization. Note that when executing this lint against many (tens of thousands of certificates) that this configuration may have a profound affect on performance. For more information, please see https://fermatattack.secvuln.info/"` +} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rsa_fermat_factorization", + Description: "RSA key pairs that are too close to each other are susceptible to the Fermat Factorization " + + "Method (for more information please see https://en.wikipedia.org/wiki/Fermat%27s_factorization_method " + + "and https://fermatattack.secvuln.info/)", + Citation: "Pierre de Fermat", + Source: lint.Community, + EffectiveDate: util.ZeroDate, + Lint: NewFermatFactorization, + }) +} + +func NewFermatFactorization() lint.LintInterface { + return &fermatFactorization{Rounds: 100} +} + +func (l *fermatFactorization) Configure() interface{} { + return l +} + +func (l *fermatFactorization) CheckApplies(c *x509.Certificate) bool { + _, ok := c.PublicKey.(*rsa.PublicKey) + return ok && c.PublicKeyAlgorithm == x509.RSA +} + +func (l *fermatFactorization) Execute(c *x509.Certificate) *lint.LintResult { + err := checkPrimeFactorsTooClose(c.PublicKey.(*rsa.PublicKey).N, l.Rounds) + if err != nil { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("this certificate's RSA key pair is susceptible to Fermat factorization, %s", err.Error())} + } else { + return &lint.LintResult{Status: lint.Pass} + } +} + +// Source: Let's Encrypt, Boulder +// Author: Aaron Gable (https://github.com/aarongable) +// Commit: https://github.com/letsencrypt/boulder/commit/89000bd61cfc6f373cb48b6f046d4fce7df5468e +// +// Returns an error if the modulus n is able to be factored into primes p and q +// via Fermat's factorization method. This method relies on the two primes being +// very close together, which means that they were almost certainly not picked +// independently from a uniform random distribution. Basically, if we can factor +// the key this easily, so can anyone else. +func checkPrimeFactorsTooClose(n *big.Int, rounds int) error { + // Pre-allocate some big numbers that we'll use a lot down below. + one := big.NewInt(1) + bb := new(big.Int) + + // Any odd integer is equal to a difference of squares of integers: + // n = a^2 - b^2 = (a + b)(a - b) + // Any RSA public key modulus is equal to a product of two primes: + // n = pq + // Here we try to find values for a and b, since doing so also gives us the + // prime factors p = (a + b) and q = (a - b). + + // We start with a close to the square root of the modulus n, to start with + // two candidate prime factors that are as close together as possible and + // work our way out from there. Specifically, we set a = ceil(sqrt(n)), the + // first integer greater than the square root of n. Unfortunately, big.Int's + // built-in square root function takes the floor, so we have to add one to get + // the ceil. + a := new(big.Int) + a.Sqrt(n).Add(a, one) + + // We calculate b2 to see if it is a perfect square (i.e. b^2), and therefore + // b is an integer. Specifically, b2 = a^2 - n. + b2 := new(big.Int) + b2.Mul(a, a).Sub(b2, n) + + for i := 0; i < rounds; i++ { + // To see if b2 is a perfect square, we take its square root, square that, + // and check to see if we got the same result back. + bb.Sqrt(b2).Mul(bb, bb) + if b2.Cmp(bb) == 0 { + // b2 is a perfect square, so we've found integer values of a and b, + // and can easily compute p and q as their sum and difference. + bb.Sqrt(bb) + p := new(big.Int).Add(a, bb) + q := new(big.Int).Sub(a, bb) + return fmt.Errorf("public modulus n = pq factored into p: %s; q: %s", p, q) + } + + // Set up the next iteration by incrementing a by one and recalculating b2. + a.Add(a, one) + b2.Mul(a, a).Sub(b2, n) + } + return nil +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_no_public_key.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_no_public_key.go index 9b2eb1442..c53256719 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_no_public_key.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_rsa_no_public_key.go @@ -31,12 +31,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &rsaParsedPubKeyExist{}, + Lint: NewRsaParsedPubKeyExist, }) } -func (l *rsaParsedPubKeyExist) Initialize() error { - return nil +func NewRsaParsedPubKeyExist() lint.LintInterface { + return &rsaParsedPubKeyExist{} } func (l *rsaParsedPubKeyExist) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_bare_wildcard.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_bare_wildcard.go index 8dc7568d6..083495f57 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_bare_wildcard.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_bare_wildcard.go @@ -31,12 +31,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &brSANBareWildcard{}, + Lint: NewBrSANBareWildcard, }) } -func (l *brSANBareWildcard) Initialize() error { - return nil +func NewBrSANBareWildcard() lint.LintInterface { + return &brSANBareWildcard{} } func (l *brSANBareWildcard) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_duplicate.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_duplicate.go index fb36c261e..2d3476712 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_duplicate.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_duplicate.go @@ -31,12 +31,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &SANDNSDuplicate{}, + Lint: NewSANDNSDuplicate, }) } -func (l *SANDNSDuplicate) Initialize() error { - return nil +func NewSANDNSDuplicate() lint.LintInterface { + return &SANDNSDuplicate{} } func (l *SANDNSDuplicate) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_includes_null_char.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_includes_null_char.go index b486d77f5..6e023d036 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_includes_null_char.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_includes_null_char.go @@ -29,12 +29,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &SANDNSNull{}, + Lint: NewSANDNSNull, }) } -func (l *SANDNSNull) Initialize() error { - return nil +func NewSANDNSNull() lint.LintInterface { + return &SANDNSNull{} } func (l *SANDNSNull) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_starts_with_period.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_starts_with_period.go index 394362003..54e1ba870 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_starts_with_period.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_dns_name_starts_with_period.go @@ -31,12 +31,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &SANDNSPeriod{}, + Lint: NewSANDNSPeriod, }) } -func (l *SANDNSPeriod) Initialize() error { - return nil +func NewSANDNSPeriod() lint.LintInterface { + return &SANDNSPeriod{} } func (l *SANDNSPeriod) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_iana_pub_suffix_empty.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_iana_pub_suffix_empty.go index 53be114dc..ee91b6f50 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_iana_pub_suffix_empty.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_iana_pub_suffix_empty.go @@ -32,12 +32,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &pubSuffix{}, + Lint: NewPubSuffix, }) } -func (l *pubSuffix) Initialize() error { - return nil +func NewPubSuffix() lint.LintInterface { + return &pubSuffix{} } func (l *pubSuffix) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_wildcard_not_first.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_wildcard_not_first.go index b94c7a07f..2d5526fbe 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_wildcard_not_first.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_san_wildcard_not_first.go @@ -29,12 +29,12 @@ func init() { Citation: "awslabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &SANWildCardFirst{}, + Lint: NewSANWildCardFirst, }) } -func (l *SANWildCardFirst) Initialize() error { - return nil +func NewSANWildCardFirst() lint.LintInterface { + return &SANWildCardFirst{} } func (l *SANWildCardFirst) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_leading_whitespace.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_leading_whitespace.go index fcd132860..354b25732 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_leading_whitespace.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_leading_whitespace.go @@ -29,12 +29,12 @@ func init() { Citation: "lint.AWSLabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &SubjectDNLeadingSpace{}, + Lint: NewSubjectDNLeadingSpace, }) } -func (l *SubjectDNLeadingSpace) Initialize() error { - return nil +func NewSubjectDNLeadingSpace() lint.LintInterface { + return &SubjectDNLeadingSpace{} } func (l *SubjectDNLeadingSpace) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_trailing_whitespace.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_trailing_whitespace.go index 99ed4ea53..7cd411d4f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_trailing_whitespace.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_dn_trailing_whitespace.go @@ -29,12 +29,12 @@ func init() { Citation: "lint.AWSLabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &SubjectDNTrailingSpace{}, + Lint: NewSubjectDNTrailingSpace, }) } -func (l *SubjectDNTrailingSpace) Initialize() error { - return nil +func NewSubjectDNTrailingSpace() lint.LintInterface { + return &SubjectDNTrailingSpace{} } func (l *SubjectDNTrailingSpace) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_multiple_rdn.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_multiple_rdn.go index e40b3e0fc..2e3336637 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_multiple_rdn.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_subject_multiple_rdn.go @@ -15,8 +15,7 @@ package community */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zcrypto/x509/pkix" "github.com/zmap/zlint/v3/lint" @@ -32,12 +31,12 @@ func init() { Citation: "lint.AWSLabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &SubjectRDNHasMultipleAttribute{}, + Lint: NewSubjectRDNHasMultipleAttribute, }) } -func (l *SubjectRDNHasMultipleAttribute) Initialize() error { - return nil +func NewSubjectRDNHasMultipleAttribute() lint.LintInterface { + return &SubjectRDNHasMultipleAttribute{} } func (l *SubjectRDNHasMultipleAttribute) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_validity_time_not_positive.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_validity_time_not_positive.go index 3a931ff5c..e9f420ed3 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/community/lint_validity_time_not_positive.go +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_validity_time_not_positive.go @@ -29,12 +29,12 @@ func init() { Citation: "lint.AWSLabs certlint", Source: lint.Community, EffectiveDate: util.ZeroDate, - Lint: &validityNegative{}, + Lint: NewValidityNegative, }) } -func (l *validityNegative) Initialize() error { - return nil +func NewValidityNegative() lint.LintInterface { + return &validityNegative{} } func (l *validityNegative) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_present_qcs_critical.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_present_qcs_critical.go index f7ddd7cb9..a568f976e 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_present_qcs_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_present_qcs_critical.go @@ -29,12 +29,12 @@ func init() { Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.1", Source: lint.EtsiEsi, EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, - Lint: &qcStatemQcEtsiPresentQcsCritical{}, + Lint: NewQcStatemQcEtsiPresentQcsCritical, }) } -func (l *qcStatemQcEtsiPresentQcsCritical) Initialize() error { - return nil +func NewQcStatemQcEtsiPresentQcsCritical() lint.LintInterface { + return &qcStatemQcEtsiPresentQcsCritical{} } func (l *qcStatemQcEtsiPresentQcsCritical) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_type_as_statem.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_type_as_statem.go index d93ebd169..b2ca72336 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_type_as_statem.go +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_etsi_type_as_statem.go @@ -15,9 +15,9 @@ package etsi import ( - "encoding/asn1" "fmt" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -32,12 +32,12 @@ func init() { Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.2.3", Source: lint.EtsiEsi, EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, - Lint: &qcStatemEtsiTypeAsStatem{}, + Lint: NewQcStatemEtsiTypeAsStatem, }) } -func (l *qcStatemEtsiTypeAsStatem) Initialize() error { - return nil +func NewQcStatemEtsiTypeAsStatem() lint.LintInterface { + return &qcStatemEtsiTypeAsStatem{} } func (l *qcStatemEtsiTypeAsStatem) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_mandatory_etsi_statems.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_mandatory_etsi_statems.go index 37d9b8650..ec67f7a27 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_mandatory_etsi_statems.go +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_mandatory_etsi_statems.go @@ -15,8 +15,7 @@ package etsi import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -31,12 +30,12 @@ func init() { Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 5", Source: lint.EtsiEsi, EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, - Lint: &qcStatemQcmandatoryEtsiStatems{}, + Lint: NewQcStatemQcmandatoryEtsiStatems, }) } -func (l *qcStatemQcmandatoryEtsiStatems) Initialize() error { - return nil +func NewQcStatemQcmandatoryEtsiStatems() lint.LintInterface { + return &qcStatemQcmandatoryEtsiStatems{} } func (l *qcStatemQcmandatoryEtsiStatems) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qccompliance_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qccompliance_valid.go index 2494268e5..31d3ce835 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qccompliance_valid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qccompliance_valid.go @@ -15,8 +15,7 @@ package etsi import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -31,16 +30,16 @@ func init() { Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.2.1", Source: lint.EtsiEsi, EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, - Lint: &qcStatemQcComplianceValid{}, + Lint: NewQcStatemQcComplianceValid, }) } -func (this *qcStatemQcComplianceValid) getStatementOid() *asn1.ObjectIdentifier { - return &util.IdEtsiQcsQcCompliance +func NewQcStatemQcComplianceValid() lint.LintInterface { + return &qcStatemQcComplianceValid{} } -func (l *qcStatemQcComplianceValid) Initialize() error { - return nil +func (this *qcStatemQcComplianceValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcCompliance } func (l *qcStatemQcComplianceValid) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qclimitvalue_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qclimitvalue_valid.go index 27678b99c..bc31e6431 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qclimitvalue_valid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qclimitvalue_valid.go @@ -15,9 +15,9 @@ package etsi import ( - "encoding/asn1" "unicode" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -32,16 +32,16 @@ func init() { Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.3.2", Source: lint.EtsiEsi, EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, - Lint: &qcStatemQcLimitValueValid{}, + Lint: NewQcStatemQcLimitValueValid, }) } -func (this *qcStatemQcLimitValueValid) getStatementOid() *asn1.ObjectIdentifier { - return &util.IdEtsiQcsQcLimitValue +func NewQcStatemQcLimitValueValid() lint.LintInterface { + return &qcStatemQcLimitValueValid{} } -func (l *qcStatemQcLimitValueValid) Initialize() error { - return nil +func (this *qcStatemQcLimitValueValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcLimitValue } func (l *qcStatemQcLimitValueValid) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_lang_case.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_lang_case.go index 8aa87c944..82f87772e 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_lang_case.go +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_lang_case.go @@ -15,10 +15,10 @@ package etsi import ( - "encoding/asn1" "fmt" "unicode" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -33,16 +33,16 @@ func init() { Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.3.4", Source: lint.EtsiEsi, EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, - Lint: &qcStatemQcPdsLangCase{}, + Lint: NewQcStatemQcPdsLangCase, }) } -func (this *qcStatemQcPdsLangCase) getStatementOid() *asn1.ObjectIdentifier { - return &util.IdEtsiQcsQcEuPDS +func NewQcStatemQcPdsLangCase() lint.LintInterface { + return &qcStatemQcPdsLangCase{} } -func (l *qcStatemQcPdsLangCase) Initialize() error { - return nil +func (this *qcStatemQcPdsLangCase) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcEuPDS } func (l *qcStatemQcPdsLangCase) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_valid.go index 5f0fda22e..2df626891 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_valid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_valid.go @@ -15,10 +15,10 @@ package etsi import ( - "encoding/asn1" "fmt" "strings" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -33,16 +33,16 @@ func init() { Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.3.4", Source: lint.EtsiEsi, EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, - Lint: &qcStatemQcPdsValid{}, + Lint: NewQcStatemQcPdsValid, }) } -func (this *qcStatemQcPdsValid) getStatementOid() *asn1.ObjectIdentifier { - return &util.IdEtsiQcsQcEuPDS +func NewQcStatemQcPdsValid() lint.LintInterface { + return &qcStatemQcPdsValid{} } -func (l *qcStatemQcPdsValid) Initialize() error { - return nil +func (this *qcStatemQcPdsValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcEuPDS } func (l *qcStatemQcPdsValid) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcretentionperiod_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcretentionperiod_valid.go index 626b53279..7ae39557f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcretentionperiod_valid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcretentionperiod_valid.go @@ -15,8 +15,7 @@ package etsi import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -31,16 +30,16 @@ func init() { Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11)/ Section 4.3.3", Source: lint.EtsiEsi, EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, - Lint: &qcStatemQcRetentionPeriodValid{}, + Lint: NewQcStatemQcRetentionPeriodValid, }) } -func (this *qcStatemQcRetentionPeriodValid) getStatementOid() *asn1.ObjectIdentifier { - return &util.IdEtsiQcsQcRetentionPeriod +func NewQcStatemQcRetentionPeriodValid() lint.LintInterface { + return &qcStatemQcRetentionPeriodValid{} } -func (l *qcStatemQcRetentionPeriodValid) Initialize() error { - return nil +func (this *qcStatemQcRetentionPeriodValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcRetentionPeriod } func (l *qcStatemQcRetentionPeriodValid) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcsscd_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcsscd_valid.go index 199fdba40..cc08b6839 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcsscd_valid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcsscd_valid.go @@ -15,8 +15,7 @@ package etsi import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -31,16 +30,16 @@ func init() { Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.2.2", Source: lint.EtsiEsi, EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, - Lint: &qcStatemQcSscdValid{}, + Lint: NewQcStatemQcSscdValid, }) } -func (this *qcStatemQcSscdValid) getStatementOid() *asn1.ObjectIdentifier { - return &util.IdEtsiQcsQcSSCD +func NewQcStatemQcSscdValid() lint.LintInterface { + return &qcStatemQcSscdValid{} } -func (l *qcStatemQcSscdValid) Initialize() error { - return nil +func (this *qcStatemQcSscdValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcSSCD } func (l *qcStatemQcSscdValid) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_valid.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_valid.go index ed382d26f..cf957bde2 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_valid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_valid.go @@ -15,9 +15,9 @@ package etsi import ( - "encoding/asn1" "fmt" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -32,16 +32,16 @@ func init() { Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.2.3", Source: lint.EtsiEsi, EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, - Lint: &qcStatemQctypeValid{}, + Lint: NewQcStatemQctypeValid, }) } -func (this *qcStatemQctypeValid) getStatementOid() *asn1.ObjectIdentifier { - return &util.IdEtsiQcsQcType +func NewQcStatemQctypeValid() lint.LintInterface { + return &qcStatemQctypeValid{} } -func (l *qcStatemQctypeValid) Initialize() error { - return nil +func (this *qcStatemQctypeValid) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcType } func (l *qcStatemQctypeValid) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_web.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_web.go index 71a75c9cb..a2b152239 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_web.go +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qctype_web.go @@ -15,9 +15,9 @@ package etsi import ( - "encoding/asn1" "fmt" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -32,16 +32,16 @@ func init() { Citation: "ETSI EN 319 412 - 5 V2.2.1 (2017 - 11) / Section 4.2.3", Source: lint.EtsiEsi, EffectiveDate: util.EtsiEn319_412_5_V2_2_1_Date, - Lint: &qcStatemQctypeWeb{}, + Lint: NewQcStatemQctypeWeb, }) } -func (this *qcStatemQctypeWeb) getStatementOid() *asn1.ObjectIdentifier { - return &util.IdEtsiQcsQcType +func NewQcStatemQctypeWeb() lint.LintInterface { + return &qcStatemQctypeWeb{} } -func (l *qcStatemQctypeWeb) Initialize() error { - return nil +func (this *qcStatemQctypeWeb) getStatementOid() *asn1.ObjectIdentifier { + return &util.IdEtsiQcsQcType } func (l *qcStatemQctypeWeb) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_e_prohibit_dsa_usage.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_e_prohibit_dsa_usage.go new file mode 100644 index 000000000..bfe87f0a6 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_e_prohibit_dsa_usage.go @@ -0,0 +1,62 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package mozilla + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type prohibitDSAUsage struct{} + +/************************************************ +https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/policy/ + +Subsection 5.1 Algorithms +Root certificates in our root program, and any certificate which chains up to them, MUST use only algorithms and key sizes from the following set: + +- RSA keys whose modulus size in bits is divisible by 8, and is at least 2048. +- ECDSA keys using one of the following curves: + + P-256 + + P-384 +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_prohibit_dsa_usage", + Description: "DSA is not an explicitly allowed signature algorithm, therefore it is forbidden.", + Citation: "Mozilla Root Store Policy / Section 5.1", + Source: lint.MozillaRootStorePolicy, + EffectiveDate: util.MozillaPolicy241Date, + Lint: NewProhibitDSAUsage, + }) +} + +func NewProhibitDSAUsage() lint.LintInterface { + return &prohibitDSAUsage{} +} + +func (l *prohibitDSAUsage) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *prohibitDSAUsage) Execute(c *x509.Certificate) *lint.LintResult { + if c.PublicKeyAlgorithm == x509.DSA { + return &lint.LintResult{Status: lint.Error} + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_allowed_eku.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_allowed_eku.go index 774bf4675..7fd70ed94 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_allowed_eku.go +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_allowed_eku.go @@ -39,16 +39,16 @@ intermediates. func init() { lint.RegisterLint(&lint.Lint{ Name: "n_mp_allowed_eku", - Description: "A SubCA certificate must not have key usage that allows for both server auth and email protection, and must not use anyKeyUsage", + Description: "A SubCA certificate must not have key usage that allows for both server auth and email protection, and must not use anyExtendedKeyUsage", Citation: "Mozilla Root Store Policy / Section 5.3", Source: lint.MozillaRootStorePolicy, EffectiveDate: time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC), - Lint: &allowedEKU{}, + Lint: NewAllowedEKU, }) } -func (l *allowedEKU) Initialize() error { - return nil +func NewAllowedEKU() lint.LintInterface { + return &allowedEKU{} } func (l *allowedEKU) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_authority_key_identifier_correct.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_authority_key_identifier_correct.go index 004f01284..017ded94b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_authority_key_identifier_correct.go +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_authority_key_identifier_correct.go @@ -15,9 +15,9 @@ package mozilla import ( - "encoding/asn1" "fmt" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -45,12 +45,12 @@ func init() { Citation: "Mozilla Root Store Policy / Section 5.2", Source: lint.MozillaRootStorePolicy, EffectiveDate: util.MozillaPolicy22Date, - Lint: &authorityKeyIdentifierCorrect{}, + Lint: NewAuthorityKeyIdentifierCorrect, }) } -func (l *authorityKeyIdentifierCorrect) Initialize() error { - return nil +func NewAuthorityKeyIdentifierCorrect() lint.LintInterface { + return &authorityKeyIdentifierCorrect{} } func (l *authorityKeyIdentifierCorrect) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go index 92b7ebbcb..9a13db7ce 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go @@ -50,10 +50,14 @@ func init() { Citation: "Mozilla Root Store Policy / Section 5.1.2", Source: lint.MozillaRootStorePolicy, EffectiveDate: util.MozillaPolicy27Date, - Lint: &ecdsaPubKeyAidEncoding{}, + Lint: NewEcdsaPubKeyAidEncoding, }) } +func NewEcdsaPubKeyAidEncoding() lint.LintInterface { + return &ecdsaPubKeyAidEncoding{} +} + var acceptedAlgIDEncodingsDER = [2][]byte{ // encoded AlgorithmIdentifier for a P-256 key {0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}, @@ -61,10 +65,6 @@ var acceptedAlgIDEncodingsDER = [2][]byte{ {0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22}, } -func (l *ecdsaPubKeyAidEncoding) Initialize() error { - return nil -} - func (l *ecdsaPubKeyAidEncoding) CheckApplies(c *x509.Certificate) bool { return c.PublicKeyAlgorithm == x509.ECDSA } diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go index 71dd0d8ea..2339d05a0 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go @@ -51,12 +51,12 @@ func init() { Citation: "Mozilla Root Store Policy / Section 5.1.2", Source: lint.MozillaRootStorePolicy, EffectiveDate: util.MozillaPolicy27Date, - Lint: &ecdsaSignatureAidEncoding{}, + Lint: NewEcdsaSignatureAidEncoding, }) } -func (l *ecdsaSignatureAidEncoding) Initialize() error { - return nil +func NewEcdsaSignatureAidEncoding() lint.LintInterface { + return &ecdsaSignatureAidEncoding{} } func (l *ecdsaSignatureAidEncoding) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_exponent_cannot_be_one.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_exponent_cannot_be_one.go index 42bae8c31..9e51d9e41 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_exponent_cannot_be_one.go +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_exponent_cannot_be_one.go @@ -37,12 +37,12 @@ func init() { Citation: "Mozilla Root Store Policy / Section 5.2", Source: lint.MozillaRootStorePolicy, EffectiveDate: util.MozillaPolicy24Date, - Lint: &exponentCannotBeOne{}, + Lint: NewExponentCannotBeOne, }) } -func (l *exponentCannotBeOne) Initialize() error { - return nil +func NewExponentCannotBeOne() lint.LintInterface { + return &exponentCannotBeOne{} } func (l *exponentCannotBeOne) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_2048_bits_or_more.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_2048_bits_or_more.go index b6689a1f1..4dd21ffef 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_2048_bits_or_more.go +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_2048_bits_or_more.go @@ -36,12 +36,12 @@ func init() { Citation: "Mozilla Root Store Policy / Section 5.1", Source: lint.MozillaRootStorePolicy, EffectiveDate: util.MozillaPolicy24Date, - Lint: &modulus2048OrMore{}, + Lint: NewModulus2048OrMore, }) } -func (l *modulus2048OrMore) Initialize() error { - return nil +func NewModulus2048OrMore() lint.LintInterface { + return &modulus2048OrMore{} } func (l *modulus2048OrMore) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_divisible_by_8.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_divisible_by_8.go index e21b9faf5..96f129f49 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_divisible_by_8.go +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_modulus_must_be_divisible_by_8.go @@ -36,12 +36,12 @@ func init() { Citation: "Mozilla Root Store Policy / Section 5.1", Source: lint.MozillaRootStorePolicy, EffectiveDate: util.MozillaPolicy24Date, - Lint: &modulusDivisibleBy8{}, + Lint: NewModulusDivisibleBy8, }) } -func (l *modulusDivisibleBy8) Initialize() error { - return nil +func NewModulusDivisibleBy8() lint.LintInterface { + return &modulusDivisibleBy8{} } func (l *modulusDivisibleBy8) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_pss_parameters_encoding_correct.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_pss_parameters_encoding_correct.go index f1d0fc91b..cdf56a429 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_pss_parameters_encoding_correct.go +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_pss_parameters_encoding_correct.go @@ -64,10 +64,14 @@ func init() { Citation: "Mozilla Root Store Policy / Section 5.1.1", Source: lint.MozillaRootStorePolicy, EffectiveDate: util.MozillaPolicy27Date, - Lint: &rsaPssAidEncoding{}, + Lint: NewRsaPssAidEncoding, }) } +func NewRsaPssAidEncoding() lint.LintInterface { + return &rsaPssAidEncoding{} +} + var RSASSAPSSAlgorithmIDToDER = [3][]byte{ // RSASSA-PSS with SHA-256, MGF-1 with SHA-256, salt length 32 bytes {0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20}, @@ -77,10 +81,6 @@ var RSASSAPSSAlgorithmIDToDER = [3][]byte{ {0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x40}, } -func (l *rsaPssAidEncoding) Initialize() error { - return nil -} - func (l *rsaPssAidEncoding) CheckApplies(c *x509.Certificate) bool { return c.SignatureAlgorithmOID.Equal(util.OidRSASSAPSS) } diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_rsassa-pss_in_spki.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_rsassa-pss_in_spki.go index b978cce4c..f7fdfd03d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_rsassa-pss_in_spki.go +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_rsassa-pss_in_spki.go @@ -39,12 +39,12 @@ func init() { Citation: "Mozilla Root Store Policy / Section 5.1.1", Source: lint.MozillaRootStorePolicy, EffectiveDate: util.MozillaPolicy27Date, - Lint: &rsaPssInSPKI{}, + Lint: NewRsaPssInSPKI, }) } -func (l *rsaPssInSPKI) Initialize() error { - return nil +func NewRsaPssInSPKI() lint.LintInterface { + return &rsaPssInSPKI{} } func (l *rsaPssInSPKI) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_basic_constraints_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_basic_constraints_not_critical.go index 55866ec44..3e0b70933 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_basic_constraints_not_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_basic_constraints_not_critical.go @@ -41,12 +41,12 @@ func init() { Citation: "RFC 5280: 4.2.1.9", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &basicConstCrit{}, + Lint: NewBasicConstCrit, }) } -func (l *basicConstCrit) Initialize() error { - return nil +func NewBasicConstCrit() lint.LintInterface { + return &basicConstCrit{} } func (l *basicConstCrit) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ca_subject_field_empty.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ca_subject_field_empty.go index f6a55d781..3d5478221 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ca_subject_field_empty.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ca_subject_field_empty.go @@ -41,12 +41,12 @@ func init() { Citation: "RFC 5280: 4.1.2.6", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &caSubjectEmpty{}, + Lint: NewCaSubjectEmpty, }) } -func (l *caSubjectEmpty) Initialize() error { - return nil +func NewCaSubjectEmpty() lint.LintInterface { + return &caSubjectEmpty{} } func (l *caSubjectEmpty) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_contains_unique_identifier.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_contains_unique_identifier.go index 13d5f5e79..dbb51c5b7 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_contains_unique_identifier.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_contains_unique_identifier.go @@ -42,12 +42,12 @@ func init() { Source: lint.RFC5280, Citation: "RFC 5280: 4.1.2.8", EffectiveDate: util.RFC5280Date, - Lint: &CertContainsUniqueIdentifier{}, + Lint: NewCertContainsUniqueIdentifier, }) } -func (l *CertContainsUniqueIdentifier) Initialize() error { - return nil +func NewCertContainsUniqueIdentifier() lint.LintInterface { + return &CertContainsUniqueIdentifier{} } func (l *CertContainsUniqueIdentifier) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_extensions_version_not_3.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_extensions_version_not_3.go index 18a82c627..73b5d5658 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_extensions_version_not_3.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_extensions_version_not_3.go @@ -48,12 +48,12 @@ func init() { Citation: "RFC 5280: 4.1.2.9", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &CertExtensionsVersonNot3{}, + Lint: NewCertExtensionsVersonNot3, }) } -func (l *CertExtensionsVersonNot3) Initialize() error { - return nil +func NewCertExtensionsVersonNot3() lint.LintInterface { + return &CertExtensionsVersonNot3{} } func (l *CertExtensionsVersonNot3) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_unique_identifier_version_not_2_or_3.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_unique_identifier_version_not_2_or_3.go index 476d88932..f6c982b7c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_unique_identifier_version_not_2_or_3.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_cert_unique_identifier_version_not_2_or_3.go @@ -43,12 +43,12 @@ func init() { Citation: "RFC 5280: 4.1.2.8", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &certUniqueIdVersion{}, + Lint: NewCertUniqueIdVersion, }) } -func (l *certUniqueIdVersion) Initialize() error { - return nil +func NewCertUniqueIdVersion() lint.LintInterface { + return &certUniqueIdVersion{} } func (l *certUniqueIdVersion) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_incomplete.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_incomplete.go index 32ccb9475..75766eb9d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_incomplete.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_incomplete.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zcrypto/x509/pkix" "github.com/zmap/zlint/v3/lint" @@ -56,12 +55,12 @@ func init() { Citation: "RFC 5280: 4.2.1.13", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &dpIncomplete{}, + Lint: NewDpIncomplete, }) } -func (l *dpIncomplete) Initialize() error { - return nil +func NewDpIncomplete() lint.LintInterface { + return &dpIncomplete{} } func (l *dpIncomplete) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_missing_ldap_or_uri.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_missing_ldap_or_uri.go index 1ad537db0..8a15bd9ee 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_missing_ldap_or_uri.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_distribution_point_missing_ldap_or_uri.go @@ -36,12 +36,12 @@ func init() { Citation: "RFC 5280: 4.2.1.13", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &distribNoLDAPorURI{}, + Lint: NewDistribNoLDAPorURI, }) } -func (l *distribNoLDAPorURI) Initialize() error { - return nil +func NewDistribNoLDAPorURI() lint.LintInterface { + return &distribNoLDAPorURI{} } func (l *distribNoLDAPorURI) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_contains_empty_label.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_contains_empty_label.go new file mode 100644 index 000000000..88eb1fb19 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_contains_empty_label.go @@ -0,0 +1,63 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameEmptyLabel struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rfc_dnsname_empty_label", + Description: "DNSNames should not have an empty label.", + Citation: "RFC5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: NewDNSNameEmptyLabel, + }) +} + +func NewDNSNameEmptyLabel() lint.LintInterface { + return &DNSNameEmptyLabel{} +} + +func (l *DNSNameEmptyLabel) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func domainHasEmptyLabel(domain string) bool { + labels := strings.Split(domain, ".") + for _, elem := range labels { + if elem == "" { + return true + } + } + return false +} + +func (l *DNSNameEmptyLabel) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + if domainHasEmptyLabel(dns) { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_hyphen_in_sld.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_hyphen_in_sld.go new file mode 100644 index 000000000..a92ccda7e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_hyphen_in_sld.go @@ -0,0 +1,58 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameHyphenInSLD struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rfc_dnsname_hyphen_in_sld", + Description: "DNSName should not have a hyphen beginning or ending the SLD", + Citation: "RFC5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: NewDNSNameHyphenInSLD, + }) +} + +func NewDNSNameHyphenInSLD() lint.LintInterface { + return &DNSNameHyphenInSLD{} +} + +func (l *DNSNameHyphenInSLD) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *DNSNameHyphenInSLD) Execute(c *x509.Certificate) *lint.LintResult { + parsedSANDNSNames := c.GetParsedDNSNames(false) + for i := range c.GetParsedDNSNames(false) { + if parsedSANDNSNames[i].ParseError != nil { + return &lint.LintResult{Status: lint.NA} + } + if strings.HasPrefix(parsedSANDNSNames[i].ParsedDomain.SLD, "-") || + strings.HasSuffix(parsedSANDNSNames[i].ParsedDomain.SLD, "-") { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_label_too_long.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_label_too_long.go new file mode 100644 index 000000000..25782be04 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_label_too_long.go @@ -0,0 +1,64 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameLabelLengthTooLong struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rfc_dnsname_label_too_long", + Description: "DNSName labels MUST be less than or equal to 63 characters", + Citation: "RFC 5280: 4.2.1.6, citing RFC 1035", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: NewDNSNameLabelLengthTooLong, + }) +} + +func NewDNSNameLabelLengthTooLong() lint.LintInterface { + return &DNSNameLabelLengthTooLong{} +} + +func (l *DNSNameLabelLengthTooLong) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func labelLengthTooLong(domain string) bool { + labels := strings.Split(domain, ".") + for _, label := range labels { + if len(label) > 63 { + return true + } + } + return false +} + +func (l *DNSNameLabelLengthTooLong) Execute(c *x509.Certificate) *lint.LintResult { + for _, dns := range c.DNSNames { + labelTooLong := labelLengthTooLong(dns) + if labelTooLong { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_underscore_in_sld.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_underscore_in_sld.go new file mode 100644 index 000000000..3efa8d264 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_underscore_in_sld.go @@ -0,0 +1,57 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameUnderscoreInSLD struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rfc_dnsname_underscore_in_sld", + Description: "DNSName MUST NOT contain underscore characters", + Citation: "RFC5280: 4.2.1.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: NewDNSNameUnderscoreInSLD, + }) +} + +func NewDNSNameUnderscoreInSLD() lint.LintInterface { + return &DNSNameUnderscoreInSLD{} +} + +func (l *DNSNameUnderscoreInSLD) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *DNSNameUnderscoreInSLD) Execute(c *x509.Certificate) *lint.LintResult { + parsedSANDNSNames := c.GetParsedDNSNames(false) + for i := range c.GetParsedDNSNames(false) { + if parsedSANDNSNames[i].ParseError != nil { + return &lint.LintResult{Status: lint.NA} + } + if strings.Contains(parsedSANDNSNames[i].ParsedDomain.SLD, "_") { + return &lint.LintResult{Status: lint.Error} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_underscore_in_trd.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_underscore_in_trd.go new file mode 100644 index 000000000..3e07d6b86 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_dnsname_underscore_in_trd.go @@ -0,0 +1,58 @@ +package rfc + +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type DNSNameUnderscoreInTRD struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_rfc_dnsname_underscore_in_trd", + Description: "DNSName MUST NOT contain underscore characters", + Citation: "RFC5280: 4.1.2.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: NewDNSNameUnderscoreInTRD, + }) +} + +func NewDNSNameUnderscoreInTRD() lint.LintInterface { + return &DNSNameUnderscoreInTRD{} +} + +func (l *DNSNameUnderscoreInTRD) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.DNSNamesExist(c) +} + +func (l *DNSNameUnderscoreInTRD) Execute(c *x509.Certificate) *lint.LintResult { + parsedSANDNSNames := c.GetParsedDNSNames(false) + for i := range c.GetParsedDNSNames(false) { + if parsedSANDNSNames[i].ParseError != nil { + return &lint.LintResult{Status: lint.NA} + } + if strings.Contains(parsedSANDNSNames[i].ParsedDomain.TRD, "_") { + return &lint.LintResult{Status: lint.Warn} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ecdsa_allowed_ku.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ecdsa_allowed_ku.go new file mode 100644 index 000000000..14e15605d --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ecdsa_allowed_ku.go @@ -0,0 +1,91 @@ +/* + * ZLint Copyright 2022 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "fmt" + "sort" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type ecdsaAllowedKU struct{} + +/************************************************ +RFC 8813: 3. Updates to Section 3 +If the keyUsage extension is present in a certificate that indicates + id-ecPublicKey in SubjectPublicKeyInfo, then the following values + MUST NOT be present: + + keyEncipherment; and + dataEncipherment. +************************************************/ +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_ecdsa_allowed_ku", + Description: "Key usage values keyEncipherment or dataEncipherment MUST NOT be present in certificates with ECDSA public keys", + Citation: "RFC 8813 Section 3", + Source: lint.RFC8813, + EffectiveDate: util.RFC8813Date, + Lint: NewEcdsaAllowedKU, + }) +} + +func NewEcdsaAllowedKU() lint.LintInterface { + return &ecdsaAllowedKU{} +} + +// CheckApplies returns true when the certificate has an ECDSA public key and a key usage extension. +func (l *ecdsaAllowedKU) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.ECDSA && util.HasKeyUsageOID(c) +} + +// Execute returns an Error level lint.LintResult if the ECDSA certificate +// being linted has the following Key Usage bits set: keyEncipherment or dataEncipherment. +func (l *ecdsaAllowedKU) Execute(c *x509.Certificate) *lint.LintResult { + // RFC 8813, Section 3 "Updates to Section 3" reads: + // + // If the keyUsage extension is present in a certificate that indicates + // id-ecPublicKey in SubjectPublicKeyInfo, then the following values + // MUST NOT be present: + // + // keyEncipherment; and + // dataEncipherment. + + var invalidKUs []string + + if util.HasKeyUsage(c, x509.KeyUsageKeyEncipherment) { + invalidKUs = append(invalidKUs, util.KeyUsageToString[x509.KeyUsageKeyEncipherment]) + } + + if util.HasKeyUsage(c, x509.KeyUsageDataEncipherment) { + invalidKUs = append(invalidKUs, util.KeyUsageToString[x509.KeyUsageDataEncipherment]) + } + + if len(invalidKUs) > 0 { + // Sort the invalid KUs to allow consistent ordering of Details messages for + // unit testing + sort.Strings(invalidKUs) + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("Certificate contains invalid key usage(s): %s", strings.Join(invalidKUs, ", ")), + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ecdsa_ee_invalid_ku.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ecdsa_ee_invalid_ku.go index be191d1ac..600d02da9 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ecdsa_ee_invalid_ku.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ecdsa_ee_invalid_ku.go @@ -33,15 +33,16 @@ func init() { Citation: "RFC 5480 Section 3", Source: lint.RFC5480, EffectiveDate: util.CABEffectiveDate, - Lint: &ecdsaInvalidKU{}, + Lint: NewEcdsaInvalidKU, }) } -// Initialize is a no-op for this lint. -func (l *ecdsaInvalidKU) Initialize() error { - return nil +func NewEcdsaInvalidKU() lint.LintInterface { + return &ecdsaInvalidKU{} } +// Initialize is a no-op for this lint. + // CheckApplies returns true when the certificate is a subscriber cert using an // ECDSA public key algorithm. func (l *ecdsaInvalidKU) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_eku_critical_improperly.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_eku_critical_improperly.go index d6051db4e..f23e934f6 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_eku_critical_improperly.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_eku_critical_improperly.go @@ -42,12 +42,12 @@ func init() { Citation: "RFC 5280: 4.2.1.12", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &ekuBadCritical{}, + Lint: NewEkuBadCritical, }) } -func (l *ekuBadCritical) Initialize() error { - return nil +func NewEkuBadCritical() lint.LintInterface { + return &ekuBadCritical{} } func (l *ekuBadCritical) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_access_location_missing.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_access_location_missing.go index df2e41a9b..784b36e46 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_access_location_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_access_location_missing.go @@ -42,12 +42,12 @@ func init() { Citation: "RFC 5280: 4.2.2.1", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &aiaNoHTTPorLDAP{}, + Lint: NewAiaNoHTTPorLDAP, }) } -func (l *aiaNoHTTPorLDAP) Initialize() error { - return nil +func NewAiaNoHTTPorLDAP() lint.LintInterface { + return &aiaNoHTTPorLDAP{} } func (l *aiaNoHTTPorLDAP) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_marked_critical.go index dce31de95..8c236821d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_marked_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_aia_marked_critical.go @@ -35,12 +35,12 @@ func init() { Citation: "RFC 5280: 4.2.2.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &ExtAiaMarkedCritical{}, + Lint: NewExtAiaMarkedCritical, }) } -func (l *ExtAiaMarkedCritical) Initialize() error { - return nil +func NewExtAiaMarkedCritical() lint.LintInterface { + return &ExtAiaMarkedCritical{} } func (l *ExtAiaMarkedCritical) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_critical.go index 768a47492..e0856d8db 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_critical.go @@ -34,12 +34,12 @@ func init() { Citation: "RFC 5280: 4.2.1.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &authorityKeyIdCritical{}, + Lint: NewAuthorityKeyIdCritical, }) } -func (l *authorityKeyIdCritical) Initialize() error { - return nil +func NewAuthorityKeyIdCritical() lint.LintInterface { + return &authorityKeyIdCritical{} } func (l *authorityKeyIdCritical) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_missing.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_missing.go index 76488f76a..711b2b960 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_missing.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_missing.go @@ -44,12 +44,12 @@ func init() { Citation: "RFC 5280: 4.2 & 4.2.1.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &authorityKeyIdMissing{}, + Lint: NewAuthorityKeyIdMissing, }) } -func (l *authorityKeyIdMissing) Initialize() error { - return nil +func NewAuthorityKeyIdMissing() lint.LintInterface { + return &authorityKeyIdMissing{} } func (l *authorityKeyIdMissing) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_no_key_identifier.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_no_key_identifier.go index fdf2a2add..82c62f928 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_no_key_identifier.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_authority_key_identifier_no_key_identifier.go @@ -44,12 +44,12 @@ func init() { Citation: "RFC 5280: 4.2.1.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &authorityKeyIdNoKeyIdField{}, + Lint: NewAuthorityKeyIdNoKeyIdField, }) } -func (l *authorityKeyIdNoKeyIdField) Initialize() error { - return nil +func NewAuthorityKeyIdNoKeyIdField() lint.LintInterface { + return &authorityKeyIdNoKeyIdField{} } func (l *authorityKeyIdNoKeyIdField) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_contains_noticeref.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_contains_noticeref.go index f64aab142..17313d29c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_contains_noticeref.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_contains_noticeref.go @@ -35,12 +35,12 @@ func init() { Citation: "RFC 5280: 4.2.1.4", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: ¬iceRefPres{}, + Lint: NewNoticeRefPres, }) } -func (l *noticeRefPres) Initialize() error { - return nil +func NewNoticeRefPres() lint.LintInterface { + return ¬iceRefPres{} } func (l *noticeRefPres) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_disallowed_any_policy_qualifier.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_disallowed_any_policy_qualifier.go index 042e5798d..d050929ea 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_disallowed_any_policy_qualifier.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_disallowed_any_policy_qualifier.go @@ -40,12 +40,12 @@ func init() { Citation: "RFC 5280: 4.2.1.4", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &unrecommendedQualifier{}, + Lint: NewUnrecommendedQualifier, }) } -func (l *unrecommendedQualifier) Initialize() error { - return nil +func NewUnrecommendedQualifier() lint.LintInterface { + return &unrecommendedQualifier{} } func (l *unrecommendedQualifier) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_duplicate.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_duplicate.go index cffa718d4..3cd736dca 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_duplicate.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_duplicate.go @@ -37,12 +37,12 @@ func init() { Citation: "RFC 5280: 4.2.1.4", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &ExtCertPolicyDuplicate{}, + Lint: NewExtCertPolicyDuplicate, }) } -func (l *ExtCertPolicyDuplicate) Initialize() error { - return nil +func NewExtCertPolicyDuplicate() lint.LintInterface { + return &ExtCertPolicyDuplicate{} } func (l *ExtCertPolicyDuplicate) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_ia5_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_ia5_string.go index d5233cd44..57dd2c2ca 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_ia5_string.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_ia5_string.go @@ -43,12 +43,12 @@ func init() { Citation: "RFC 6818: 3", Source: lint.RFC5280, EffectiveDate: util.RFC6818Date, - Lint: &explicitTextIA5String{}, + Lint: NewExplicitTextIA5String, }) } -func (l *explicitTextIA5String) Initialize() error { - return nil +func NewExplicitTextIA5String() lint.LintInterface { + return &explicitTextIA5String{} } func (l *explicitTextIA5String) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_includes_control.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_includes_control.go index 41e752740..360b43220 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_includes_control.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_includes_control.go @@ -41,12 +41,12 @@ func init() { Citation: "RFC 6818: 3", Source: lint.RFC5280, EffectiveDate: util.RFC6818Date, - Lint: &controlChar{}, + Lint: NewControlChar, }) } -func (l *controlChar) Initialize() error { - return nil +func NewControlChar() lint.LintInterface { + return &controlChar{} } func (l *controlChar) CheckApplies(c *x509.Certificate) bool { @@ -59,6 +59,7 @@ func (l *controlChar) CheckApplies(c *x509.Certificate) bool { } //nolint:nestif +//nolint:cyclop func (l *controlChar) Execute(c *x509.Certificate) *lint.LintResult { for _, firstLvl := range c.ExplicitTexts { for _, text := range firstLvl { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_nfc.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_nfc.go index 7d68b8f0b..0ad63817f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_nfc.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_nfc.go @@ -35,12 +35,12 @@ func init() { Citation: "RFC6181 3", Source: lint.RFC5280, EffectiveDate: util.RFC6818Date, - Lint: &ExtCertPolicyExplicitTextNotNFC{}, + Lint: NewExtCertPolicyExplicitTextNotNFC, }) } -func (l *ExtCertPolicyExplicitTextNotNFC) Initialize() error { - return nil +func NewExtCertPolicyExplicitTextNotNFC() lint.LintInterface { + return &ExtCertPolicyExplicitTextNotNFC{} } func (l *ExtCertPolicyExplicitTextNotNFC) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_utf8.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_utf8.go index 7c283b207..3c0201b98 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_utf8.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_not_utf8.go @@ -44,12 +44,12 @@ func init() { Citation: "RFC 6818: 3", Source: lint.RFC5280, EffectiveDate: util.RFC6818Date, - Lint: &explicitTextUtf8{}, + Lint: NewExplicitTextUtf8, }) } -func (l *explicitTextUtf8) Initialize() error { - return nil +func NewExplicitTextUtf8() lint.LintInterface { + return &explicitTextUtf8{} } func (l *explicitTextUtf8) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_too_long.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_too_long.go index b728daea6..2e044c854 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_too_long.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_cert_policy_explicit_text_too_long.go @@ -42,16 +42,16 @@ func init() { Citation: "RFC 6818: 3", Source: lint.RFC5280, EffectiveDate: util.RFC6818Date, - Lint: &explicitTextTooLong{}, + Lint: NewExplicitTextTooLong, }) } -const tagBMPString int = 30 - -func (l *explicitTextTooLong) Initialize() error { - return nil +func NewExplicitTextTooLong() lint.LintInterface { + return &explicitTextTooLong{} } +const tagBMPString int = 30 + func (l *explicitTextTooLong) CheckApplies(c *x509.Certificate) bool { for _, text := range c.ExplicitTexts { if text != nil { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_crl_distribution_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_crl_distribution_marked_critical.go index 8016b419c..0a4e9b7a6 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_crl_distribution_marked_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_crl_distribution_marked_critical.go @@ -33,12 +33,12 @@ func init() { Citation: "RFC 5280: 4.2.1.13", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &ExtCrlDistributionMarkedCritical{}, + Lint: NewExtCrlDistributionMarkedCritical, }) } -func (l *ExtCrlDistributionMarkedCritical) Initialize() error { - return nil +func NewExtCrlDistributionMarkedCritical() lint.LintInterface { + return &ExtCrlDistributionMarkedCritical{} } func (l *ExtCrlDistributionMarkedCritical) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_duplicate_extension.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_duplicate_extension.go index 8eb32ee6b..fcbfa77a9 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_duplicate_extension.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_duplicate_extension.go @@ -36,12 +36,12 @@ func init() { Citation: "RFC 5280: 4.2", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &extDuplicateExtension{}, + Lint: NewExtDuplicateExtension, }) } -func (l *extDuplicateExtension) Initialize() error { - return nil +func NewExtDuplicateExtension() lint.LintInterface { + return &extDuplicateExtension{} } func (l *extDuplicateExtension) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_freshest_crl_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_freshest_crl_marked_critical.go index 0417c4c8d..71d8e9d52 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_freshest_crl_marked_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_freshest_crl_marked_critical.go @@ -34,12 +34,12 @@ func init() { Citation: "RFC 5280: 4.2.1.15", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &ExtFreshestCrlMarkedCritical{}, + Lint: NewExtFreshestCrlMarkedCritical, }) } -func (l *ExtFreshestCrlMarkedCritical) Initialize() error { - return nil +func NewExtFreshestCrlMarkedCritical() lint.LintInterface { + return &ExtFreshestCrlMarkedCritical{} } func (l *ExtFreshestCrlMarkedCritical) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_critical.go index 75eb2427b..f32665806 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_critical.go @@ -35,12 +35,12 @@ func init() { Citation: "RFC 5280: 4.2.1.7", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &ExtIANCritical{}, + Lint: NewExtIANCritical, }) } -func (l *ExtIANCritical) Initialize() error { - return nil +func NewExtIANCritical() lint.LintInterface { + return &ExtIANCritical{} } func (l *ExtIANCritical) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_dns_not_ia5_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_dns_not_ia5_string.go index 1d440f092..15c45ccf5 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_dns_not_ia5_string.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_dns_not_ia5_string.go @@ -45,12 +45,12 @@ func init() { Citation: "RFC 5280: 4.2.1.7", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &IANDNSNotIA5String{}, + Lint: NewIANDNSNotIA5String, }) } -func (l *IANDNSNotIA5String) Initialize() error { - return nil +func NewIANDNSNotIA5String() lint.LintInterface { + return &IANDNSNotIA5String{} } func (l *IANDNSNotIA5String) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_empty_name.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_empty_name.go index a2dc53e0e..757984aa2 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_empty_name.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_empty_name.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -43,12 +42,12 @@ func init() { Citation: "RFC 5280: 4.2.1.7", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &IANEmptyName{}, + Lint: NewIANEmptyName, }) } -func (l *IANEmptyName) Initialize() error { - return nil +func NewIANEmptyName() lint.LintInterface { + return &IANEmptyName{} } func (l *IANEmptyName) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_no_entries.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_no_entries.go index b23f7f839..eadb3b9fa 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_no_entries.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_no_entries.go @@ -41,12 +41,12 @@ func init() { Citation: "RFC 5280: 4.2.1.7", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &IANNoEntry{}, + Lint: NewIANNoEntry, }) } -func (l *IANNoEntry) Initialize() error { - return nil +func NewIANNoEntry() lint.LintInterface { + return &IANNoEntry{} } func (l *IANNoEntry) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_rfc822_format_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_rfc822_format_invalid.go index 122f2010d..46165145d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_rfc822_format_invalid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_rfc822_format_invalid.go @@ -43,12 +43,12 @@ func init() { Citation: "RFC 5280: 4.2.1.7", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &IANEmail{}, + Lint: NewIANEmail, }) } -func (l *IANEmail) Initialize() error { - return nil +func NewIANEmail() lint.LintInterface { + return &IANEmail{} } func (l *IANEmail) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_space_dns_name.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_space_dns_name.go index 6311236c2..495b82c7d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_space_dns_name.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_space_dns_name.go @@ -45,12 +45,12 @@ func init() { Citation: "RFC 5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &IANSpace{}, + Lint: NewIANSpace, }) } -func (l *IANSpace) Initialize() error { - return nil +func NewIANSpace() lint.LintInterface { + return &IANSpace{} } func (l *IANSpace) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_format_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_format_invalid.go index e461d5bd4..31b20a0dd 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_format_invalid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_format_invalid.go @@ -36,12 +36,12 @@ func init() { Citation: "RFC5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &IANURIFormat{}, + Lint: NewIANURIFormat, }) } -func (l *IANURIFormat) Initialize() error { - return nil +func NewIANURIFormat() lint.LintInterface { + return &IANURIFormat{} } func (l *IANURIFormat) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_host_not_fqdn_or_ip.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_host_not_fqdn_or_ip.go index 70eabf2d5..23afb908c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_host_not_fqdn_or_ip.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_host_not_fqdn_or_ip.go @@ -43,12 +43,12 @@ func init() { Citation: "RFC 5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &IANURIFQDNOrIP{}, + Lint: NewIANURIFQDNOrIP, }) } -func (l *IANURIFQDNOrIP) Initialize() error { - return nil +func NewIANURIFQDNOrIP() lint.LintInterface { + return &IANURIFQDNOrIP{} } func (l *IANURIFQDNOrIP) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_not_ia5.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_not_ia5.go index 6fe028648..41004ea36 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_not_ia5.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_not_ia5.go @@ -36,12 +36,12 @@ func init() { Citation: "RFC5280: 4.2.1.7", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &IANURIIA5String{}, + Lint: NewIANURIIA5String, }) } -func (l *IANURIIA5String) Initialize() error { - return nil +func NewIANURIIA5String() lint.LintInterface { + return &IANURIIA5String{} } func (l *IANURIIA5String) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_relative.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_relative.go index 0a14d22f4..7d1112d71 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_relative.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_ian_uri_relative.go @@ -43,12 +43,12 @@ func init() { Citation: "RFC 5280: 4.2.1.7", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &uriRelative{}, + Lint: NewUriRelative, }) } -func (l *uriRelative) Initialize() error { - return nil +func NewUriRelative() lint.LintInterface { + return &uriRelative{} } func (l *uriRelative) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_cert_sign_without_ca.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_cert_sign_without_ca.go index 4e2e853fc..655b46ffc 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_cert_sign_without_ca.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_cert_sign_without_ca.go @@ -40,12 +40,12 @@ func init() { Citation: "RFC 5280: 4.2.1.3 & 4.2.1.9", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &keyUsageCertSignNoCa{}, + Lint: NewKeyUsageCertSignNoCa, }) } -func (l *keyUsageCertSignNoCa) Initialize() error { - return nil +func NewKeyUsageCertSignNoCa() lint.LintInterface { + return &keyUsageCertSignNoCa{} } func (l *keyUsageCertSignNoCa) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_not_critical.go index 6bc654694..3a48341fe 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_not_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_not_critical.go @@ -31,12 +31,12 @@ func init() { Citation: "RFC 5280: 4.2.1.3", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &checkKeyUsageCritical{}, + Lint: NewCheckKeyUsageCritical, }) } -func (l *checkKeyUsageCritical) Initialize() error { - return nil +func NewCheckKeyUsageCritical() lint.LintInterface { + return &checkKeyUsageCritical{} } func (l *checkKeyUsageCritical) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_without_bits.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_without_bits.go index 4da1b36c9..fe5a918c1 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_without_bits.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_key_usage_without_bits.go @@ -38,12 +38,12 @@ func init() { Citation: "RFC 5280: 4.2.1.3", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &keyUsageBitsSet{}, + Lint: NewKeyUsageBitsSet, }) } -func (l *keyUsageBitsSet) Initialize() error { - return nil +func NewKeyUsageBitsSet() lint.LintInterface { + return &keyUsageBitsSet{} } func (l *keyUsageBitsSet) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_critical.go index 17272b702..81da91dd9 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_critical.go @@ -37,16 +37,16 @@ Restrictions are defined in terms of permitted or excluded name func init() { lint.RegisterLint(&lint.Lint{ Name: "e_ext_name_constraints_not_critical", - Description: "If it is included, conforming CAs MUST mark the name constrains extension as critical", + Description: "If it is included, conforming CAs MUST mark the name constraints extension as critical", Citation: "RFC 5280: 4.2.1.10", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &nameConstraintCrit{}, + Lint: NewNameConstraintCrit, }) } -func (l *nameConstraintCrit) Initialize() error { - return nil +func NewNameConstraintCrit() lint.LintInterface { + return &nameConstraintCrit{} } func (l *nameConstraintCrit) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_in_ca.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_in_ca.go index 18c0b7e72..eaedbf6f5 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_in_ca.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_name_constraints_not_in_ca.go @@ -40,12 +40,12 @@ func init() { Citation: "RFC 5280: 4.2.1.10", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &nameConstraintNotCa{}, + Lint: NewNameConstraintNotCa, }) } -func (l *nameConstraintNotCa) Initialize() error { - return nil +func NewNameConstraintNotCa() lint.LintInterface { + return &nameConstraintNotCa{} } func (l *nameConstraintNotCa) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_empty.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_empty.go index d4797f7b0..d7bed987a 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_empty.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_empty.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -40,12 +39,12 @@ func init() { Citation: "RFC 5280: 4.2.1.11", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &policyConstraintsContents{}, + Lint: NewPolicyConstraintsContents, }) } -func (l *policyConstraintsContents) Initialize() error { - return nil +func NewPolicyConstraintsContents() lint.LintInterface { + return &policyConstraintsContents{} } func (l *policyConstraintsContents) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_not_critical.go index 307abff69..6c2f2c40e 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_not_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_constraints_not_critical.go @@ -34,12 +34,12 @@ func init() { Citation: "RFC 5280: 4.2.1.11", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &policyConstraintsCritical{}, + Lint: NewPolicyConstraintsCritical, }) } -func (l *policyConstraintsCritical) Initialize() error { - return nil +func NewPolicyConstraintsCritical() lint.LintInterface { + return &policyConstraintsCritical{} } func (l *policyConstraintsCritical) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_any_policy.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_any_policy.go index 9fb661c37..a25e66d7b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_any_policy.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_any_policy.go @@ -37,12 +37,12 @@ func init() { Citation: "RFC 5280: 4.2.1.5", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &policyMapAnyPolicy{}, + Lint: NewPolicyMapAnyPolicy, }) } -func (l *policyMapAnyPolicy) Initialize() error { - return nil +func NewPolicyMapAnyPolicy() lint.LintInterface { + return &policyMapAnyPolicy{} } func (l *policyMapAnyPolicy) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_critical.go index 4d5d98011..49a4efbb5 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_critical.go @@ -35,12 +35,12 @@ func init() { Citation: "RFC 5280: 4.2.1.5", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &policyMapCritical{}, + Lint: NewPolicyMapCritical, }) } -func (l *policyMapCritical) Initialize() error { - return nil +func NewPolicyMapCritical() lint.LintInterface { + return &policyMapCritical{} } func (l *policyMapCritical) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_in_cert_policy.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_in_cert_policy.go index 8906cedc6..1555eec75 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_in_cert_policy.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_policy_map_not_in_cert_policy.go @@ -37,12 +37,12 @@ func init() { Citation: "RFC 5280: 4.2.1.5", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &policyMapMatchesCertPolicy{}, + Lint: NewPolicyMapMatchesCertPolicy, }) } -func (l *policyMapMatchesCertPolicy) Initialize() error { - return nil +func NewPolicyMapMatchesCertPolicy() lint.LintInterface { + return &policyMapMatchesCertPolicy{} } func (l *policyMapMatchesCertPolicy) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_name_too_long.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_name_too_long.go index daaea49cc..f55b0bff3 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_name_too_long.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_name_too_long.go @@ -29,12 +29,12 @@ func init() { Citation: "RFC 5280", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &SANDNSTooLong{}, + Lint: NewSANDNSTooLong, }) } -func (l *SANDNSTooLong) Initialize() error { - return nil +func NewSANDNSTooLong() lint.LintInterface { + return &SANDNSTooLong{} } func (l *SANDNSTooLong) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_not_ia5_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_not_ia5_string.go index 46d006845..8dc456bc8 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_not_ia5_string.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_dns_not_ia5_string.go @@ -45,12 +45,12 @@ func init() { Citation: "RFC 5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &SANDNSNotIA5String{}, + Lint: NewSANDNSNotIA5String, }) } -func (l *SANDNSNotIA5String) Initialize() error { - return nil +func NewSANDNSNotIA5String() lint.LintInterface { + return &SANDNSNotIA5String{} } func (l *SANDNSNotIA5String) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_empty_name.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_empty_name.go index 8f1b15229..47256b9b6 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_empty_name.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_empty_name.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -43,12 +42,12 @@ func init() { Citation: "RFC 5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &SANEmptyName{}, + Lint: NewSANEmptyName, }) } -func (l *SANEmptyName) Initialize() error { - return nil +func NewSANEmptyName() lint.LintInterface { + return &SANEmptyName{} } func (l *SANEmptyName) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_no_entries.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_no_entries.go index dae062c72..fef7d8fde 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_no_entries.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_no_entries.go @@ -41,12 +41,12 @@ func init() { Citation: "RFC 5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &SANNoEntry{}, + Lint: NewSANNoEntry, }) } -func (l *SANNoEntry) Initialize() error { - return nil +func NewSANNoEntry() lint.LintInterface { + return &SANNoEntry{} } func (l *SANNoEntry) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_not_critical_without_subject.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_not_critical_without_subject.go index 99cf835c1..91e729a94 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_not_critical_without_subject.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_not_critical_without_subject.go @@ -42,12 +42,12 @@ func init() { Citation: "RFC 5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &extSANNotCritNoSubject{}, + Lint: NewExtSANNotCritNoSubject, }) } -func (l *extSANNotCritNoSubject) Initialize() error { - return nil +func NewExtSANNotCritNoSubject() lint.LintInterface { + return &extSANNotCritNoSubject{} } func (l *extSANNotCritNoSubject) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_rfc822_format_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_rfc822_format_invalid.go index 2797f60c2..9364a496d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_rfc822_format_invalid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_rfc822_format_invalid.go @@ -43,12 +43,12 @@ func init() { Citation: "RFC 5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &invalidEmail{}, + Lint: NewInvalidEmail, }) } -func (l *invalidEmail) Initialize() error { - return nil +func NewInvalidEmail() lint.LintInterface { + return &invalidEmail{} } func (l *invalidEmail) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_space_dns_name.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_space_dns_name.go index 8fb6f2197..4b59e987d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_space_dns_name.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_space_dns_name.go @@ -45,12 +45,12 @@ func init() { Citation: "RFC 5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &SANIsSpaceDNS{}, + Lint: NewSANIsSpaceDNS, }) } -func (l *SANIsSpaceDNS) Initialize() error { - return nil +func NewSANIsSpaceDNS() lint.LintInterface { + return &SANIsSpaceDNS{} } func (l *SANIsSpaceDNS) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_format_invalid.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_format_invalid.go index de462c86f..6b727d457 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_format_invalid.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_format_invalid.go @@ -36,12 +36,12 @@ func init() { Citation: "RFC5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &extSANURIFormatInvalid{}, + Lint: NewExtSANURIFormatInvalid, }) } -func (l *extSANURIFormatInvalid) Initialize() error { - return nil +func NewExtSANURIFormatInvalid() lint.LintInterface { + return &extSANURIFormatInvalid{} } func (l *extSANURIFormatInvalid) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_host_not_fqdn_or_ip.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_host_not_fqdn_or_ip.go index 929e70a91..94d9bd2a1 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_host_not_fqdn_or_ip.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_host_not_fqdn_or_ip.go @@ -43,12 +43,12 @@ func init() { Citation: "RFC 5280: 4.2.1.7", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &SANURIHost{}, + Lint: NewSANURIHost, }) } -func (l *SANURIHost) Initialize() error { - return nil +func NewSANURIHost() lint.LintInterface { + return &SANURIHost{} } func (l *SANURIHost) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_not_ia5.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_not_ia5.go index ff75b29fc..5e6183655 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_not_ia5.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_not_ia5.go @@ -36,12 +36,12 @@ func init() { Citation: "RFC5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &extSANURINotIA5{}, + Lint: NewExtSANURINotIA5, }) } -func (l *extSANURINotIA5) Initialize() error { - return nil +func NewExtSANURINotIA5() lint.LintInterface { + return &extSANURINotIA5{} } func (l *extSANURINotIA5) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_relative.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_relative.go index 3abfd7095..901cd0a17 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_relative.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_san_uri_relative.go @@ -43,12 +43,12 @@ func init() { Citation: "RFC 5280: 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &extSANURIRelative{}, + Lint: NewExtSANURIRelative, }) } -func (l *extSANURIRelative) Initialize() error { - return nil +func NewExtSANURIRelative() lint.LintInterface { + return &extSANURIRelative{} } func (l *extSANURIRelative) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_directory_attr_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_directory_attr_critical.go index f24fe5c08..f1dbf9f53 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_directory_attr_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_directory_attr_critical.go @@ -37,12 +37,12 @@ func init() { Citation: "RFC 5280: 4.2.1.8", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subDirAttrCrit{}, + Lint: NewSubDirAttrCrit, }) } -func (l *subDirAttrCrit) Initialize() error { - return nil +func NewSubDirAttrCrit() lint.LintInterface { + return &subDirAttrCrit{} } func (l *subDirAttrCrit) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_critical.go index 8979ef13c..9351893ba 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_critical.go @@ -34,12 +34,12 @@ func init() { Citation: "RFC 5280: 4.2.1.2", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectKeyIdCritical{}, + Lint: NewSubjectKeyIdCritical, }) } -func (l *subjectKeyIdCritical) Initialize() error { - return nil +func NewSubjectKeyIdCritical() lint.LintInterface { + return &subjectKeyIdCritical{} } func (l *subjectKeyIdCritical) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_ca.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_ca.go index 87e1f524e..dc7754cca 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_ca.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_ca.go @@ -49,12 +49,12 @@ func init() { Citation: "RFC 5280: 4.2 & 4.2.1.2", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectKeyIdMissingCA{}, + Lint: NewSubjectKeyIdMissingCA, }) } -func (l *subjectKeyIdMissingCA) Initialize() error { - return nil +func NewSubjectKeyIdMissingCA() lint.LintInterface { + return &subjectKeyIdMissingCA{} } func (l *subjectKeyIdMissingCA) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_sub_cert.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_sub_cert.go index 9e8932613..791460619 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_sub_cert.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_ext_subject_key_identifier_missing_sub_cert.go @@ -49,12 +49,12 @@ func init() { Citation: "RFC 5280: 4.2 & 4.2.1.2", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectKeyIdMissingSubscriber{}, + Lint: NewSubjectKeyIdMissingSubscriber, }) } -func (l *subjectKeyIdMissingSubscriber) Initialize() error { - return nil +func NewSubjectKeyIdMissingSubscriber() lint.LintInterface { + return &subjectKeyIdMissingSubscriber{} } func (l *subjectKeyIdMissingSubscriber) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_does_not_include_seconds.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_does_not_include_seconds.go index 702e2f703..b6839f8ec 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_does_not_include_seconds.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_does_not_include_seconds.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -45,12 +44,12 @@ func init() { Citation: "RFC 5280: 4.1.2.5.2", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &generalizedNoSeconds{}, + Lint: NewGeneralizedNoSeconds, }) } -func (l *generalizedNoSeconds) Initialize() error { - return nil +func NewGeneralizedNoSeconds() lint.LintInterface { + return &generalizedNoSeconds{} } func (l *generalizedNoSeconds) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_includes_fraction_seconds.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_includes_fraction_seconds.go index 0fb591118..eb0590ce8 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_includes_fraction_seconds.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_includes_fraction_seconds.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -45,12 +44,12 @@ func init() { Citation: "RFC 5280: 4.1.2.5.2", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &generalizedTimeFraction{}, + Lint: NewGeneralizedTimeFraction, }) } -func (l *generalizedTimeFraction) Initialize() error { - return nil +func NewGeneralizedTimeFraction() lint.LintInterface { + return &generalizedTimeFraction{} } func (l *generalizedTimeFraction) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_not_in_zulu.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_not_in_zulu.go index 353d7f99f..efdb79519 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_not_in_zulu.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_generalized_time_not_in_zulu.go @@ -43,12 +43,12 @@ func init() { Citation: "RFC 5280: 4.1.2.5.2", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &generalizedNotZulu{}, + Lint: NewGeneralizedNotZulu, }) } -func (l *generalizedNotZulu) Initialize() error { - return nil +func NewGeneralizedNotZulu() lint.LintInterface { + return &generalizedNotZulu{} } func (l *generalizedNotZulu) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_malformed_unicode.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_malformed_unicode.go index 65322734b..347d5900d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_malformed_unicode.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_malformed_unicode.go @@ -20,7 +20,6 @@ import ( "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" - "golang.org/x/net/idna" ) type IDNMalformedUnicode struct{} @@ -28,16 +27,16 @@ type IDNMalformedUnicode struct{} func init() { lint.RegisterLint(&lint.Lint{ Name: "e_international_dns_name_not_unicode", - Description: "Internationalized DNSNames punycode not valid unicode", + Description: "Internationalized DNSNames punycode not valid Unicode", Citation: "RFC 3490", EffectiveDate: util.RFC3490Date, Source: lint.RFC5280, - Lint: &IDNMalformedUnicode{}, + Lint: NewIDNMalformedUnicode, }) } -func (l *IDNMalformedUnicode) Initialize() error { - return nil +func NewIDNMalformedUnicode() lint.LintInterface { + return &IDNMalformedUnicode{} } func (l *IDNMalformedUnicode) CheckApplies(c *x509.Certificate) bool { @@ -48,8 +47,8 @@ func (l *IDNMalformedUnicode) Execute(c *x509.Certificate) *lint.LintResult { for _, dns := range c.DNSNames { labels := strings.Split(dns, ".") for _, label := range labels { - if strings.HasPrefix(label, "xn--") { - _, err := idna.ToUnicode(label) + if util.HasXNLabelPrefix(label) { + _, err := util.IdnaToUnicode(label) if err != nil { return &lint.LintResult{Status: lint.Error} } diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_must_be_nfc.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_must_be_nfc.go index 13b69762c..09b7b5e5b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_must_be_nfc.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_idn_dnsname_must_be_nfc.go @@ -20,7 +20,6 @@ import ( "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" - "golang.org/x/net/idna" "golang.org/x/text/unicode/norm" ) @@ -29,16 +28,16 @@ type IDNNotNFC struct{} func init() { lint.RegisterLint(&lint.Lint{ Name: "e_international_dns_name_not_nfc", - Description: "Internationalized DNSNames must be normalized by unicode normalization form C", + Description: "Internationalized DNSNames must be normalized by Unicode normalization form C", Citation: "RFC 8399", Source: lint.RFC5891, EffectiveDate: util.RFC8399Date, - Lint: &IDNNotNFC{}, + Lint: NewIDNNotNFC, }) } -func (l *IDNNotNFC) Initialize() error { - return nil +func NewIDNNotNFC() lint.LintInterface { + return &IDNNotNFC{} } func (l *IDNNotNFC) CheckApplies(c *x509.Certificate) bool { @@ -49,8 +48,8 @@ func (l *IDNNotNFC) Execute(c *x509.Certificate) *lint.LintResult { for _, dns := range c.DNSNames { labels := strings.Split(dns, ".") for _, label := range labels { - if strings.HasPrefix(label, "xn--") { - unicodeLabel, err := idna.ToUnicode(label) + if util.HasXNLabelPrefix(label) { + unicodeLabel, err := util.IdnaToUnicode(label) if err != nil { return &lint.LintResult{Status: lint.NA} } diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_incorrect_ku_encoding.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_incorrect_ku_encoding.go new file mode 100644 index 000000000..877792556 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_incorrect_ku_encoding.go @@ -0,0 +1,80 @@ +/* + * ZLint Copyright 2022 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "fmt" + "math/big" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_incorrect_ku_encoding", + Description: "RFC 5280 Section 4.2.1.3 describes the value of a KeyUsage to be a DER encoded BitString, which itself defines that all trailing 0 bits be counted as being \"unused\".", + Citation: "Where ITU-T Rec. X.680 | ISO/IEC 8824-1, 21.7, applies, the bitstring shall have all trailing 0 bits removed before it is encoded.", + Source: lint.RFC5280, + EffectiveDate: util.ZeroDate, + Lint: func() lint.LintInterface { return &incorrectKuEncoding{} }, + }) +} + +type incorrectKuEncoding struct{} + +func NewIncorrectKuEncoding() lint.LintInterface { + return &incorrectKuEncoding{} +} + +func (l *incorrectKuEncoding) CheckApplies(c *x509.Certificate) bool { + ku := util.GetExtFromCert(c, util.KeyUsageOID) + return ku != nil && len(ku.Value) > 0 +} + +func (l *incorrectKuEncoding) Execute(c *x509.Certificate) *lint.LintResult { + ku := util.GetExtFromCert(c, util.KeyUsageOID).Value + if len(ku) < 4 { + return &lint.LintResult{ + Status: lint.Fatal, + Details: fmt.Sprintf("KeyUsage encodings must be at least four bytes long. Got %d bytes", len(ku)), + } + } + // Byte 0: Tag + // Byte 1: Length + // Byte 2: Unused bits + // Bytes 3..n: KeyUsage + declaredUnused := uint(ku[2]) + actualUnused := big.NewInt(0).SetBytes(ku[3:]).TrailingZeroBits() + if declaredUnused == actualUnused { + return &lint.LintResult{Status: lint.Pass} + } + // Just a bit of formatting to a visualized binary form so + // it's easier for users to see what the exact binary that + // we're referring to so that they can debug their own certs. + binary := make([]string, len(ku)) + for i, b := range ku { + binary[i] = fmt.Sprintf("%08b", b) + } + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf( + "KeyUsage contains an inefficient encoding wherein the number of 'unused bits' is declared to be "+ + "%d, but it should be %d. Raw Bytes: %v, Raw Binary: [%s]", + declaredUnused, actualUnused, ku, strings.Join(binary, " "), + )} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_inhibit_any_policy_not_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_inhibit_any_policy_not_critical.go index 93cb4b654..4473eeae1 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_inhibit_any_policy_not_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_inhibit_any_policy_not_critical.go @@ -44,12 +44,12 @@ func init() { Citation: "RFC 5280: 4.2.1.14", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &InhibitAnyPolicyNotCritical{}, + Lint: NewInhibitAnyPolicyNotCritical, }) } -func (l *InhibitAnyPolicyNotCritical) Initialize() error { - return nil +func NewInhibitAnyPolicyNotCritical() lint.LintInterface { + return &InhibitAnyPolicyNotCritical{} } func (l *InhibitAnyPolicyNotCritical) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_dn_country_not_printable_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_dn_country_not_printable_string.go index 504a36d33..09895f94f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_dn_country_not_printable_string.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_dn_country_not_printable_string.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -31,12 +30,12 @@ func init() { Citation: "RFC 5280: Appendix A", Source: lint.RFC5280, EffectiveDate: util.ZeroDate, - Lint: &IssuerDNCountryNotPrintableString{}, + Lint: NewIssuerDNCountryNotPrintableString, }) } -func (l *IssuerDNCountryNotPrintableString) Initialize() error { - return nil +func NewIssuerDNCountryNotPrintableString() lint.LintInterface { + return &IssuerDNCountryNotPrintableString{} } func (l *IssuerDNCountryNotPrintableString) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_field_empty.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_field_empty.go index f13c26ad0..312cf4c5b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_field_empty.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_issuer_field_empty.go @@ -37,12 +37,12 @@ func init() { Citation: "RFC 5280: 4.1.2.4", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &issuerFieldEmpty{}, + Lint: NewIssuerFieldEmpty, }) } -func (l *issuerFieldEmpty) Initialize() error { - return nil +func NewIssuerFieldEmpty() lint.LintInterface { + return &issuerFieldEmpty{} } func (l *issuerFieldEmpty) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_key_usage_incorrect_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_key_usage_incorrect_length.go new file mode 100644 index 000000000..47bd9041c --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_key_usage_incorrect_length.go @@ -0,0 +1,67 @@ +package rfc + +/* + * ZLint Copyright 2022 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import ( + "encoding/asn1" + "fmt" + "math/big" + + "golang.org/x/crypto/cryptobyte" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type keyUsageIncorrectLength struct{} + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_key_usage_incorrect_length", + Description: "The key usage is a bit string with exactly nine possible flags", + Citation: "RFC 5280: 4.2.1.3", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + Lint: NewKeyUsageIncorrectLength, + }) +} + +func NewKeyUsageIncorrectLength() lint.LintInterface { + return &keyUsageIncorrectLength{} +} + +func (l *keyUsageIncorrectLength) CheckApplies(c *x509.Certificate) bool { + return util.IsExtInCert(c, util.KeyUsageOID) +} + +func keyUsageIncorrectLengthBytes(kuBytes []byte) *lint.LintResult { + keyUsageExt := cryptobyte.String(kuBytes) + var keyUsageVal asn1.BitString + ok := keyUsageExt.ReadASN1BitString(&keyUsageVal) + if !ok { + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("the key usage (%v) extension is not parseable.", kuBytes)} + } + unused := kuBytes[2] + kuBig := big.NewInt(0).SetBytes(keyUsageVal.Bytes) + if !kuBig.IsInt64() || kuBig.Int64()>>unused >= 512 { + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("the key usage (%v) contains a value that is out of bounds of the range of possible KU values. (raw ASN: %v)", keyUsageVal.Bytes, kuBytes)} + } + return &lint.LintResult{Status: lint.Pass} +} + +func (l *keyUsageIncorrectLength) Execute(c *x509.Certificate) *lint.LintResult { + return keyUsageIncorrectLengthBytes(util.GetExtFromCert(c, util.KeyUsageOID).Value) +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_empty.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_empty.go index 958bca660..7815ee099 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_empty.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_empty.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -43,12 +42,12 @@ func init() { Citation: "RFC 5280: 4.2.1.10", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &nameConstraintEmpty{}, + Lint: NewNameConstraintEmpty, }) } -func (l *nameConstraintEmpty) Initialize() error { - return nil +func NewNameConstraintEmpty() lint.LintInterface { + return &nameConstraintEmpty{} } func (l *nameConstraintEmpty) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_maximum_not_absent.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_maximum_not_absent.go index 2a5c653f2..c8a25c9ec 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_maximum_not_absent.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_maximum_not_absent.go @@ -40,12 +40,12 @@ func init() { Citation: "RFC 5280: 4.2.1.10", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &nameConstraintMax{}, + Lint: NewNameConstraintMax, }) } -func (l *nameConstraintMax) Initialize() error { - return nil +func NewNameConstraintMax() lint.LintInterface { + return &nameConstraintMax{} } func (l *nameConstraintMax) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_minimum_non_zero.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_minimum_non_zero.go index a64a67b64..1393ac743 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_minimum_non_zero.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_minimum_non_zero.go @@ -40,12 +40,12 @@ func init() { Citation: "RFC 5280: 4.2.1.10", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &nameConstMin{}, + Lint: NewNameConstMin, }) } -func (l *nameConstMin) Initialize() error { - return nil +func NewNameConstMin() lint.LintInterface { + return &nameConstMin{} } func (l *nameConstMin) CheckApplies(c *x509.Certificate) bool { @@ -53,6 +53,7 @@ func (l *nameConstMin) CheckApplies(c *x509.Certificate) bool { } //nolint:gocyclo +//nolint:cyclop func (l *nameConstMin) Execute(c *x509.Certificate) *lint.LintResult { for _, i := range c.PermittedDNSNames { if i.Min != 0 { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_not_fqdn.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_not_fqdn.go index ae283df50..1775472af 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_not_fqdn.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_not_fqdn.go @@ -43,12 +43,12 @@ func init() { Citation: "RFC 5280: 4.2.1.10", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &nameConstraintNotFQDN{}, + Lint: NewNameConstraintNotFQDN, }) } -func (l *nameConstraintNotFQDN) Initialize() error { - return nil +func NewNameConstraintNotFQDN() lint.LintInterface { + return &nameConstraintNotFQDN{} } func (l *nameConstraintNotFQDN) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_edi_party_name.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_edi_party_name.go index 13150c7cd..7aee6c9d1 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_edi_party_name.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_edi_party_name.go @@ -42,12 +42,12 @@ func init() { Citation: "RFC 5280: 4.2.1.10", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &nameConstraintOnEDI{}, + Lint: NewNameConstraintOnEDI, }) } -func (l *nameConstraintOnEDI) Initialize() error { - return nil +func NewNameConstraintOnEDI() lint.LintInterface { + return &nameConstraintOnEDI{} } func (l *nameConstraintOnEDI) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_registered_id.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_registered_id.go index 583c680fb..e626d55c3 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_registered_id.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_registered_id.go @@ -42,12 +42,12 @@ func init() { Citation: "RFC 5280: 4.2.1.10", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &nameConstraintOnRegisteredId{}, + Lint: NewNameConstraintOnRegisteredId, }) } -func (l *nameConstraintOnRegisteredId) Initialize() error { - return nil +func NewNameConstraintOnRegisteredId() lint.LintInterface { + return &nameConstraintOnRegisteredId{} } func (l *nameConstraintOnRegisteredId) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_x400.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_x400.go index 1bfb012c0..42fb5c67c 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_x400.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_name_constraint_on_x400.go @@ -42,12 +42,12 @@ func init() { Citation: "RFC 5280: 4.2.1.10", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &nameConstraintOnX400{}, + Lint: NewNameConstraintOnX400, }) } -func (l *nameConstraintOnX400) Initialize() error { - return nil +func NewNameConstraintOnX400() lint.LintInterface { + return &nameConstraintOnX400{} } func (l *nameConstraintOnX400) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_improperly_included.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_improperly_included.go index 7fc68a799..7d08aff28 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_improperly_included.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_improperly_included.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -38,12 +37,12 @@ func init() { Citation: "RFC 5280: 4.2.1.9", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &pathLenIncluded{}, + Lint: NewPathLenIncluded, }) } -func (l *pathLenIncluded) Initialize() error { - return nil +func NewPathLenIncluded() lint.LintInterface { + return &pathLenIncluded{} } func (l *pathLenIncluded) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_zero_or_less.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_zero_or_less.go index 0bc2d0892..44f20bde2 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_zero_or_less.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_path_len_constraint_zero_or_less.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -53,12 +52,12 @@ func init() { Citation: "RFC 5280: 4.2.1.9", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &pathLenNonPositive{}, + Lint: NewPathLenNonPositive, }) } -func (l *pathLenNonPositive) Initialize() error { - return nil +func NewPathLenNonPositive() lint.LintInterface { + return &pathLenNonPositive{} } func (l *pathLenNonPositive) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_rsa_allowed_ku_ca.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_rsa_allowed_ku_ca.go new file mode 100644 index 000000000..158c055ab --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_rsa_allowed_ku_ca.go @@ -0,0 +1,94 @@ +/* + * ZLint Copyright 2022 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "fmt" + "sort" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaAllowedKUCa struct{} + +/************************************************ +RFC 3279: 2.3.1 RSA Keys + If the keyUsage extension is present in a CA or CRL issuer + certificate which conveys an RSA public key, any combination of the + following values MAY be present: + + digitalSignature; + nonRepudiation; + keyEncipherment; + dataEncipherment; + keyCertSign; and + cRLSign. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rsa_allowed_ku_ca", + Description: "Key usage values digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyCertSign, and cRLSign may only be present in a CA certificate with an RSA key", + Citation: "RFC 3279: 2.3.1", + Source: lint.RFC3279, + EffectiveDate: util.RFC3279Date, + Lint: NewRsaAllowedKUCa, + }) +} + +func NewRsaAllowedKUCa() lint.LintInterface { + return &rsaAllowedKUCa{} +} + +func (l *rsaAllowedKUCa) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.RSA && util.HasKeyUsageOID(c) && util.IsCACert(c) +} + +func (l *rsaAllowedKUCa) Execute(c *x509.Certificate) *lint.LintResult { + + //KeyUsageDigitalSignature: allowed + //KeyUsageContentCommitment: allowed + //KeyUsageKeyEncipherment: allowed + //KeyUsageDataEncipherment: allowed + //KeyUsageKeyAgreement: not allowed + //KeyUsageCertSign: allowed + //KeyUsageCRLSign: allowed + //KeyUsageEncipherOnly: not allowed + //KeyUsageDecipherOnly: not allowed + + var invalidKUs []string + + disallowedKUs := [3]x509.KeyUsage{x509.KeyUsageKeyAgreement, x509.KeyUsageEncipherOnly, x509.KeyUsageDecipherOnly} + + for _, disallowedKU := range disallowedKUs { + if util.HasKeyUsage(c, disallowedKU) { + invalidKUs = append(invalidKUs, util.KeyUsageToString[disallowedKU]) + } + } + + if len(invalidKUs) > 0 { + // Sort the invalid KUs to allow consistent ordering of Details messages for unit testing + sort.Strings(invalidKUs) + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("CA certificate with an RSA key contains invalid key usage(s): %s", strings.Join(invalidKUs, ", ")), + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_rsa_allowed_ku_ee.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_rsa_allowed_ku_ee.go new file mode 100644 index 000000000..4902a758a --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_rsa_allowed_ku_ee.go @@ -0,0 +1,92 @@ +/* + * ZLint Copyright 2022 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "fmt" + "sort" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaAllowedKUEe struct{} + +/************************************************ +RFC 3279: 2.3.1 RSA Keys + If the keyUsage extension is present in an end entity certificate + which conveys an RSA public key, any combination of the following + values MAY be present: + + digitalSignature; + nonRepudiation; + keyEncipherment; and + dataEncipherment. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rsa_allowed_ku_ee", + Description: "Key usage values digitalSignature, nonRepudiation, keyEncipherment, and dataEncipherment may only be present in an end entity certificate with an RSA key", + Citation: "RFC 3279: 2.3.1", + Source: lint.RFC3279, + EffectiveDate: util.RFC3279Date, + Lint: NewRsaAllowedKUEe, + }) +} + +func NewRsaAllowedKUEe() lint.LintInterface { + return &rsaAllowedKUEe{} +} + +func (l *rsaAllowedKUEe) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.RSA && util.HasKeyUsageOID(c) && util.IsSubscriberCert(c) +} + +func (l *rsaAllowedKUEe) Execute(c *x509.Certificate) *lint.LintResult { + + //KeyUsageDigitalSignature: allowed + //KeyUsageContentCommitment: allowed + //KeyUsageKeyEncipherment: allowed + //KeyUsageDataEncipherment: allowed + //KeyUsageKeyAgreement: not allowed + //KeyUsageCertSign: not allowed + //KeyUsageCRLSign: not allowed + //KeyUsageEncipherOnly: not allowed + //KeyUsageDecipherOnly: not allowed + + var invalidKUs []string + + disallowedKUs := [5]x509.KeyUsage{x509.KeyUsageKeyAgreement, x509.KeyUsageCertSign, x509.KeyUsageCRLSign, x509.KeyUsageEncipherOnly, x509.KeyUsageDecipherOnly} + + for _, disallowedKU := range disallowedKUs { + if util.HasKeyUsage(c, disallowedKU) { + invalidKUs = append(invalidKUs, util.KeyUsageToString[disallowedKU]) + } + } + + if len(invalidKUs) > 0 { + // Sort the invalid KUs to allow consistent ordering of Details messages for unit testing + sort.Strings(invalidKUs) + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("Subscriber certificate with an RSA key contains invalid key usage(s): %s", strings.Join(invalidKUs, ", ")), + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_rsa_allowed_ku_no_encipherment_ca.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_rsa_allowed_ku_no_encipherment_ca.go new file mode 100644 index 000000000..a8d74bf57 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_rsa_allowed_ku_no_encipherment_ca.go @@ -0,0 +1,71 @@ +/* + * ZLint Copyright 2022 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type rsaAllowedKUCaNoEncipherment struct{} + +/************************************************ +RFC 3279: 2.3.1 RSA Keys + If the keyUsage extension is present in a CA or CRL issuer + certificate which conveys an RSA public key, any combination of the + following values MAY be present: + + digitalSignature; + nonRepudiation; + keyEncipherment; + dataEncipherment; + keyCertSign; and + cRLSign. + + However, this specification RECOMMENDS that if keyCertSign or cRLSign + is present, both keyEncipherment and dataEncipherment SHOULD NOT be + present. +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_rsa_allowed_ku_no_encipherment_ca", + Description: "If Key usage value keyCertSign or cRLSign is present in a CA certificate both keyEncipherment and dataEncipherment SHOULD NOT be present", + Citation: "RFC 3279: 2.3.1", + Source: lint.RFC3279, + EffectiveDate: util.RFC3279Date, + Lint: NewRsaAllowedKUCaNoEncipherment, + }) +} + +func NewRsaAllowedKUCaNoEncipherment() lint.LintInterface { + return &rsaAllowedKUCaNoEncipherment{} +} + +func (l *rsaAllowedKUCaNoEncipherment) CheckApplies(c *x509.Certificate) bool { + return c.PublicKeyAlgorithm == x509.RSA && util.HasKeyUsageOID(c) && util.IsCACert(c) +} + +func (l *rsaAllowedKUCaNoEncipherment) Execute(c *x509.Certificate) *lint.LintResult { + + if util.HasKeyUsage(c, x509.KeyUsageCertSign) || util.HasKeyUsage(c, x509.KeyUsageCRLSign) { + if util.HasKeyUsage(c, x509.KeyUsageKeyEncipherment) || util.HasKeyUsage(c, x509.KeyUsageDataEncipherment) { + return &lint.LintResult{Status: lint.Error, Details: "CA certificate with an RSA key and key usage keyCertSign and/or cRLSign has additionally keyEncipherment and/or dataEncipherment key usage"} + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_longer_than_20_octets.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_longer_than_20_octets.go index 71f661b71..0e490c60a 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_longer_than_20_octets.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_longer_than_20_octets.go @@ -15,9 +15,9 @@ package rfc */ import ( - "encoding/asn1" "fmt" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -49,12 +49,12 @@ func init() { Citation: "RFC 5280: 4.1.2.2", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &serialNumberTooLong{}, + Lint: NewSerialNumberTooLong, }) } -func (l *serialNumberTooLong) Initialize() error { - return nil +func NewSerialNumberTooLong() lint.LintInterface { + return &serialNumberTooLong{} } func (l *serialNumberTooLong) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_not_positive.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_not_positive.go index c2cc41900..de3d2848f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_not_positive.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_serial_number_not_positive.go @@ -46,12 +46,12 @@ func init() { Citation: "RFC 5280: 4.1.2.2", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &SerialNumberNotPositive{}, + Lint: NewSerialNumberNotPositive, }) } -func (l *SerialNumberNotPositive) Initialize() error { - return nil +func NewSerialNumberNotPositive() lint.LintInterface { + return &SerialNumberNotPositive{} } func (l *SerialNumberNotPositive) CheckApplies(cert *x509.Certificate) bool { @@ -59,7 +59,9 @@ func (l *SerialNumberNotPositive) CheckApplies(cert *x509.Certificate) bool { } func (l *SerialNumberNotPositive) Execute(cert *x509.Certificate) *lint.LintResult { - if cert.SerialNumber.Sign() == -1 { // -1 Means negative when using big.Sign() + // -1 Means negative when using big.Sign() + // As per the BitLen docs, "The bit length of 0 is 0." + if cert.SerialNumber.Sign() == -1 || cert.SerialNumber.BitLen() == 0 { return &lint.LintResult{Status: lint.Error} } else { return &lint.LintResult{Status: lint.Pass} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_spki_rsa_encryption_parameter_not_null.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_spki_rsa_encryption_parameter_not_null.go index b4c6a0fbc..af73101ab 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_spki_rsa_encryption_parameter_not_null.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_spki_rsa_encryption_parameter_not_null.go @@ -36,12 +36,12 @@ func init() { Citation: "RFC 4055, Section 1.2", Source: lint.RFC5280, // RFC4055 is referenced in lint.RFC5280, Section 1 EffectiveDate: util.RFC5280Date, - Lint: &rsaSPKIEncryptionParamNotNULL{}, + Lint: NewRsaSPKIEncryptionParamNotNULL, }) } -func (l *rsaSPKIEncryptionParamNotNULL) Initialize() error { - return nil +func NewRsaSPKIEncryptionParamNotNULL() lint.LintInterface { + return &rsaSPKIEncryptionParamNotNULL{} } func (l *rsaSPKIEncryptionParamNotNULL) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_common_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_common_name_max_length.go index 7a6daeef0..1fdf5f2ec 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_common_name_max_length.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_common_name_max_length.go @@ -38,12 +38,12 @@ func init() { Citation: "RFC 5280: A.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectCommonNameMaxLength{}, + Lint: NewSubjectCommonNameMaxLength, }) } -func (l *subjectCommonNameMaxLength) Initialize() error { - return nil +func NewSubjectCommonNameMaxLength() lint.LintInterface { + return &subjectCommonNameMaxLength{} } func (l *subjectCommonNameMaxLength) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_country_not_printable_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_country_not_printable_string.go index e1ad97aa7..22efb3d4a 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_country_not_printable_string.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_country_not_printable_string.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -31,12 +30,12 @@ func init() { Citation: "RFC 5280: Appendix A", Source: lint.RFC5280, EffectiveDate: util.ZeroDate, - Lint: &SubjectDNCountryNotPrintableString{}, + Lint: NewSubjectDNCountryNotPrintableString, }) } -func (l *SubjectDNCountryNotPrintableString) Initialize() error { - return nil +func NewSubjectDNCountryNotPrintableString() lint.LintInterface { + return &SubjectDNCountryNotPrintableString{} } func (l *SubjectDNCountryNotPrintableString) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_not_printable_characters.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_not_printable_characters.go index f5f97e5e5..2a6b710da 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_not_printable_characters.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_not_printable_characters.go @@ -15,9 +15,9 @@ package rfc import ( - "encoding/asn1" "unicode/utf8" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -32,12 +32,12 @@ func init() { Citation: "RFC 5280: Appendix A", Source: lint.RFC5280, EffectiveDate: util.ZeroDate, - Lint: &subjectDNNotPrintableCharacters{}, + Lint: NewSubjectDNNotPrintableCharacters, }) } -func (l *subjectDNNotPrintableCharacters) Initialize() error { - return nil +func NewSubjectDNNotPrintableCharacters() lint.LintInterface { + return &subjectDNNotPrintableCharacters{} } func (l *subjectDNNotPrintableCharacters) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_max_length.go index f84855e62..66bf32635 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_max_length.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_max_length.go @@ -31,12 +31,12 @@ func init() { Citation: "RFC 5280: Appendix A", Source: lint.RFC5280, EffectiveDate: util.ZeroDate, - Lint: &SubjectDNSerialNumberMaxLength{}, + Lint: NewSubjectDNSerialNumberMaxLength, }) } -func (l *SubjectDNSerialNumberMaxLength) Initialize() error { - return nil +func NewSubjectDNSerialNumberMaxLength() lint.LintInterface { + return &SubjectDNSerialNumberMaxLength{} } func (l *SubjectDNSerialNumberMaxLength) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_not_printable_string.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_not_printable_string.go index 18b54c57e..ee904cb92 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_not_printable_string.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_dn_serial_number_not_printable_string.go @@ -15,8 +15,7 @@ package rfc */ import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -31,12 +30,12 @@ func init() { Citation: "RFC 5280: Appendix A", Source: lint.RFC5280, EffectiveDate: util.ZeroDate, - Lint: &SubjectDNSerialNumberNotPrintableString{}, + Lint: NewSubjectDNSerialNumberNotPrintableString, }) } -func (l *SubjectDNSerialNumberNotPrintableString) Initialize() error { - return nil +func NewSubjectDNSerialNumberNotPrintableString() lint.LintInterface { + return &SubjectDNSerialNumberNotPrintableString{} } func (l *SubjectDNSerialNumberNotPrintableString) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_email_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_email_max_length.go index 88259b731..1e2721f8d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_email_max_length.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_email_max_length.go @@ -45,12 +45,12 @@ func init() { Citation: "RFC 5280: A.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectEmailMaxLength{}, + Lint: NewSubjectEmailMaxLength, }) } -func (l *subjectEmailMaxLength) Initialize() error { - return nil +func NewSubjectEmailMaxLength() lint.LintInterface { + return &subjectEmailMaxLength{} } func (l *subjectEmailMaxLength) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_empty_without_san.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_empty_without_san.go index 17649ea5a..ff830bf49 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_empty_without_san.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_empty_without_san.go @@ -42,12 +42,12 @@ func init() { Citation: "RFC 5280: 4.2 & 4.2.1.6", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &emptyWithoutSAN{}, + Lint: NewEmptyWithoutSAN, }) } -func (l *emptyWithoutSAN) Initialize() error { - return nil +func NewEmptyWithoutSAN() lint.LintInterface { + return &emptyWithoutSAN{} } func (l *emptyWithoutSAN) CheckApplies(cert *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_given_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_given_name_max_length.go index 2de691db6..1c06daf54 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_given_name_max_length.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_given_name_max_length.go @@ -26,25 +26,42 @@ type subjectGivenNameMaxLength struct{} /************************************************ RFC 5280: A.1 - * In this Appendix, there is a list of upperbounds - for fields in a x509 Certificate. * - ub-given-name-length INTEGER ::= 16 +-- Naming attributes of type X520name +id-at-givenName AttributeType ::= { id-at 42 } + +-- Naming attributes of type X520Name: +-- X520name ::= DirectoryString (SIZE (1..ub-name)) +-- +-- Expanded to avoid parameterized type: +X520name ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-name)), + printableString PrintableString (SIZE (1..ub-name)), + universalString UniversalString (SIZE (1..ub-name)), + utf8String UTF8String (SIZE (1..ub-name)), + bmpString BMPString (SIZE (1..ub-name)) } + +-- specifications of Upper Bounds MUST be regarded as mandatory +-- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter +-- Upper Bounds + +-- Upper Bounds +ub-name INTEGER ::= 32768 ************************************************/ func init() { lint.RegisterLint(&lint.Lint{ Name: "e_subject_given_name_max_length", - Description: "The 'GivenName' field of the subject MUST be less than 17 characters", + Description: "The 'GivenName' field of the subject MUST be less than 32769 characters", Citation: "RFC 5280: A.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectGivenNameMaxLength{}, + Lint: NewSubjectGivenNameMaxLength, }) } -func (l *subjectGivenNameMaxLength) Initialize() error { - return nil +func NewSubjectGivenNameMaxLength() lint.LintInterface { + return &subjectGivenNameMaxLength{} } func (l *subjectGivenNameMaxLength) CheckApplies(c *x509.Certificate) bool { @@ -52,11 +69,11 @@ func (l *subjectGivenNameMaxLength) CheckApplies(c *x509.Certificate) bool { } func (l *subjectGivenNameMaxLength) Execute(c *x509.Certificate) *lint.LintResult { - for _, j := range c.Subject.GivenName { - if utf8.RuneCountInString(j) > 16 { + for _, givenName := range c.Subject.GivenName { + characters := utf8.RuneCountInString(givenName) + if characters > 32768 { return &lint.LintResult{Status: lint.Error} } } - return &lint.LintResult{Status: lint.Pass} } diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_given_name_recommended_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_given_name_recommended_max_length.go new file mode 100644 index 000000000..1c6cb2c08 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_given_name_recommended_max_length.go @@ -0,0 +1,62 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +/************************************************ +RFC 5280: A.1 +-- specifications of Upper Bounds MUST be regarded as mandatory +-- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter +-- Upper Bounds +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_subject_given_name_recommended_max_length", + Description: "X.411 (1988) describes ub-common-name-length to be 64 bytes long. As systems may have " + + "targeted this length, for compatibility purposes it may be prudent to limit given names to this length.", + Citation: "ITU-T Rec. X.411 (11/1988), Annex B Reference Definition of MTS Parameter Upper Bounds", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: NewSubjectGivenNameRecommendedMaxLength, + }) +} + +func NewSubjectGivenNameRecommendedMaxLength() lint.LintInterface { + return &SubjectGivenNameRecommendedMaxLength{} +} + +type SubjectGivenNameRecommendedMaxLength struct{} + +func (l *SubjectGivenNameRecommendedMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *SubjectGivenNameRecommendedMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + for _, givenName := range c.Subject.GivenName { + characters := utf8.RuneCountInString(givenName) + if characters > 64 { + return &lint.LintResult{Status: lint.Warn} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_info_access_marked_critical.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_info_access_marked_critical.go index 9cc46945b..8e5ef2e04 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_info_access_marked_critical.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_info_access_marked_critical.go @@ -33,12 +33,12 @@ func init() { Citation: "RFC 5280: 4.2.2.2", Source: lint.RFC5280, EffectiveDate: util.RFC3280Date, - Lint: &siaCrit{}, + Lint: NewSiaCrit, }) } -func (l *siaCrit) Initialize() error { - return nil +func NewSiaCrit() lint.LintInterface { + return &siaCrit{} } func (l *siaCrit) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_locality_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_locality_name_max_length.go index 7268f3f01..d9a95bd2b 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_locality_name_max_length.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_locality_name_max_length.go @@ -38,12 +38,12 @@ func init() { Citation: "RFC 5280: A.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectLocalityNameMaxLength{}, + Lint: NewSubjectLocalityNameMaxLength, }) } -func (l *subjectLocalityNameMaxLength) Initialize() error { - return nil +func NewSubjectLocalityNameMaxLength() lint.LintInterface { + return &subjectLocalityNameMaxLength{} } func (l *subjectLocalityNameMaxLength) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_not_dn.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_not_dn.go index e0ad56e57..53b8cae94 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_not_dn.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_not_dn.go @@ -41,12 +41,12 @@ func init() { Citation: "RFC 5280: 4.1.2.6", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectDN{}, + Lint: NewSubjectDN, }) } -func (l *subjectDN) Initialize() error { - return nil +func NewSubjectDN() lint.LintInterface { + return &subjectDN{} } func (l *subjectDN) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organization_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organization_name_max_length.go index 7a18e338d..32bef29b9 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organization_name_max_length.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organization_name_max_length.go @@ -38,12 +38,12 @@ func init() { Citation: "RFC 5280: A.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectOrganizationNameMaxLength{}, + Lint: NewSubjectOrganizationNameMaxLength, }) } -func (l *subjectOrganizationNameMaxLength) Initialize() error { - return nil +func NewSubjectOrganizationNameMaxLength() lint.LintInterface { + return &subjectOrganizationNameMaxLength{} } func (l *subjectOrganizationNameMaxLength) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organizational_unit_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organizational_unit_name_max_length.go index 2b7a0b659..33704853d 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organizational_unit_name_max_length.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_organizational_unit_name_max_length.go @@ -38,12 +38,12 @@ func init() { Citation: "RFC 5280: A.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectOrganizationalUnitNameMaxLength{}, + Lint: NewSubjectOrganizationalUnitNameMaxLength, }) } -func (l *subjectOrganizationalUnitNameMaxLength) Initialize() error { - return nil +func NewSubjectOrganizationalUnitNameMaxLength() lint.LintInterface { + return &subjectOrganizationalUnitNameMaxLength{} } func (l *subjectOrganizationalUnitNameMaxLength) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_postal_code_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_postal_code_max_length.go index f23770dfd..62837d2b4 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_postal_code_max_length.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_postal_code_max_length.go @@ -39,12 +39,12 @@ func init() { Citation: "RFC 5280: A.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectPostalCodeMaxLength{}, + Lint: NewSubjectPostalCodeMaxLength, }) } -func (l *subjectPostalCodeMaxLength) Initialize() error { - return nil +func NewSubjectPostalCodeMaxLength() lint.LintInterface { + return &subjectPostalCodeMaxLength{} } func (l *subjectPostalCodeMaxLength) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_printable_string_badalpha.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_printable_string_badalpha.go index 801fa92fc..b54b5b7a5 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_printable_string_badalpha.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_printable_string_badalpha.go @@ -15,16 +15,31 @@ package rfc import ( - "encoding/asn1" "errors" "fmt" "regexp" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" ) +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_subject_printable_string_badalpha", + Description: "PrintableString type's alphabet only includes a-z, A-Z, 0-9, and 11 special characters", + Citation: "RFC 5280: Appendix B. ASN.1 Notes", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: NewSubjectPrintableStringBadAlpha, + }) +} + +func NewSubjectPrintableStringBadAlpha() lint.LintInterface { + return &subjectPrintableStringBadAlpha{} +} + var ( // Per RFC 5280, Appendix B. ASN.1 Notes: // The character string type PrintableString supports a very basic Latin @@ -46,21 +61,6 @@ func validatePrintableString(rawPS []byte) error { type subjectPrintableStringBadAlpha struct { } -func init() { - lint.RegisterLint(&lint.Lint{ - Name: "e_subject_printable_string_badalpha", - Description: "PrintableString type's alphabet only includes a-z, A-Z, 0-9, and 11 special characters", - Citation: "RFC 5280: Appendix B. ASN.1 Notes", - Source: lint.RFC5280, - EffectiveDate: util.RFC2459Date, - Lint: &subjectPrintableStringBadAlpha{}, - }) -} - -func (l *subjectPrintableStringBadAlpha) Initialize() error { - return nil -} - // CheckApplies returns true for any certificate with a non-empty RawSubject. func (l *subjectPrintableStringBadAlpha) CheckApplies(c *x509.Certificate) bool { return len(c.RawSubject) > 0 diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_state_name_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_state_name_max_length.go index 172aea8a3..479e0d0e5 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_state_name_max_length.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_state_name_max_length.go @@ -38,12 +38,12 @@ func init() { Citation: "RFC 5280: A.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectStateNameMaxLength{}, + Lint: NewSubjectStateNameMaxLength, }) } -func (l *subjectStateNameMaxLength) Initialize() error { - return nil +func NewSubjectStateNameMaxLength() lint.LintInterface { + return &subjectStateNameMaxLength{} } func (l *subjectStateNameMaxLength) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_street_address_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_street_address_max_length.go index 5459853e5..8b003fd56 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_street_address_max_length.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_street_address_max_length.go @@ -37,12 +37,12 @@ func init() { Citation: "ITU-T X.520 (02/2001) UpperBounds", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectStreetAddressMaxLength{}, + Lint: NewSubjectStreetAddressMaxLength, }) } -func (l *subjectStreetAddressMaxLength) Initialize() error { - return nil +func NewSubjectStreetAddressMaxLength() lint.LintInterface { + return &subjectStreetAddressMaxLength{} } func (l *subjectStreetAddressMaxLength) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_surname_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_surname_max_length.go index 0053127da..4dfa67a82 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_surname_max_length.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_surname_max_length.go @@ -26,25 +26,42 @@ type subjectSurnameMaxLength struct{} /************************************************ RFC 5280: A.1 - * In this Appendix, there is a list of upperbounds - for fields in a x509 Certificate. * - ub-surname-length INTEGER ::= 40 +-- Naming attributes of type X520name +id-at-surname AttributeType ::= { id-at 4 } + +-- Naming attributes of type X520Name: +-- X520name ::= DirectoryString (SIZE (1..ub-name)) +-- +-- Expanded to avoid parameterized type: +X520name ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-name)), + printableString PrintableString (SIZE (1..ub-name)), + universalString UniversalString (SIZE (1..ub-name)), + utf8String UTF8String (SIZE (1..ub-name)), + bmpString BMPString (SIZE (1..ub-name)) } + +-- specifications of Upper Bounds MUST be regarded as mandatory +-- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter +-- Upper Bounds + +-- Upper Bounds +ub-name INTEGER ::= 32768 ************************************************/ func init() { lint.RegisterLint(&lint.Lint{ Name: "e_subject_surname_max_length", - Description: "The 'Surname' field of the subject MUST be less than 41 characters", + Description: "The 'Surname' field of the subject MUST be less than 32769 characters", Citation: "RFC 5280: A.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &subjectSurnameMaxLength{}, + Lint: NewSubjectSurnameMaxLength, }) } -func (l *subjectSurnameMaxLength) Initialize() error { - return nil +func NewSubjectSurnameMaxLength() lint.LintInterface { + return &subjectSurnameMaxLength{} } func (l *subjectSurnameMaxLength) CheckApplies(c *x509.Certificate) bool { @@ -52,11 +69,11 @@ func (l *subjectSurnameMaxLength) CheckApplies(c *x509.Certificate) bool { } func (l *subjectSurnameMaxLength) Execute(c *x509.Certificate) *lint.LintResult { - for _, j := range c.Subject.Surname { - if utf8.RuneCountInString(j) > 40 { + for _, surname := range c.Subject.Surname { + characters := utf8.RuneCountInString(surname) + if characters > 32768 { return &lint.LintResult{Status: lint.Error} } } - return &lint.LintResult{Status: lint.Pass} } diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_surname_recommended_max_length.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_surname_recommended_max_length.go new file mode 100644 index 000000000..8d40faed3 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_subject_surname_recommended_max_length.go @@ -0,0 +1,62 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "unicode/utf8" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +/************************************************ +RFC 5280: A.1 +-- specifications of Upper Bounds MUST be regarded as mandatory +-- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter +-- Upper Bounds +************************************************/ + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "w_subject_surname_recommended_max_length", + Description: "X.411 (1988) describes ub-common-name-length to be 64 bytes long. As systems may have " + + "targeted this length, for compatibility purposes it may be prudent to limit surnames to this length.", + Citation: "ITU-T Rec. X.411 (11/1988), Annex B Reference Definition of MTS Parameter Upper Bounds", + Source: lint.RFC5280, + EffectiveDate: util.RFC2459Date, + Lint: NewSubjectSurnameRecommendedMaxLength, + }) +} + +func NewSubjectSurnameRecommendedMaxLength() lint.LintInterface { + return &SubjectSurnameRecommendedMaxLength{} +} + +type SubjectSurnameRecommendedMaxLength struct{} + +func (l *SubjectSurnameRecommendedMaxLength) CheckApplies(c *x509.Certificate) bool { + return true +} + +func (l *SubjectSurnameRecommendedMaxLength) Execute(c *x509.Certificate) *lint.LintResult { + for _, givenName := range c.Subject.Surname { + characters := utf8.RuneCountInString(givenName) + if characters > 64 { + return &lint.LintResult{Status: lint.Warn} + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_superfluous_ku_encoding.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_superfluous_ku_encoding.go new file mode 100644 index 000000000..72ef76df7 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_superfluous_ku_encoding.go @@ -0,0 +1,61 @@ +/* + * ZLint Copyright 2022 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package rfc + +import ( + "fmt" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "e_superfluous_ku_encoding", + Description: "RFC 5280 Section 4.2.1.3 describes the value of a KeyUsage to be a DER encoded BitString, which itself must not have unnecessary trailing 00 bytes.", + Citation: "1.2.2 Where Rec. ITU-T X.680 | ISO/IEC 8824-1, 22.7, applies, the bitstring shall have all trailing 0 bits removed before it is encoded.", + Source: lint.RFC5280, + EffectiveDate: util.ZeroDate, + Lint: func() lint.LintInterface { return &superfluousKuEncoding{} }, + }) +} + +type superfluousKuEncoding struct{} + +func NewSuperfluousKuEncoding() lint.LintInterface { + return &superfluousKuEncoding{} +} + +func (l *superfluousKuEncoding) CheckApplies(c *x509.Certificate) bool { + ku := util.GetExtFromCert(c, util.KeyUsageOID) + return ku != nil && len(ku.Value) > 0 +} + +func (l *superfluousKuEncoding) Execute(c *x509.Certificate) *lint.LintResult { + ku := util.GetExtFromCert(c, util.KeyUsageOID).Value + if ku[len(ku)-1] != 0 { + return &lint.LintResult{Status: lint.Pass} + } + binary := make([]string, len(ku)) + for i, b := range ku { + binary[i] = fmt.Sprintf("%08b", b) + } + // E.G. KeyUsage contains superfluous trailing 00 byte. Bytes: [3 3 7 6 0], Binary: [00000011 00000011 00000111 00000110 00000000] + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf( + "KeyUsage contains superfluous trailing 00 byte. Bytes: %v, Binary: [%s]", ku, strings.Join(binary, " "), + )} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_alg_matches_cert_signature_alg.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_alg_matches_cert_signature_alg.go index 28a8aa586..e0e9b857e 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_alg_matches_cert_signature_alg.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_alg_matches_cert_signature_alg.go @@ -40,12 +40,12 @@ func init() { Citation: "RFC 5280, Section 4.1.1.2", Source: lint.RFC5280, EffectiveDate: util.RFC5280Date, - Lint: &mismatchingSigAlg{}, + Lint: NewMismatchingSigAlg, }) } -func (l *mismatchingSigAlg) Initialize() error { - return nil +func NewMismatchingSigAlg() lint.LintInterface { + return &mismatchingSigAlg{} } func (l *mismatchingSigAlg) CheckApplies(_ *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_rsa_encryption_parameter_not_null.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_rsa_encryption_parameter_not_null.go index f80bb6a6a..58c5359f5 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_rsa_encryption_parameter_not_null.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_tbs_signature_rsa_encryption_parameter_not_null.go @@ -38,12 +38,12 @@ func init() { Citation: "RFC 4055, Section 5", Source: lint.RFC5280, // RFC4055 is referenced in RFC5280, Section 1 EffectiveDate: util.RFC5280Date, - Lint: &rsaTBSSignatureEncryptionParamNotNULL{}, + Lint: NewRsaTBSSignatureEncryptionParamNotNULL, }) } -func (l *rsaTBSSignatureEncryptionParamNotNULL) Initialize() error { - return nil +func NewRsaTBSSignatureEncryptionParamNotNULL() lint.LintInterface { + return &rsaTBSSignatureEncryptionParamNotNULL{} } func (l *rsaTBSSignatureEncryptionParamNotNULL) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_does_not_include_seconds.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_does_not_include_seconds.go index 851d247b9..c8cd431d1 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_does_not_include_seconds.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_does_not_include_seconds.go @@ -47,12 +47,12 @@ func init() { Citation: "RFC 5280: 4.1.2.5.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &utcNoSecond{}, + Lint: NewUtcNoSecond, }) } -func (l *utcNoSecond) Initialize() error { - return nil +func NewUtcNoSecond() lint.LintInterface { + return &utcNoSecond{} } func (l *utcNoSecond) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_not_in_zulu.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_not_in_zulu.go index 648f78256..bc39becb2 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_not_in_zulu.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_utc_time_not_in_zulu.go @@ -50,12 +50,12 @@ func init() { Citation: "RFC 5280: 4.1.2.5.1", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &utcTimeGMT{}, + Lint: NewUtcTimeGMT, }) } -func (l *utcTimeGMT) Initialize() error { - return nil +func NewUtcTimeGMT() lint.LintInterface { + return &utcTimeGMT{} } func (l *utcTimeGMT) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_wrong_time_format_pre2050.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_wrong_time_format_pre2050.go index 3edaaf2bb..5bd27fa39 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_wrong_time_format_pre2050.go +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_wrong_time_format_pre2050.go @@ -15,9 +15,9 @@ package rfc */ import ( - "encoding/asn1" "time" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" @@ -40,12 +40,12 @@ func init() { Citation: "RFC 5280: 4.1.2.5", Source: lint.RFC5280, EffectiveDate: util.RFC2459Date, - Lint: &generalizedPre2050{}, + Lint: NewGeneralizedPre2050, }) } -func (l *generalizedPre2050) Initialize() error { - return nil +func NewGeneralizedPre2050() lint.LintInterface { + return &generalizedPre2050{} } func (l *generalizedPre2050) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/makefile b/vendor/github.com/zmap/zlint/v3/makefile index 6fb343ddb..8943a8d57 100644 --- a/vendor/github.com/zmap/zlint/v3/makefile +++ b/vendor/github.com/zmap/zlint/v3/makefile @@ -10,11 +10,13 @@ PARALLELISM := 5 # make integration INT_FLAGS="-includeSources='Mozilla,ETSI_ESI' -config small.config.json" INT_FLAGS := +GIT_VERSION := "$(shell git describe --abbrev=8)" + CMDS = zlint zlint-gtld-update CMD_PREFIX = ./cmd/ -BUILD = $(GO_ENV) go build +BUILD = $(GO_ENV) go build --ldflags="-X 'main.version=$(GIT_VERSION)'" TEST = $(GO_ENV) GORACE=halt_on_error=1 go test -race -INT_TEST = $(GO_ENV) go test -v -tags integration -timeout 20m ./integration/... -parallelism $(PARALLELISM) $(INT_FLAGS) +INT_TEST = $(GO_ENV) go test -v -tags integration -timeout 20m ./integration/. -parallelism $(PARALLELISM) $(INT_FLAGS) all: $(CMDS) @@ -34,9 +36,15 @@ integration: $(INT_TEST) code-lint: - golangci-lint run + # Skip these two directories as they contain Go files that are tests for custom + # code linting framework and there is no expectation of those files conforming to anything. + golangci-lint run --skip-dirs lints/lints/testdata/,lints/testdata + +custom-code-lint: + (cd integration/lints/ && go run main.go ../../lints) + (cd integration/lints/ && go run main.go ../../cmd/genTestCerts) testdata-lint: ./test/prepend_testcerts_openssl.sh && git diff --exit-code testdata/ -.PHONY: clean zlint zlint-gtld-update test integration code-lint testdata-lint +.PHONY: clean zlint zlint-gtld-update test integration code-lint testdata-lint custom-code-lint diff --git a/vendor/github.com/zmap/zlint/v3/newLint.sh b/vendor/github.com/zmap/zlint/v3/newLint.sh index 9bfd13ad7..fde173dc4 100644 --- a/vendor/github.com/zmap/zlint/v3/newLint.sh +++ b/vendor/github.com/zmap/zlint/v3/newLint.sh @@ -44,6 +44,7 @@ FILENAME=${LINTNAME:2} STRUCTNAME=$3 sed -e "s/PACKAGE/${PATHNAME}/" \ + -e "s/PASCAL_CASE_SUBST/${STRUCTNAME^}/g" \ -e "s/SUBST/${STRUCTNAME}/g" \ -e "s/SUBTEST/${LINTNAME}/g" template > lints/${PATHNAME}/lint_${FILENAME}.go diff --git a/vendor/github.com/zmap/zlint/v3/resultset.go b/vendor/github.com/zmap/zlint/v3/resultset.go index f1e4db3c9..0fb3c7594 100644 --- a/vendor/github.com/zmap/zlint/v3/resultset.go +++ b/vendor/github.com/zmap/zlint/v3/resultset.go @@ -38,7 +38,7 @@ func (z *ResultSet) execute(cert *x509.Certificate, registry lint.Registry) { z.Results = make(map[string]*lint.LintResult, len(registry.Names())) // Run each lints from the registry. for _, name := range registry.Names() { - res := registry.ByName(name).Execute(cert) + res := registry.ByName(name).Execute(cert, registry.GetConfiguration()) z.Results[name] = res z.updateErrorStatePresent(res) } diff --git a/vendor/github.com/zmap/zlint/v3/template b/vendor/github.com/zmap/zlint/v3/template index 77311118c..1ae2a6738 100644 --- a/vendor/github.com/zmap/zlint/v3/template +++ b/vendor/github.com/zmap/zlint/v3/template @@ -16,13 +16,24 @@ package PACKAGE import ( "github.com/zmap/zcrypto/x509" - "github.com/zmap/zlint/v2/lint" + "github.com/zmap/zlint/v3/lint" ) +func init() { + lint.RegisterLint(&lint.Lint{ + Name: "SUBTEST", + Description: "Fill this in...", + Citation: "Fill this in...", + Source: UnknownLintSource, + EffectiveDate: "Change this...", + Lint: func() lint.LintInterface { return &SUBST{} }, + }) +} + type SUBST struct{} -func (l *SUBST) Initialize() error { - return nil +func NewPASCAL_CASE_SUBST() lint.LintInterface { + return &SUBST{} } func (l *SUBST) CheckApplies(c *x509.Certificate) bool { @@ -32,14 +43,3 @@ func (l *SUBST) CheckApplies(c *x509.Certificate) bool { func (l *SUBST) Execute(c *x509.Certificate) *lint.LintResult { // Add actual lint here } - -func init() { - lint.RegisterLint(&lint.Lint{ - Name: "SUBTEST", - Description: "Fill this in...", - Citation: "Fill this in...", - Source: UnknownLintSource, - EffectiveDate: "Change this...", - Lint: &SUBST{}, - }) -} diff --git a/vendor/github.com/zmap/zlint/v3/util/algorithm_identifier.go b/vendor/github.com/zmap/zlint/v3/util/algorithm_identifier.go index 07df3a4e9..cb6d2f0f4 100644 --- a/vendor/github.com/zmap/zlint/v3/util/algorithm_identifier.go +++ b/vendor/github.com/zmap/zlint/v3/util/algorithm_identifier.go @@ -2,13 +2,13 @@ package util import ( "bytes" - "encoding/asn1" "errors" "fmt" + "github.com/zmap/zcrypto/cryptobyte" + cryptobyte_asn1 "github.com/zmap/zcrypto/cryptobyte/asn1" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" - "golang.org/x/crypto/cryptobyte" - cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" ) // additional OIDs not provided by the x509 package. @@ -39,6 +39,7 @@ var RSAAlgorithmIDToDER = map[string][]byte{ // CheckAlgorithmIDParamNotNULL parses an AlgorithmIdentifier with algorithm OID rsaEncryption to check the Param field is asn1.NULL // Expects DER-encoded AlgorithmIdentifier including tag and length. +//nolint:cyclop func CheckAlgorithmIDParamNotNULL(algorithmIdentifier []byte, requiredAlgoID asn1.ObjectIdentifier) error { expectedAlgoIDBytes, ok := RSAAlgorithmIDToDER[requiredAlgoID.String()] if !ok { diff --git a/vendor/github.com/zmap/zlint/v3/util/encodings.go b/vendor/github.com/zmap/zlint/v3/util/encodings.go index fc28c350f..80efdbb4f 100644 --- a/vendor/github.com/zmap/zlint/v3/util/encodings.go +++ b/vendor/github.com/zmap/zlint/v3/util/encodings.go @@ -16,13 +16,13 @@ package util import ( "bytes" - "encoding/asn1" "errors" "regexp" "strings" "unicode" "unicode/utf16" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509/pkix" ) diff --git a/vendor/github.com/zmap/zlint/v3/util/ev.go b/vendor/github.com/zmap/zlint/v3/util/ev.go index 68ef5df3a..d5b0abb72 100644 --- a/vendor/github.com/zmap/zlint/v3/util/ev.go +++ b/vendor/github.com/zmap/zlint/v3/util/ev.go @@ -15,10 +15,11 @@ package util import ( - "encoding/asn1" + "github.com/zmap/zcrypto/encoding/asn1" ) var evoids = map[string]bool{ + "2.23.140.1.1": true, "1.3.159.1.17.1": true, "1.3.6.1.4.1.34697.2.1": true, "1.3.6.1.4.1.34697.2.2": true, diff --git a/vendor/github.com/zmap/zlint/v3/util/gtld_map.go b/vendor/github.com/zmap/zlint/v3/util/gtld_map.go index 7137627d4..9a5f1713c 100644 --- a/vendor/github.com/zmap/zlint/v3/util/gtld_map.go +++ b/vendor/github.com/zmap/zlint/v3/util/gtld_map.go @@ -156,7 +156,7 @@ var tldMap = map[string]GTLDPeriod{ "afamilycompany": { GTLD: "afamilycompany", DelegationDate: "2016-07-31", - RemovalDate: "", + RemovalDate: "2021-12-03", }, "afl": { GTLD: "afl", @@ -936,7 +936,7 @@ var tldMap = map[string]GTLDPeriod{ "budapest": { GTLD: "budapest", DelegationDate: "2014-09-23", - RemovalDate: "", + RemovalDate: "2022-02-17", }, "bugatti": { GTLD: "bugatti", @@ -1041,7 +1041,7 @@ var tldMap = map[string]GTLDPeriod{ "cancerresearch": { GTLD: "cancerresearch", DelegationDate: "2014-07-03", - RemovalDate: "", + RemovalDate: "2022-10-05", }, "canon": { GTLD: "canon", @@ -1116,7 +1116,7 @@ var tldMap = map[string]GTLDPeriod{ "caseih": { GTLD: "caseih", DelegationDate: "2016-10-30", - RemovalDate: "", + RemovalDate: "2021-02-19", }, "cash": { GTLD: "cash", @@ -1581,7 +1581,7 @@ var tldMap = map[string]GTLDPeriod{ "csc": { GTLD: "csc", DelegationDate: "2015-09-01", - RemovalDate: "", + RemovalDate: "2022-02-01", }, "cu": { GTLD: "cu", @@ -1891,7 +1891,7 @@ var tldMap = map[string]GTLDPeriod{ "duck": { GTLD: "duck", DelegationDate: "2016-07-21", - RemovalDate: "", + RemovalDate: "2021-12-03", }, "dunlop": { GTLD: "dunlop", @@ -2416,7 +2416,7 @@ var tldMap = map[string]GTLDPeriod{ "fujixerox": { GTLD: "fujixerox", DelegationDate: "2016-07-15", - RemovalDate: "", + RemovalDate: "2021-03-26", }, "fun": { GTLD: "fun", @@ -2591,7 +2591,7 @@ var tldMap = map[string]GTLDPeriod{ "glade": { GTLD: "glade", DelegationDate: "2016-07-28", - RemovalDate: "", + RemovalDate: "2021-12-03", }, "glass": { GTLD: "glass", @@ -3276,7 +3276,7 @@ var tldMap = map[string]GTLDPeriod{ "iveco": { GTLD: "iveco", DelegationDate: "2016-10-30", - RemovalDate: "", + RemovalDate: "2021-04-21", }, "iwc": { GTLD: "iwc", @@ -3458,6 +3458,11 @@ var tldMap = map[string]GTLDPeriod{ DelegationDate: "2015-09-26", RemovalDate: "", }, + "kids": { + GTLD: "kids", + DelegationDate: "2022-04-04", + RemovalDate: "", + }, "kim": { GTLD: "kim", DelegationDate: "2014-01-23", @@ -3786,7 +3791,7 @@ var tldMap = map[string]GTLDPeriod{ "lixil": { GTLD: "lixil", DelegationDate: "2015-07-30", - RemovalDate: "", + RemovalDate: "2021-12-29", }, "lk": { GTLD: "lk", @@ -4338,6 +4343,11 @@ var tldMap = map[string]GTLDPeriod{ DelegationDate: "2001-11-01", RemovalDate: "", }, + "music": { + GTLD: "music", + DelegationDate: "2021-10-29", + RemovalDate: "", + }, "mutual": { GTLD: "mutual", DelegationDate: "2016-04-05", @@ -4401,7 +4411,7 @@ var tldMap = map[string]GTLDPeriod{ "nationwide": { GTLD: "nationwide", DelegationDate: "2016-07-15", - RemovalDate: "", + RemovalDate: "2021-04-16", }, "natura": { GTLD: "natura", @@ -4466,7 +4476,7 @@ var tldMap = map[string]GTLDPeriod{ "newholland": { GTLD: "newholland", DelegationDate: "2016-10-30", - RemovalDate: "", + RemovalDate: "2021-02-19", }, "news": { GTLD: "news", @@ -4641,7 +4651,7 @@ var tldMap = map[string]GTLDPeriod{ "off": { GTLD: "off", DelegationDate: "2016-07-21", - RemovalDate: "", + RemovalDate: "2021-12-03", }, "office": { GTLD: "office", @@ -4706,7 +4716,7 @@ var tldMap = map[string]GTLDPeriod{ "onyourside": { GTLD: "onyourside", DelegationDate: "2016-07-15", - RemovalDate: "", + RemovalDate: "2021-04-16", }, "ooo": { GTLD: "ooo", @@ -5161,7 +5171,7 @@ var tldMap = map[string]GTLDPeriod{ "qvc": { GTLD: "qvc", DelegationDate: "2016-08-04", - RemovalDate: "", + RemovalDate: "2021-10-07", }, "racing": { GTLD: "racing", @@ -5176,7 +5186,7 @@ var tldMap = map[string]GTLDPeriod{ "raid": { GTLD: "raid", DelegationDate: "2016-07-21", - RemovalDate: "", + RemovalDate: "2021-12-03", }, "re": { GTLD: "re", @@ -5341,7 +5351,7 @@ var tldMap = map[string]GTLDPeriod{ "rmit": { GTLD: "rmit", DelegationDate: "2016-11-24", - RemovalDate: "", + RemovalDate: "2021-09-27", }, "ro": { GTLD: "ro", @@ -5576,7 +5586,7 @@ var tldMap = map[string]GTLDPeriod{ "scjohnson": { GTLD: "scjohnson", DelegationDate: "2016-07-21", - RemovalDate: "", + RemovalDate: "2021-12-03", }, "scor": { GTLD: "scor", @@ -5916,7 +5926,7 @@ var tldMap = map[string]GTLDPeriod{ "spreadbetting": { GTLD: "spreadbetting", DelegationDate: "2015-03-13", - RemovalDate: "", + RemovalDate: "2021-04-21", }, "sr": { GTLD: "sr", @@ -6076,7 +6086,7 @@ var tldMap = map[string]GTLDPeriod{ "swiftcover": { GTLD: "swiftcover", DelegationDate: "2016-07-21", - RemovalDate: "", + RemovalDate: "2021-10-05", }, "swiss": { GTLD: "swiss", @@ -7006,7 +7016,7 @@ var tldMap = map[string]GTLDPeriod{ "xn--3oq18vl8pn36a": { GTLD: "xn--3oq18vl8pn36a", DelegationDate: "2016-08-16", - RemovalDate: "", + RemovalDate: "2021-10-27", }, "xn--3pxu8k": { GTLD: "xn--3pxu8k", @@ -7033,6 +7043,11 @@ var tldMap = map[string]GTLDPeriod{ DelegationDate: "2014-11-17", RemovalDate: "", }, + "xn--4dbrk0ce": { + GTLD: "xn--4dbrk0ce", + DelegationDate: "1985-01-01", + RemovalDate: "", + }, "xn--4gbrim": { GTLD: "xn--4gbrim", DelegationDate: "2014-05-28", diff --git a/vendor/github.com/zmap/zlint/v3/util/idna.go b/vendor/github.com/zmap/zlint/v3/util/idna.go new file mode 100644 index 000000000..5e2543efb --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/idna.go @@ -0,0 +1,60 @@ +/* + * ZLint Copyright 2021 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package util + +import ( + "regexp" + + "golang.org/x/net/idna" +) + +var reservedLabelPrefix = regexp.MustCompile(`^..--`) + +var xnLabelPrefix = regexp.MustCompile(`(?i)^xn--`) + +// HasReservedLabelPrefix checks whether the given string (presumably +// a domain label) has hyphens ("-") as the third and fourth characters. Domain +// labels with hyphens in these positions are considered to be "Reserved Labels" +// per RFC 5890, section 2.3.1. +// (https://datatracker.ietf.org/doc/html/rfc5890#section-2.3.1) +func HasReservedLabelPrefix(s string) bool { + return reservedLabelPrefix.MatchString(s) +} + +// HasXNLabelPrefix checks whether the given string (presumably a +// domain label) is prefixed with the case-insensitive string "xn--" (the +// IDNA ACE prefix). +// +// This check is useful given the bug following bug report for IDNA wherein +// the ACE prefix incorrectly taken to be case-sensitive. +// +// https://github.com/golang/go/issues/48778 +func HasXNLabelPrefix(s string) bool { + return xnLabelPrefix.MatchString(s) +} + +// IdnaToUnicode is a wrapper around idna.ToUnicode. +// +// If the provided string starts with the IDNA ACE prefix ("xn--", case +// insensitive), then that ACE prefix is coerced to a lowercase "xn--" before +// processing by the idna package. +// +// This is only necessary due to the bug at https://github.com/golang/go/issues/48778 +func IdnaToUnicode(s string) (string, error) { + if HasXNLabelPrefix(s) { + s = "xn--" + s[4:] + } + return idna.ToUnicode(s) +} diff --git a/vendor/github.com/zmap/zlint/v3/util/ku.go b/vendor/github.com/zmap/zlint/v3/util/ku.go index 31a828fb4..529e4c355 100644 --- a/vendor/github.com/zmap/zlint/v3/util/ku.go +++ b/vendor/github.com/zmap/zlint/v3/util/ku.go @@ -16,3 +16,21 @@ var ( x509.KeyUsageDecipherOnly: "KeyUsageDecipherOnly", } ) + +// HasKeyUsageOID returns whether-or-not the OID 2.5.29.15 is present in the given certificate's extensions. +func HasKeyUsageOID(c *x509.Certificate) bool { + return IsExtInCert(c, KeyUsageOID) +} + +// HasKeyUsage returns whether-or-not the given x509.KeyUsage is present within the +// given certificate's KeyUsage bitmap. The certificate, however, is NOT checked for +// whether-or-not it actually has a key usage OID. If you wish to check for the presence +// of the key usage OID, please use HasKeyUsageOID. +func HasKeyUsage(c *x509.Certificate, usage x509.KeyUsage) bool { + return KeyUsageIsPresent(c.KeyUsage, usage) +} + +// KeyUsageIsPresent checks the provided bitmap (keyUsages) for presence of the provided x509.KeyUsage. +func KeyUsageIsPresent(keyUsages x509.KeyUsage, usage x509.KeyUsage) bool { + return keyUsages&usage != 0 +} diff --git a/vendor/github.com/zmap/zlint/v3/util/names.go b/vendor/github.com/zmap/zlint/v3/util/names.go index f8e4936f1..7792f13dc 100644 --- a/vendor/github.com/zmap/zlint/v3/util/names.go +++ b/vendor/github.com/zmap/zlint/v3/util/names.go @@ -15,8 +15,7 @@ package util import ( - "encoding/asn1" - + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509/pkix" ) diff --git a/vendor/github.com/zmap/zlint/v3/util/oid.go b/vendor/github.com/zmap/zlint/v3/util/oid.go index 652bd60d2..a7892b6b4 100644 --- a/vendor/github.com/zmap/zlint/v3/util/oid.go +++ b/vendor/github.com/zmap/zlint/v3/util/oid.go @@ -15,9 +15,9 @@ package util import ( - "encoding/asn1" "errors" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" "github.com/zmap/zcrypto/x509/pkix" ) @@ -110,7 +110,6 @@ func IsExtInCert(cert *x509.Certificate, oid asn1.ObjectIdentifier) bool { // GetExtFromCert returns the extension with the matching OID, if present. If // the extension if not present, it returns nil. -//nolint:interfacer func GetExtFromCert(cert *x509.Certificate, oid asn1.ObjectIdentifier) *pkix.Extension { // Since this function is called by many Lint CheckApplies functions we use // the x509.Certificate.ExtensionsMap field added by zcrypto to check for diff --git a/vendor/github.com/zmap/zlint/v3/util/onion.go b/vendor/github.com/zmap/zlint/v3/util/onion.go new file mode 100644 index 000000000..45cb6013e --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/util/onion.go @@ -0,0 +1,104 @@ +package util + +import ( + "encoding/base32" + "strings" + + "github.com/zmap/zcrypto/x509" +) + +// An onion address is base32 encoded, however Tor believes that the standard base32 encoding +// is lowercase while the Go standard library believes that the standard base32 encoding is uppercase. +// +// onionBase32Encoding is simply base32.StdEncoding but lowercase instead of uppercase in order +// to work with the above mismatch. +var onionBase32Encoding = base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567") + +// IsOnionV3Address returns whether or not the provided DNS name is an Onion V3 encoded address. +// +// In order to be an Onion V3 encoded address, the DNS name must satisfy the following: +// 1. Contain at least two labels. +// 2. The right most label MUST be "onion". +// 3. The second to the right most label MUST be exactly 56 characters long. +// 4. The second to the right most label MUST be base32 encoded against the lowercase standard encoding. +// 5. The final byte of the decoded result from #4 MUST be equal to 0x03. +func IsOnionV3Address(dnsName string) bool { + labels := strings.Split(dnsName, ".") + if len(labels) < 2 || labels[len(labels)-1] != "onion" { + return false + } + address := labels[len(labels)-2] + if len(address) != 56 { + return false + } + raw, err := onionBase32Encoding.DecodeString(address) + if err != nil { + return false + } + return raw[len(raw)-1] == 0x03 +} + +// IsOnionV2Address returns whether-or-not the give address appears to be an Onion V2 address. +// +// In order to be an Onion V2 encoded address, the DNS name must satisfy the following: +// 1. The address has at least two labels. +// 2. The right most label is the .onion TLD. +// 3. The second-to-the-right most label is a 16 character long, base32. +func IsOnionV2Address(dnsName string) bool { + if !strings.HasSuffix(dnsName, "onion") { + return false + } + labels := strings.Split(dnsName, ".") + if len(labels) < 2 { + return false + } + if len(labels[0]) != 16 { + return false + } + _, err := onionBase32Encoding.DecodeString(labels[0]) + if err != nil { + return false + } + return true +} + +// IsOnionV3Cert returns whether-or-not at least one of the provided certificates subject common name, +// or any of its DNS names, are version 3 Onion addresses. +func IsOnionV3Cert(c *x509.Certificate) bool { + return anyAreOnionVX(append(c.DNSNames, c.Subject.CommonName), IsOnionV3Address) +} + +// IsOnionV2Cert returns whether-or-not at least one of the provided certificates subject common name, +// or any of its DNS names, are version 2 Onion addresses. +func IsOnionV2Cert(c *x509.Certificate) bool { + return anyAreOnionVX(append(c.DNSNames, c.Subject.CommonName), IsOnionV2Address) +} + +// anyAreOnionVX returns whether-or-not there is at least one item +// within the given slice that satisfies the given predicate. +// +// An empty slice always returns `false`. +// +// @TODO once we commit to forcing the library users onto Go 1.18 this should migrate to a generic function. +func anyAreOnionVX(slice []string, predicate func(string) bool) bool { + for _, item := range slice { + if predicate(item) { + return true + } + } + return false +} + +// allAreOnionVX returns whether-or-not all items within the given slice +// satisfy the given predicate. +// +// An empty slice always returns `true`. This may seem counterintuitive, +// however it is due to being what is called a "vacuous truth". For +// more information, please see https://en.wikipedia.org/wiki/Vacuous_truth. +// +// @TODO once we commit to forcing the library users onto Go 1.18 this should migrate to a generic function. +func allAreOnionVX(slice []string, predicate func(string) bool) bool { + return !anyAreOnionVX(slice, func(item string) bool { + return !predicate(item) + }) +} diff --git a/vendor/github.com/zmap/zlint/v3/util/qc_stmt.go b/vendor/github.com/zmap/zlint/v3/util/qc_stmt.go index 97af7faf6..3b8183f72 100644 --- a/vendor/github.com/zmap/zlint/v3/util/qc_stmt.go +++ b/vendor/github.com/zmap/zlint/v3/util/qc_stmt.go @@ -16,9 +16,10 @@ package util import ( "bytes" - "encoding/asn1" "fmt" "reflect" + + "github.com/zmap/zcrypto/encoding/asn1" ) type anyContent struct { diff --git a/vendor/github.com/zmap/zlint/v3/util/rdn.go b/vendor/github.com/zmap/zlint/v3/util/rdn.go index cb076a91b..b07a989c6 100644 --- a/vendor/github.com/zmap/zlint/v3/util/rdn.go +++ b/vendor/github.com/zmap/zlint/v3/util/rdn.go @@ -14,7 +14,7 @@ package util -import "encoding/asn1" +import "github.com/zmap/zcrypto/encoding/asn1" type AttributeTypeAndRawValue struct { Type asn1.ObjectIdentifier diff --git a/vendor/github.com/zmap/zlint/v3/util/time.go b/vendor/github.com/zmap/zlint/v3/util/time.go index ba47b2d3b..e3313970e 100644 --- a/vendor/github.com/zmap/zlint/v3/util/time.go +++ b/vendor/github.com/zmap/zlint/v3/util/time.go @@ -1,5 +1,5 @@ /* - * ZLint Copyright 2021 Regents of the University of Michigan + * ZLint Copyright 2022 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -15,9 +15,9 @@ package util import ( - "encoding/asn1" "time" + "github.com/zmap/zcrypto/encoding/asn1" "github.com/zmap/zcrypto/x509" ) @@ -25,6 +25,7 @@ var ( ZeroDate = time.Date(0000, time.January, 1, 0, 0, 0, 0, time.UTC) RFC1035Date = time.Date(1987, time.January, 1, 0, 0, 0, 0, time.UTC) RFC2459Date = time.Date(1999, time.January, 1, 0, 0, 0, 0, time.UTC) + RFC3279Date = time.Date(2002, time.April, 1, 0, 0, 0, 0, time.UTC) RFC3280Date = time.Date(2002, time.April, 1, 0, 0, 0, 0, time.UTC) RFC3490Date = time.Date(2003, time.March, 1, 0, 0, 0, 0, time.UTC) RFC8399Date = time.Date(2018, time.May, 1, 0, 0, 0, 0, time.UTC) @@ -32,6 +33,7 @@ var ( RFC4630Date = time.Date(2006, time.August, 1, 0, 0, 0, 0, time.UTC) RFC5280Date = time.Date(2008, time.May, 1, 0, 0, 0, 0, time.UTC) RFC6818Date = time.Date(2013, time.January, 1, 0, 0, 0, 0, time.UTC) + RFC8813Date = time.Date(2020, time.August, 1, 0, 0, 0, 0, time.UTC) CABEffectiveDate = time.Date(2012, time.July, 1, 0, 0, 0, 0, time.UTC) CABReservedIPDate = time.Date(2016, time.October, 1, 0, 0, 0, 0, time.UTC) CABGivenNameDate = time.Date(2016, time.September, 7, 0, 0, 0, 0, time.UTC) @@ -43,24 +45,33 @@ var ( CABV130Date = time.Date(2015, time.April, 16, 0, 0, 0, 0, time.UTC) CABV131Date = time.Date(2015, time.September, 28, 0, 0, 0, 0, time.UTC) // https://cabforum.org/wp-content/uploads/CA-Browser-Forum-EV-Guidelines-v1.7.0.pdf - CABV170Date = time.Date(2020, time.January, 31, 0, 0, 0, 0, time.UTC) - NO_SHA1 = time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC) - NoRSA1024RootDate = time.Date(2011, time.January, 1, 0, 0, 0, 0, time.UTC) - NoRSA1024Date = time.Date(2014, time.January, 1, 0, 0, 0, 0, time.UTC) - GeneralizedDate = time.Date(2050, time.January, 1, 0, 0, 0, 0, time.UTC) - NoReservedIP = time.Date(2015, time.November, 1, 0, 0, 0, 0, time.UTC) - SubCert39Month = time.Date(2016, time.July, 2, 0, 0, 0, 0, time.UTC) - SubCert825Days = time.Date(2018, time.March, 2, 0, 0, 0, 0, time.UTC) - CABV148Date = time.Date(2017, time.June, 8, 0, 0, 0, 0, time.UTC) - EtsiEn319_412_5_V2_2_1_Date = time.Date(2017, time.November, 1, 0, 0, 0, 0, time.UTC) - OnionOnlyEVDate = time.Date(2015, time.May, 1, 0, 0, 0, 0, time.UTC) - CABV201Date = time.Date(2017, time.July, 28, 0, 0, 0, 0, time.UTC) - AppleCTPolicyDate = time.Date(2018, time.October, 15, 0, 0, 0, 0, time.UTC) - MozillaPolicy22Date = time.Date(2013, time.July, 26, 0, 0, 0, 0, time.UTC) - MozillaPolicy24Date = time.Date(2017, time.February, 28, 0, 0, 0, 0, time.UTC) - MozillaPolicy27Date = time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC) - CABFBRs_1_6_9_Date = time.Date(2020, time.March, 27, 0, 0, 0, 0, time.UTC) - AppleReducedLifetimeDate = time.Date(2020, time.September, 1, 0, 0, 0, 0, time.UTC) + CABV170Date = time.Date(2020, time.January, 31, 0, 0, 0, 0, time.UTC) + NO_SHA1 = time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC) + NoRSA1024RootDate = time.Date(2011, time.January, 1, 0, 0, 0, 0, time.UTC) + NoRSA1024Date = time.Date(2014, time.January, 1, 0, 0, 0, 0, time.UTC) + GeneralizedDate = time.Date(2050, time.January, 1, 0, 0, 0, 0, time.UTC) + NoReservedIP = time.Date(2015, time.November, 1, 0, 0, 0, 0, time.UTC) + SubCert39Month = time.Date(2016, time.July, 2, 0, 0, 0, 0, time.UTC) + SubCert825Days = time.Date(2018, time.March, 2, 0, 0, 0, 0, time.UTC) + CABV148Date = time.Date(2017, time.June, 8, 0, 0, 0, 0, time.UTC) + EtsiEn319_412_5_V2_2_1_Date = time.Date(2017, time.November, 1, 0, 0, 0, 0, time.UTC) + OnionOnlyEVDate = time.Date(2015, time.May, 1, 0, 0, 0, 0, time.UTC) + CABV201Date = time.Date(2017, time.July, 28, 0, 0, 0, 0, time.UTC) + AppleCTPolicyDate = time.Date(2018, time.October, 15, 0, 0, 0, 0, time.UTC) + MozillaPolicy22Date = time.Date(2013, time.July, 26, 0, 0, 0, 0, time.UTC) + MozillaPolicy24Date = time.Date(2017, time.February, 28, 0, 0, 0, 0, time.UTC) + MozillaPolicy241Date = time.Date(2017, time.March, 31, 0, 0, 0, 0, time.UTC) + MozillaPolicy27Date = time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC) + CABFBRs_1_6_2_UnderscorePermissibilitySunsetDate = time.Date(2019, time.April, 1, 0, 0, 0, 0, time.UTC) + CABFBRs_1_6_2_Date = time.Date(2018, time.December, 10, 0, 0, 0, 0, time.UTC) + CABFBRs_1_2_1_Date = time.Date(2015, time.January, 16, 0, 0, 0, 0, time.UTC) + CABFBRs_1_6_9_Date = time.Date(2020, time.March, 27, 0, 0, 0, 0, time.UTC) + CABFBRs_1_7_1_Date = time.Date(2020, time.August, 20, 0, 0, 0, 0, time.UTC) + AppleReducedLifetimeDate = time.Date(2020, time.September, 1, 0, 0, 0, 0, time.UTC) + CABFBRs_1_7_9_Date = time.Date(2021, time.August, 16, 0, 0, 0, 0, time.UTC) + CABFBRs_1_8_0_Date = time.Date(2021, time.August, 25, 0, 0, 0, 0, time.UTC) + NoReservedDomainLabelsDate = time.Date(2021, time.October, 1, 0, 0, 0, 0, time.UTC) + CABFBRs_OU_Prohibited_Date = time.Date(2022, time.September, 1, 0, 0, 0, 0, time.UTC) ) var ( @@ -116,3 +127,13 @@ func GetTimes(cert *x509.Certificate) (asn1.RawValue, asn1.RawValue) { } return firstDate, secondDate } + +// BeforeOrOn returns whether left is before or strictly equal to right. +func BeforeOrOn(left, right time.Time) bool { + return !left.After(right) +} + +// OnOrAfter returns whether left is after or strictly equal to right. +func OnOrAfter(left, right time.Time) bool { + return !left.Before(right) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 32a6fe87a..24f84bc68 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -67,8 +67,6 @@ github.com/jmoiron/sqlx/types # github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46 ## explicit github.com/kisielk/sqlstruct -# github.com/kr/text v0.2.0 -## explicit # github.com/kylelemons/go-gypsy v1.0.0 ## explicit; go 1.5 github.com/kylelemons/go-gypsy/yaml @@ -83,6 +81,9 @@ github.com/mattn/go-sqlite3 # github.com/matttproud/golang_protobuf_extensions v1.0.4 ## explicit; go 1.9 github.com/matttproud/golang_protobuf_extensions/pbutil +# github.com/pelletier/go-toml v1.9.3 +## explicit; go 1.12 +github.com/pelletier/go-toml # github.com/pmezard/go-difflib v1.0.0 ## explicit github.com/pmezard/go-difflib/difflib @@ -111,7 +112,7 @@ github.com/prometheus/procfs/internal/util ## explicit; go 1.13 github.com/stretchr/testify/assert github.com/stretchr/testify/require -# github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b +# github.com/weppos/publicsuffix-go v0.15.1-0.20220329081811-9a40b608a236 ## explicit; go 1.11 github.com/weppos/publicsuffix-go/publicsuffix # github.com/ziutek/mymysql v1.5.4 @@ -119,17 +120,20 @@ github.com/weppos/publicsuffix-go/publicsuffix github.com/ziutek/mymysql/godrv github.com/ziutek/mymysql/mysql github.com/ziutek/mymysql/native -# github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc +# github.com/zmap/zcrypto v0.0.0-20220402174210-599ec18ecbac ## explicit; go 1.16 +github.com/zmap/zcrypto/cryptobyte +github.com/zmap/zcrypto/cryptobyte/asn1 github.com/zmap/zcrypto/dsa +github.com/zmap/zcrypto/encoding/asn1 github.com/zmap/zcrypto/internal/randutil github.com/zmap/zcrypto/json github.com/zmap/zcrypto/util github.com/zmap/zcrypto/x509 github.com/zmap/zcrypto/x509/ct github.com/zmap/zcrypto/x509/pkix -# github.com/zmap/zlint/v3 v3.1.0 -## explicit; go 1.15 +# github.com/zmap/zlint/v3 v3.4.1 +## explicit; go 1.18 github.com/zmap/zlint/v3 github.com/zmap/zlint/v3/lint github.com/zmap/zlint/v3/lints/apple